From 316461c5e1f23aa4f24c25f20230a02ec932f882 Mon Sep 17 00:00:00 2001 From: "Kurt A. O'Hearn" <ohearnku@cse.msu.edu> Date: Fri, 26 Aug 2016 09:50:24 -0400 Subject: [PATCH] sPuReMD: refactor preconditioning application logic. --- sPuReMD/src/GMRES.c | 123 +++++++++++++++++++------------------------- sPuReMD/src/GMRES.h | 4 +- sPuReMD/src/QEq.c | 10 ++-- 3 files changed, 61 insertions(+), 76 deletions(-) diff --git a/sPuReMD/src/GMRES.c b/sPuReMD/src/GMRES.c index c686ce88..5eb2b12d 100644 --- a/sPuReMD/src/GMRES.c +++ b/sPuReMD/src/GMRES.c @@ -573,44 +573,32 @@ static void jacobi_iter( const sparse_matrix * const R, const real * const Dinv, /* Solve triangular system LU*x = y using level scheduling * - * workspace: lower/upper triangular, stored in CSR + * workspace: data struct containing matrices, lower/upper triangular, stored in CSR + * control: data struct containing parameters * y: constants in linear system (RHS) * x: solution - * tri: triangularity of preconditoning factor LU (lower/upper), if using ILU-based - * pc_type: preconditioner computation method used - * pa_type: preconditioner application method to use - * extra: parameter for some application methods, if applicable + * fresh_pre: parameter indicating if this is a newly computed (fresh) preconditioner * * Assumptions: - * LU has non-zero diagonals - * Each row of LU has at least one non-zero (i.e., no rows with all zeros) */ -void apply_preconditioner( const static_storage * const workspace, real * const y, - real * const x, const TRIANGULARITY tri, int pc_type, int pa_type, int extra ) + * Matrices have non-zero diagonals + * Each row of a matrix has at least one non-zero (i.e., no rows with all zeros) */ +void apply_preconditioner( const static_storage * const workspace, const control_params * const control, + real * const y, real * const x, const int fresh_pre ) { int i, si; - sparse_matrix *LU; static real *Dinv_L = NULL, *Dinv_U = NULL; - if ( tri == LOWER ) - { - LU = workspace->L; - } - else - { - LU = workspace->U; - } - - if ( ( pc_type != DIAG_PC || tri != LOWER ) && LU == NULL ) + if ( control->pre_comp_type != DIAG_PC && workspace->L == NULL ) { return; } - switch ( pa_type ) + switch ( control->pre_app_type ) { case NONE_PA: break; case TRI_SOLVE_PA: - switch ( pc_type ) + switch ( control->pre_comp_type ) { case DIAG_PC: diag_pre_app( workspace->Hdia_inv, y, x, workspace->H->n ); @@ -618,14 +606,17 @@ void apply_preconditioner( const static_storage * const workspace, real * const case ICHOLT_PC: case ILU_PAR_PC: case ILUT_PAR_PC: - tri_solve( LU, y, x, tri ); + tri_solve( workspace->L, y, x, LOWER ); + tri_solve( workspace->U, y, x, UPPER ); break; default: + fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" ); + exit( INVALID_INPUT ); break; } break; case TRI_SOLVE_LEVEL_SCHED_PA: - switch ( pc_type ) + switch ( control->pre_comp_type ) { case DIAG_PC: diag_pre_app( workspace->Hdia_inv, y, x, workspace->H->n ); @@ -633,14 +624,17 @@ void apply_preconditioner( const static_storage * const workspace, real * const case ICHOLT_PC: case ILU_PAR_PC: case ILUT_PAR_PC: - tri_solve_level_sched( LU, y, x, tri, extra ); + tri_solve_level_sched( workspace->L, y, x, LOWER, fresh_pre ); + tri_solve_level_sched( workspace->U, y, x, UPPER, fresh_pre ); break; default: + fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" ); + exit( INVALID_INPUT ); break; } break; case JACOBI_ITER_PA: - switch ( pc_type ) + switch ( control->pre_comp_type ) { case DIAG_PC: fprintf( stderr, "Unsupported preconditioner computation/application method combination. Terminating...\n" ); @@ -649,48 +643,45 @@ void apply_preconditioner( const static_storage * const workspace, real * const case ICHOLT_PC: case ILU_PAR_PC: case ILUT_PAR_PC: - if ( tri == LOWER ) + if ( Dinv_L == NULL ) { - if ( Dinv_L == NULL ) + if ( (Dinv_L = (real*) malloc(sizeof(real) * workspace->L->n)) == NULL ) { - if ( (Dinv_L = (real*) malloc(sizeof(real) * LU->n)) == NULL ) - { - fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" ); - exit( INSUFFICIENT_MEMORY ); - } + fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" ); + exit( INSUFFICIENT_MEMORY ); } - - /* construct D^{-1} */ - for ( i = 0; i < LU->n; ++i ) - { - si = LU->start[i + 1] - 1; - Dinv_L[i] = 1. / LU->val[si]; - } - - jacobi_iter( LU, Dinv_L, y, x, tri, extra ); } - else + + /* construct D^{-1}_L */ + for ( i = 0; i < workspace->L->n; ++i ) { - if ( Dinv_U == NULL ) - { - if ( (Dinv_U = (real*) malloc(sizeof(real) * LU->n)) == NULL ) - { - fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" ); - exit( INSUFFICIENT_MEMORY ); - } - } + si = workspace->L->start[i + 1] - 1; + Dinv_L[i] = 1. / workspace->L->val[si]; + } - /* construct D^{-1}_U */ - for ( i = 0; i < LU->n; ++i ) + jacobi_iter( workspace->L, Dinv_L, y, x, LOWER, control->pre_app_jacobi_iters ); + + if ( Dinv_U == NULL ) + { + if ( (Dinv_U = (real*) malloc(sizeof(real) * workspace->U->n)) == NULL ) { - si = LU->start[i]; - Dinv_U[i] = 1. / LU->val[si]; + fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" ); + exit( INSUFFICIENT_MEMORY ); } + } - jacobi_iter( LU, Dinv_U, y, x, tri, extra ); + /* construct D^{-1}_U */ + for ( i = 0; i < workspace->U->n; ++i ) + { + si = workspace->U->start[i]; + Dinv_U[i] = 1. / workspace->U->val[si]; } + + jacobi_iter( workspace->U, Dinv_U, y, x, UPPER, control->pre_app_jacobi_iters ); break; default: + fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" ); + exit( INVALID_INPUT ); break; } break; @@ -708,7 +699,7 @@ void apply_preconditioner( const static_storage * const workspace, real * const /* generalized minimual residual iterative solver for sparse linear systems */ int GMRES( const static_storage * const workspace, const control_params * const control, const sparse_matrix * const H, const real * const b, real tol, real * const x, - const FILE * const fout, real * const time, real * const spmv_time ) + const FILE * const fout, real * const time, real * const spmv_time, const int fresh_pre ) { int i, j, k, itr, N, si; real cc, tmp1, tmp2, temp, bnorm, time_start; @@ -719,8 +710,7 @@ int GMRES( const static_storage * const workspace, const control_params * const if ( control->pre_comp_type == DIAG_PC ) { /* apply precondioner to RHS */ - apply_preconditioner( workspace, workspace->b, workspace->b_prc, LOWER, - control->pre_comp_type, control->pre_app_type, control->pre_app_jacobi_iters ); + apply_preconditioner( workspace, control, workspace->b, workspace->b_prc, fresh_pre ); } /* GMRES outer-loop */ @@ -734,8 +724,7 @@ int GMRES( const static_storage * const workspace, const control_params * const if ( control->pre_comp_type == DIAG_PC ) { time_start = Get_Time( ); - apply_preconditioner( workspace, workspace->b_prm, workspace->b_prm, LOWER, - control->pre_comp_type, control->pre_app_type, control->pre_app_jacobi_iters ); + apply_preconditioner( workspace, control, workspace->b_prm, workspace->b_prm, fresh_pre ); *time += Get_Timing_Info( time_start ); } @@ -752,10 +741,7 @@ int GMRES( const static_storage * const workspace, const control_params * const if ( control->pre_comp_type != DIAG_PC ) { time_start = Get_Time( ); - apply_preconditioner( workspace, workspace->v[0], workspace->v[0], LOWER, - control->pre_comp_type, control->pre_app_type, control->pre_app_jacobi_iters ); - apply_preconditioner( workspace, workspace->v[0], workspace->v[0], UPPER, - control->pre_comp_type, control->pre_app_type, control->pre_app_jacobi_iters ); + apply_preconditioner( workspace, control, workspace->v[0], workspace->v[0], fresh_pre ); *time += Get_Timing_Info( time_start ); } @@ -772,10 +758,7 @@ int GMRES( const static_storage * const workspace, const control_params * const *spmv_time += Get_Timing_Info( time_start ); time_start = Get_Time( ); - apply_preconditioner( workspace, workspace->v[j + 1], workspace->v[j + 1], LOWER, - control->pre_comp_type, control->pre_app_type, control->pre_app_jacobi_iters ); - apply_preconditioner( workspace, workspace->v[j + 1], workspace->v[j + 1], UPPER, - control->pre_comp_type, control->pre_app_type, control->pre_app_jacobi_iters ); + apply_preconditioner( workspace, control, workspace->v[j + 1], workspace->v[j + 1], fresh_pre ); *time += Get_Timing_Info( time_start ); /* apply modified Gram-Schmidt to orthogonalize the new residual */ @@ -883,7 +866,7 @@ int GMRES( const static_storage * const workspace, const control_params * const int GMRES_HouseHolder( const static_storage * const workspace, const control_params * const control, const sparse_matrix * const H, const real * const b, real tol, real * const x, - const FILE * const fout, real * const time, real * const spmv_time ) + const FILE * const fout, real * const time, real * const spmv_time, const int fresh_pre ) { int i, j, k, itr, N; real cc, tmp1, tmp2, temp, bnorm; diff --git a/sPuReMD/src/GMRES.h b/sPuReMD/src/GMRES.h index d6d1c484..4c2d44ad 100644 --- a/sPuReMD/src/GMRES.h +++ b/sPuReMD/src/GMRES.h @@ -26,11 +26,11 @@ int GMRES( const static_storage * const, const control_params * const, const sparse_matrix * const, const real * const, real, real * const, - const FILE * const, real * const, real * const ); + const FILE * const, real * const, real * const, const int ); int GMRES_HouseHolder( const static_storage * const, const control_params * const, const sparse_matrix * const, const real * const, real, real * const, - const FILE * const, real * const, real * const ); + const FILE * const, real * const, real * const, const int ); int CG( static_storage*, sparse_matrix*, real*, real, real*, FILE* ); diff --git a/sPuReMD/src/QEq.c b/sPuReMD/src/QEq.c index 6e6cc539..68d32b7a 100644 --- a/sPuReMD/src/QEq.c +++ b/sPuReMD/src/QEq.c @@ -1635,15 +1635,17 @@ void QEq( reax_system * const system, control_params * const control, simulation { case GMRES_S: matvecs = GMRES( workspace, control, workspace->H, workspace->b_s, control->qeq_solver_q_err, - workspace->s[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv) ); + workspace->s[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv), + (data->step - data->prev_steps) % control->pre_comp_refactor == 0 ); matvecs += GMRES( workspace, control, workspace->H, workspace->b_t, control->qeq_solver_q_err, - workspace->t[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv) ); + workspace->t[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv), 0 ); break; case GMRES_H_S: matvecs = GMRES_HouseHolder( workspace, control, workspace->H, workspace->b_s, control->qeq_solver_q_err, - workspace->s[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv) ); + workspace->s[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv), + (data->step - data->prev_steps) % control->pre_comp_refactor == 0 ); matvecs += GMRES_HouseHolder( workspace, control, workspace->H, workspace->b_t, control->qeq_solver_q_err, - workspace->t[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv) ); + workspace->t[0], out_control->log, &(data->timing.pre_app), &(data->timing.spmv), 0 ); break; case CG_S: matvecs = CG( workspace, workspace->H, workspace->b_s, control->qeq_solver_q_err, -- GitLab