HYPRE_Int hypre_SStructMatvecSetup( void *matvec_vdata, hypre_SStructMatrix *A, hypre_SStructVector *x ) { hypre_SStructMatvecData *matvec_data = matvec_vdata; HYPRE_Int nparts; void **pmatvec_data; hypre_SStructPMatrix *pA; hypre_SStructPVector *px; HYPRE_Int part; nparts = hypre_SStructMatrixNParts(A); pmatvec_data = hypre_TAlloc(void *, nparts); for (part = 0; part < nparts; part++) { hypre_SStructPMatvecCreate(&pmatvec_data[part]); pA = hypre_SStructMatrixPMatrix(A, part); px = hypre_SStructVectorPVector(x, part); hypre_SStructPMatvecSetup(pmatvec_data[part], pA, px); } (matvec_data -> nparts) = nparts; (matvec_data -> pmatvec_data) = pmatvec_data; return hypre_error_flag; }
HYPRE_Int hypre_SStructScale( HYPRE_Complex alpha, hypre_SStructVector *y ) { HYPRE_Int nparts = hypre_SStructVectorNParts(y); HYPRE_Int part; HYPRE_Int y_object_type= hypre_SStructVectorObjectType(y); if (y_object_type == HYPRE_SSTRUCT) { for (part = 0; part < nparts; part++) { hypre_SStructPScale(alpha, hypre_SStructVectorPVector(y, part)); } } else if (y_object_type == HYPRE_PARCSR) { hypre_ParVector *y_par; hypre_SStructVectorConvert(y, &y_par); hypre_ParVectorScale(alpha, y_par); } return hypre_error_flag; }
int hypre_SStructScale( double alpha, hypre_SStructVector *y ) { int ierr = 0; int nparts = hypre_SStructVectorNParts(y); int part; int y_object_type= hypre_SStructVectorObjectType(y); if (y_object_type == HYPRE_SSTRUCT) { for (part = 0; part < nparts; part++) { hypre_SStructPScale(alpha, hypre_SStructVectorPVector(y, part)); } } else if (y_object_type == HYPRE_PARCSR) { hypre_ParVector *y_par; hypre_SStructVectorConvert(y, &y_par); hypre_ParVectorScale(alpha, y_par); } return ierr; }
HYPRE_Int hypre_SStructInnerProd( hypre_SStructVector *x, hypre_SStructVector *y, double *result_ptr ) { HYPRE_Int nparts = hypre_SStructVectorNParts(x); double result; double presult; HYPRE_Int part; HYPRE_Int x_object_type= hypre_SStructVectorObjectType(x); HYPRE_Int y_object_type= hypre_SStructVectorObjectType(y); if (x_object_type != y_object_type) { hypre_error_in_arg(2); hypre_error_in_arg(3); return hypre_error_flag; } result = 0.0; if ( (x_object_type == HYPRE_SSTRUCT) || (x_object_type == HYPRE_STRUCT) ) { for (part = 0; part < nparts; part++) { hypre_SStructPInnerProd(hypre_SStructVectorPVector(x, part), hypre_SStructVectorPVector(y, part), &presult); result += presult; } } else if (x_object_type == HYPRE_PARCSR) { hypre_ParVector *x_par; hypre_ParVector *y_par; hypre_SStructVectorConvert(x, &x_par); hypre_SStructVectorConvert(y, &y_par); result= hypre_ParVectorInnerProd(x_par, y_par); } *result_ptr = result; return hypre_error_flag; }
int hypre_SStructAxpy( double alpha, hypre_SStructVector *x, hypre_SStructVector *y ) { int ierr = 0; int nparts = hypre_SStructVectorNParts(x); int part; int x_object_type= hypre_SStructVectorObjectType(x); int y_object_type= hypre_SStructVectorObjectType(y); if (x_object_type != y_object_type) { printf("vector object types different- cannot compute Axpy\n"); return ierr; } if (x_object_type == HYPRE_SSTRUCT) { for (part = 0; part < nparts; part++) { hypre_SStructPAxpy(alpha, hypre_SStructVectorPVector(x, part), hypre_SStructVectorPVector(y, part)); } } else if (x_object_type == HYPRE_PARCSR) { hypre_ParVector *x_par; hypre_ParVector *y_par; hypre_SStructVectorConvert(x, &x_par); hypre_SStructVectorConvert(y, &y_par); hypre_ParVectorAxpy(alpha, x_par, y_par); } return ierr; }
HYPRE_Int hypre_SStructCopy( hypre_SStructVector *x, hypre_SStructVector *y ) { HYPRE_Int nparts = hypre_SStructVectorNParts(x); HYPRE_Int part; HYPRE_Int x_object_type= hypre_SStructVectorObjectType(x); HYPRE_Int y_object_type= hypre_SStructVectorObjectType(y); if (x_object_type != y_object_type) { hypre_error_in_arg(2); hypre_error_in_arg(3); return hypre_error_flag; } if (x_object_type == HYPRE_SSTRUCT) { for (part = 0; part < nparts; part++) { hypre_SStructPCopy(hypre_SStructVectorPVector(x, part), hypre_SStructVectorPVector(y, part)); } } else if (x_object_type == HYPRE_PARCSR) { hypre_ParVector *x_par; hypre_ParVector *y_par; hypre_SStructVectorConvert(x, &x_par); hypre_SStructVectorConvert(y, &y_par); hypre_ParVectorCopy(x_par, y_par); } return hypre_error_flag; }
HYPRE_Int hypre_SStructOverlapInnerProd( hypre_SStructVector *x, hypre_SStructVector *y, double *result_ptr ) { HYPRE_Int nparts = hypre_SStructVectorNParts(x); double result; double presult; HYPRE_Int part; result = 0.0; for (part = 0; part < nparts; part++) { hypre_SStructPOverlapInnerProd(hypre_SStructVectorPVector(x, part), hypre_SStructVectorPVector(y, part), &presult); result += presult; } *result_ptr = result; return hypre_error_flag; }
HYPRE_Int hypre_SStructVectorSetRandomValues( hypre_SStructVector *vector, HYPRE_Int seed ) { HYPRE_Int ierr = 0; HYPRE_Int nparts = hypre_SStructVectorNParts(vector); hypre_SStructPVector *pvector; HYPRE_Int part; srand( seed ); for (part = 0; part < nparts; part++) { pvector = hypre_SStructVectorPVector(vector, part); seed = rand(); hypre_SStructPVectorSetRandomValues(pvector, seed); } return ierr; }
HYPRE_Int hypre_FacSemiRestrictSetup2( void *fac_restrict_vdata, hypre_SStructVector *r, HYPRE_Int part_crse, HYPRE_Int part_fine, hypre_SStructPVector *rc, hypre_Index rfactors ) { HYPRE_Int ierr = 0; hypre_FacSemiRestrictData2 *fac_restrict_data = fac_restrict_vdata; MPI_Comm comm= hypre_SStructPVectorComm(rc); hypre_CommInfo *comm_info; hypre_CommPkg **interlevel_comm; hypre_SStructPVector *rf= hypre_SStructVectorPVector(r, part_fine); hypre_StructVector *s_rc, *s_cvector; hypre_SStructPGrid *pgrid; hypre_SStructPVector *fgrid_cvectors; hypre_SStructPGrid *fgrid_coarsen; hypre_BoxArrayArray **identity_arrayboxes; hypre_BoxArrayArray **fullwgt_ownboxes; hypre_BoxArrayArray **fullwgt_sendboxes; hypre_BoxArray *boxarray; hypre_BoxArray *tmp_boxarray, *intersect_boxes; HYPRE_Int ***own_cboxnums; hypre_BoxArrayArray **send_boxes, *send_rboxes; HYPRE_Int ***send_processes; HYPRE_Int ***send_remote_boxnums; hypre_BoxArrayArray **recv_boxes, *recv_rboxes; HYPRE_Int ***recv_processes; HYPRE_Int ***recv_remote_boxnums; hypre_BoxManager *boxman; hypre_BoxManEntry **boxman_entries; HYPRE_Int nboxman_entries; hypre_Box box, scaled_box; hypre_Index zero_index, index, ilower, iupper; HYPRE_Int ndim= hypre_SStructVectorNDim(r); HYPRE_Int myproc, proc; HYPRE_Int nvars, vars; HYPRE_Int num_values; HYPRE_Int i, cnt1, cnt2; HYPRE_Int fi, ci; hypre_MPI_Comm_rank(comm, &myproc); hypre_ClearIndex(zero_index); nvars= hypre_SStructPVectorNVars(rc); (fac_restrict_data -> nvars)= nvars; hypre_CopyIndex(rfactors, (fac_restrict_data -> stride)); for (i= ndim; i< 3; i++) { rfactors[i]= 1; } /* work vector for storing the fullweighted fgrid boxes */ hypre_SStructPGridCreate(hypre_SStructPVectorComm(rf), ndim, &fgrid_coarsen); pgrid= hypre_SStructPVectorPGrid(rf); for (vars= 0; vars< nvars; vars++) { boxarray= hypre_StructGridBoxes(hypre_SStructPGridSGrid(pgrid, vars)); hypre_ForBoxI(fi, boxarray) { hypre_CopyBox(hypre_BoxArrayBox(boxarray, fi), &box); hypre_StructMapFineToCoarse(hypre_BoxIMin(&box), zero_index, rfactors, hypre_BoxIMin(&box)); hypre_StructMapFineToCoarse(hypre_BoxIMax(&box), zero_index, rfactors, hypre_BoxIMax(&box)); hypre_SStructPGridSetExtents(fgrid_coarsen, hypre_BoxIMin(&box), hypre_BoxIMax(&box)); } }
HYPRE_Int hypre_SysPFMGSolve( void *sys_pfmg_vdata, hypre_SStructMatrix *A_in, hypre_SStructVector *b_in, hypre_SStructVector *x_in ) { hypre_SysPFMGData *sys_pfmg_data = sys_pfmg_vdata; hypre_SStructPMatrix *A; hypre_SStructPVector *b; hypre_SStructPVector *x; double tol = (sys_pfmg_data -> tol); HYPRE_Int max_iter = (sys_pfmg_data -> max_iter); HYPRE_Int rel_change = (sys_pfmg_data -> rel_change); HYPRE_Int zero_guess = (sys_pfmg_data -> zero_guess); HYPRE_Int num_pre_relax = (sys_pfmg_data -> num_pre_relax); HYPRE_Int num_post_relax = (sys_pfmg_data -> num_post_relax); HYPRE_Int num_levels = (sys_pfmg_data -> num_levels); hypre_SStructPMatrix **A_l = (sys_pfmg_data -> A_l); hypre_SStructPMatrix **P_l = (sys_pfmg_data -> P_l); hypre_SStructPMatrix **RT_l = (sys_pfmg_data -> RT_l); hypre_SStructPVector **b_l = (sys_pfmg_data -> b_l); hypre_SStructPVector **x_l = (sys_pfmg_data -> x_l); hypre_SStructPVector **r_l = (sys_pfmg_data -> r_l); hypre_SStructPVector **e_l = (sys_pfmg_data -> e_l); void **relax_data_l = (sys_pfmg_data -> relax_data_l); void **matvec_data_l = (sys_pfmg_data -> matvec_data_l); void **restrict_data_l = (sys_pfmg_data -> restrict_data_l); void **interp_data_l = (sys_pfmg_data -> interp_data_l); HYPRE_Int logging = (sys_pfmg_data -> logging); double *norms = (sys_pfmg_data -> norms); double *rel_norms = (sys_pfmg_data -> rel_norms); HYPRE_Int *active_l = (sys_pfmg_data -> active_l); double b_dot_b, r_dot_r, eps; double e_dot_e, x_dot_x; HYPRE_Int i, l; HYPRE_Int ierr = 0; #if DEBUG char filename[255]; #endif /*----------------------------------------------------- * Initialize some things and deal with special cases *-----------------------------------------------------*/ hypre_BeginTiming(sys_pfmg_data -> time_index); /*----------------------------------------------------- * Refs to A,x,b (the PMatrix & PVectors within * the input SStructMatrix & SStructVectors) *-----------------------------------------------------*/ hypre_SStructPMatrixRef(hypre_SStructMatrixPMatrix(A_in, 0), &A); hypre_SStructPVectorRef(hypre_SStructVectorPVector(b_in, 0), &b); hypre_SStructPVectorRef(hypre_SStructVectorPVector(x_in, 0), &x); hypre_SStructPMatrixDestroy(A_l[0]); hypre_SStructPVectorDestroy(b_l[0]); hypre_SStructPVectorDestroy(x_l[0]); hypre_SStructPMatrixRef(A, &A_l[0]); hypre_SStructPVectorRef(b, &b_l[0]); hypre_SStructPVectorRef(x, &x_l[0]); (sys_pfmg_data -> num_iterations) = 0; /* if max_iter is zero, return */ if (max_iter == 0) { /* if using a zero initial guess, return zero */ if (zero_guess) { hypre_SStructPVectorSetConstantValues(x, 0.0); } hypre_EndTiming(sys_pfmg_data -> time_index); return ierr; } /* part of convergence check */ if (tol > 0.0) { /* eps = (tol^2) */ hypre_SStructPInnerProd(b_l[0], b_l[0], &b_dot_b); eps = tol*tol; /* if rhs is zero, return a zero solution */ if (b_dot_b == 0.0) { hypre_SStructPVectorSetConstantValues(x, 0.0); if (logging > 0) { norms[0] = 0.0; rel_norms[0] = 0.0; } hypre_EndTiming(sys_pfmg_data -> time_index); return ierr; } } /*----------------------------------------------------- * Do V-cycles: * For each index l, "fine" = l, "coarse" = (l+1) *-----------------------------------------------------*/ for (i = 0; i < max_iter; i++) { /*-------------------------------------------------- * Down cycle *--------------------------------------------------*/ /* fine grid pre-relaxation */ hypre_SysPFMGRelaxSetPreRelax(relax_data_l[0]); hypre_SysPFMGRelaxSetMaxIter(relax_data_l[0], num_pre_relax); hypre_SysPFMGRelaxSetZeroGuess(relax_data_l[0], zero_guess); hypre_SysPFMGRelax(relax_data_l[0], A_l[0], b_l[0], x_l[0]); zero_guess = 0; /* compute fine grid residual (b - Ax) */ hypre_SStructPCopy(b_l[0], r_l[0]); hypre_SStructPMatvecCompute(matvec_data_l[0], -1.0, A_l[0], x_l[0], 1.0, r_l[0]); /* convergence check */ if (tol > 0.0) { hypre_SStructPInnerProd(r_l[0], r_l[0], &r_dot_r); if (logging > 0) { norms[i] = sqrt(r_dot_r); if (b_dot_b > 0) rel_norms[i] = sqrt(r_dot_r/b_dot_b); else rel_norms[i] = 0.0; } /* always do at least 1 V-cycle */ if ((r_dot_r/b_dot_b < eps) && (i > 0)) { if (rel_change) { if ((e_dot_e/x_dot_x) < eps) break; } else { break; } } } if (num_levels > 1) { /* restrict fine grid residual */ hypre_SysSemiRestrict(restrict_data_l[0], RT_l[0], r_l[0], b_l[1]); #if DEBUG hypre_sprintf(filename, "zout_xdown.%02d", 0); hypre_SStructPVectorPrint(filename, x_l[0], 0); hypre_sprintf(filename, "zout_rdown.%02d", 0); hypre_SStructPVectorPrint(filename, r_l[0], 0); hypre_sprintf(filename, "zout_b.%02d", 1); hypre_SStructPVectorPrint(filename, b_l[1], 0); #endif for (l = 1; l <= (num_levels - 2); l++) { if (active_l[l]) { /* pre-relaxation */ hypre_SysPFMGRelaxSetPreRelax(relax_data_l[l]); hypre_SysPFMGRelaxSetMaxIter(relax_data_l[l], num_pre_relax); hypre_SysPFMGRelaxSetZeroGuess(relax_data_l[l], 1); hypre_SysPFMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]); /* compute residual (b - Ax) */ hypre_SStructPCopy(b_l[l], r_l[l]); hypre_SStructPMatvecCompute(matvec_data_l[l], -1.0, A_l[l], x_l[l], 1.0, r_l[l]); } else { /* inactive level, set x=0, so r=(b-Ax)=b */ hypre_SStructPVectorSetConstantValues(x_l[l], 0.0); hypre_SStructPCopy(b_l[l], r_l[l]); } /* restrict residual */ hypre_SysSemiRestrict(restrict_data_l[l], RT_l[l], r_l[l], b_l[l+1]); #if DEBUG hypre_sprintf(filename, "zout_xdown.%02d", l); hypre_SStructPVectorPrint(filename, x_l[l], 0); hypre_sprintf(filename, "zout_rdown.%02d", l); hypre_SStructPVectorPrint(filename, r_l[l], 0); hypre_sprintf(filename, "zout_b.%02d", l+1); hypre_SStructPVectorPrint(filename, b_l[l+1], 0); #endif } /*-------------------------------------------------- * Bottom *--------------------------------------------------*/ hypre_SysPFMGRelaxSetZeroGuess(relax_data_l[l], 1); hypre_SysPFMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]); #if DEBUG hypre_sprintf(filename, "zout_xbottom.%02d", l); hypre_SStructPVectorPrint(filename, x_l[l], 0); #endif /*-------------------------------------------------- * Up cycle *--------------------------------------------------*/ for (l = (num_levels - 2); l >= 1; l--) { /* interpolate error and correct (x = x + Pe_c) */ hypre_SysSemiInterp(interp_data_l[l], P_l[l], x_l[l+1], e_l[l]); hypre_SStructPAxpy(1.0, e_l[l], x_l[l]); #if DEBUG hypre_sprintf(filename, "zout_eup.%02d", l); hypre_SStructPVectorPrint(filename, e_l[l], 0); hypre_sprintf(filename, "zout_xup.%02d", l); hypre_SStructPVectorPrint(filename, x_l[l], 0); #endif if (active_l[l]) { /* post-relaxation */ hypre_SysPFMGRelaxSetPostRelax(relax_data_l[l]); hypre_SysPFMGRelaxSetMaxIter(relax_data_l[l], num_post_relax); hypre_SysPFMGRelaxSetZeroGuess(relax_data_l[l], 0); hypre_SysPFMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]); } } /* interpolate error and correct on fine grid (x = x + Pe_c) */ hypre_SysSemiInterp(interp_data_l[0], P_l[0], x_l[1], e_l[0]); hypre_SStructPAxpy(1.0, e_l[0], x_l[0]); #if DEBUG hypre_sprintf(filename, "zout_eup.%02d", 0); hypre_SStructPVectorPrint(filename, e_l[0], 0); hypre_sprintf(filename, "zout_xup.%02d", 0); hypre_SStructPVectorPrint(filename, x_l[0], 0); #endif } /* part of convergence check */ if ((tol > 0.0) && (rel_change)) { if (num_levels > 1) { hypre_SStructPInnerProd(e_l[0], e_l[0], &e_dot_e); hypre_SStructPInnerProd(x_l[0], x_l[0], &x_dot_x); } else { e_dot_e = 0.0; x_dot_x = 1.0; } } /* fine grid post-relaxation */ hypre_SysPFMGRelaxSetPostRelax(relax_data_l[0]); hypre_SysPFMGRelaxSetMaxIter(relax_data_l[0], num_post_relax); hypre_SysPFMGRelaxSetZeroGuess(relax_data_l[0], 0); hypre_SysPFMGRelax(relax_data_l[0], A_l[0], b_l[0], x_l[0]); (sys_pfmg_data -> num_iterations) = (i + 1); } /*----------------------------------------------------- * Destroy Refs to A,x,b (the PMatrix & PVectors within * the input SStructMatrix & SStructVectors). *-----------------------------------------------------*/ hypre_SStructPMatrixDestroy(A); hypre_SStructPVectorDestroy(x); hypre_SStructPVectorDestroy(b); hypre_EndTiming(sys_pfmg_data -> time_index); return ierr; }
HYPRE_Int hypre_SStructMatvecCompute( void *matvec_vdata, HYPRE_Complex alpha, hypre_SStructMatrix *A, hypre_SStructVector *x, HYPRE_Complex beta, hypre_SStructVector *y ) { hypre_SStructMatvecData *matvec_data = matvec_vdata; HYPRE_Int nparts = (matvec_data -> nparts); void **pmatvec_data = (matvec_data -> pmatvec_data); void *pdata; hypre_SStructPMatrix *pA; hypre_SStructPVector *px; hypre_SStructPVector *py; hypre_ParCSRMatrix *parcsrA = hypre_SStructMatrixParCSRMatrix(A); hypre_ParVector *parx; hypre_ParVector *pary; HYPRE_Int part; HYPRE_Int x_object_type= hypre_SStructVectorObjectType(x); HYPRE_Int A_object_type= hypre_SStructMatrixObjectType(A); if (x_object_type != A_object_type) { hypre_error_in_arg(2); hypre_error_in_arg(3); return hypre_error_flag; } if ( (x_object_type == HYPRE_SSTRUCT) || (x_object_type == HYPRE_STRUCT) ) { /* do S-matrix computations */ for (part = 0; part < nparts; part++) { pdata = pmatvec_data[part]; pA = hypre_SStructMatrixPMatrix(A, part); px = hypre_SStructVectorPVector(x, part); py = hypre_SStructVectorPVector(y, part); hypre_SStructPMatvecCompute(pdata, alpha, pA, px, beta, py); } if (x_object_type == HYPRE_SSTRUCT) { /* do U-matrix computations */ /* GEC1002 the data chunk pointed by the local-parvectors * inside the semistruct vectors x and y is now identical to the * data chunk of the structure vectors x and y. The role of the function * convert is to pass the addresses of the data chunk * to the parx and pary. */ hypre_SStructVectorConvert(x, &parx); hypre_SStructVectorConvert(y, &pary); hypre_ParCSRMatrixMatvec(alpha, parcsrA, parx, 1.0, pary); /* dummy functions since there is nothing to restore */ hypre_SStructVectorRestore(x, NULL); hypre_SStructVectorRestore(y, pary); parx = NULL; } } else if (x_object_type == HYPRE_PARCSR) { hypre_SStructVectorConvert(x, &parx); hypre_SStructVectorConvert(y, &pary); hypre_ParCSRMatrixMatvec(alpha, parcsrA, parx, beta, pary); hypre_SStructVectorRestore(x, NULL); hypre_SStructVectorRestore(y, pary); parx = NULL; } return hypre_error_flag; }
HYPRE_Int HYPRE_SStructSplitSolve( HYPRE_SStructSolver solver, HYPRE_SStructMatrix A, HYPRE_SStructVector b, HYPRE_SStructVector x ) { hypre_SStructVector *y = (solver -> y); HYPRE_Int nparts = (solver -> nparts); HYPRE_Int *nvars = (solver -> nvars); void ****smatvec_data = (solver -> smatvec_data); HYPRE_Int (***ssolver_solve)() = (solver -> ssolver_solve); void ***ssolver_data = (solver -> ssolver_data); double tol = (solver -> tol); HYPRE_Int max_iter = (solver -> max_iter); HYPRE_Int zero_guess = (solver -> zero_guess); void *matvec_data = (solver -> matvec_data); hypre_SStructPMatrix *pA; hypre_SStructPVector *px; hypre_SStructPVector *py; hypre_StructMatrix *sA; hypre_StructVector *sx; hypre_StructVector *sy; HYPRE_Int (*ssolve)(); void *sdata; hypre_ParCSRMatrix *parcsrA; hypre_ParVector *parx; hypre_ParVector *pary; HYPRE_Int iter, part, vi, vj; double b_dot_b = 0, r_dot_r; /* part of convergence check */ if (tol > 0.0) { /* eps = (tol^2) */ hypre_SStructInnerProd(b, b, &b_dot_b); /* if rhs is zero, return a zero solution */ if (b_dot_b == 0.0) { hypre_SStructVectorSetConstantValues(x, 0.0); (solver -> rel_norm) = 0.0; return hypre_error_flag; } } for (iter = 0; iter < max_iter; iter++) { /* convergence check */ if (tol > 0.0) { /* compute fine grid residual (b - Ax) */ hypre_SStructCopy(b, y); hypre_SStructMatvecCompute(matvec_data, -1.0, A, x, 1.0, y); hypre_SStructInnerProd(y, y, &r_dot_r); (solver -> rel_norm) = sqrt(r_dot_r/b_dot_b); if ((solver -> rel_norm) < tol) { break; } } /* copy b into y */ hypre_SStructCopy(b, y); /* compute y = y + Nx */ if (!zero_guess || (iter > 0)) { for (part = 0; part < nparts; part++) { pA = hypre_SStructMatrixPMatrix(A, part); px = hypre_SStructVectorPVector(x, part); py = hypre_SStructVectorPVector(y, part); for (vi = 0; vi < nvars[part]; vi++) { for (vj = 0; vj < nvars[part]; vj++) { sdata = smatvec_data[part][vi][vj]; sy = hypre_SStructPVectorSVector(py, vi); if ((sdata != NULL) && (vj != vi)) { sA = hypre_SStructPMatrixSMatrix(pA, vi, vj); sx = hypre_SStructPVectorSVector(px, vj); hypre_StructMatvecCompute(sdata, -1.0, sA, sx, 1.0, sy); } } } } parcsrA = hypre_SStructMatrixParCSRMatrix(A); hypre_SStructVectorConvert(x, &parx); hypre_SStructVectorConvert(y, &pary); hypre_ParCSRMatrixMatvec(-1.0, parcsrA, parx, 1.0, pary); hypre_SStructVectorRestore(x, NULL); hypre_SStructVectorRestore(y, pary); } /* compute x = M^{-1} y */ for (part = 0; part < nparts; part++) { pA = hypre_SStructMatrixPMatrix(A, part); px = hypre_SStructVectorPVector(x, part); py = hypre_SStructVectorPVector(y, part); for (vi = 0; vi < nvars[part]; vi++) { ssolve = ssolver_solve[part][vi]; sdata = ssolver_data[part][vi]; sA = hypre_SStructPMatrixSMatrix(pA, vi, vi); sx = hypre_SStructPVectorSVector(px, vi); sy = hypre_SStructPVectorSVector(py, vi); ssolve(sdata, sA, sy, sx); } } } (solver -> num_iterations) = iter; return hypre_error_flag; }
HYPRE_Int HYPRE_SStructSplitSetup( HYPRE_SStructSolver solver, HYPRE_SStructMatrix A, HYPRE_SStructVector b, HYPRE_SStructVector x ) { hypre_SStructVector *y; HYPRE_Int nparts; HYPRE_Int *nvars; void ****smatvec_data; HYPRE_Int (***ssolver_solve)(); HYPRE_Int (***ssolver_destroy)(); void ***ssolver_data; HYPRE_Int ssolver = (solver -> ssolver); MPI_Comm comm; hypre_SStructGrid *grid; hypre_SStructPMatrix *pA; hypre_SStructPVector *px; hypre_SStructPVector *py; hypre_StructMatrix *sA; hypre_StructVector *sx; hypre_StructVector *sy; HYPRE_StructMatrix sAH; HYPRE_StructVector sxH; HYPRE_StructVector syH; HYPRE_Int (*ssolve)(); HYPRE_Int (*sdestroy)(); void *sdata; HYPRE_Int part, vi, vj; comm = hypre_SStructVectorComm(b); grid = hypre_SStructVectorGrid(b); HYPRE_SStructVectorCreate(comm, grid, &y); HYPRE_SStructVectorInitialize(y); HYPRE_SStructVectorAssemble(y); nparts = hypre_SStructMatrixNParts(A); nvars = hypre_TAlloc(HYPRE_Int, nparts); smatvec_data = hypre_TAlloc(void ***, nparts); ssolver_solve = (HYPRE_Int (***)()) hypre_MAlloc((sizeof(HYPRE_Int (**)()) * nparts)); ssolver_destroy = (HYPRE_Int (***)()) hypre_MAlloc((sizeof(HYPRE_Int (**)()) * nparts)); ssolver_data = hypre_TAlloc(void **, nparts); for (part = 0; part < nparts; part++) { pA = hypre_SStructMatrixPMatrix(A, part); px = hypre_SStructVectorPVector(x, part); py = hypre_SStructVectorPVector(y, part); nvars[part] = hypre_SStructPMatrixNVars(pA); smatvec_data[part] = hypre_TAlloc(void **, nvars[part]); ssolver_solve[part] = (HYPRE_Int (**)()) hypre_MAlloc((sizeof(HYPRE_Int (*)()) * nvars[part])); ssolver_destroy[part] = (HYPRE_Int (**)()) hypre_MAlloc((sizeof(HYPRE_Int (*)()) * nvars[part])); ssolver_data[part] = hypre_TAlloc(void *, nvars[part]); for (vi = 0; vi < nvars[part]; vi++) { smatvec_data[part][vi] = hypre_TAlloc(void *, nvars[part]); for (vj = 0; vj < nvars[part]; vj++) { sA = hypre_SStructPMatrixSMatrix(pA, vi, vj); sx = hypre_SStructPVectorSVector(px, vj); smatvec_data[part][vi][vj] = NULL; if (sA != NULL) { smatvec_data[part][vi][vj] = hypre_StructMatvecCreate(); hypre_StructMatvecSetup(smatvec_data[part][vi][vj], sA, sx); } } sA = hypre_SStructPMatrixSMatrix(pA, vi, vi); sx = hypre_SStructPVectorSVector(px, vi); sy = hypre_SStructPVectorSVector(py, vi); sAH = (HYPRE_StructMatrix) sA; sxH = (HYPRE_StructVector) sx; syH = (HYPRE_StructVector) sy; switch(ssolver) { default: /* If no solver is matched, use Jacobi, but throw and error */ if (ssolver != HYPRE_Jacobi) { hypre_error(HYPRE_ERROR_GENERIC); } /* don't break */ case HYPRE_Jacobi: HYPRE_StructJacobiCreate(comm, (HYPRE_StructSolver *)&sdata); HYPRE_StructJacobiSetMaxIter(sdata, 1); HYPRE_StructJacobiSetTol(sdata, 0.0); if (solver -> zero_guess) { HYPRE_StructJacobiSetZeroGuess(sdata); } HYPRE_StructJacobiSetup(sdata, sAH, syH, sxH); ssolve = HYPRE_StructJacobiSolve; sdestroy = HYPRE_StructJacobiDestroy; break; case HYPRE_SMG: HYPRE_StructSMGCreate(comm, (HYPRE_StructSolver *)&sdata); HYPRE_StructSMGSetMemoryUse(sdata, 0); HYPRE_StructSMGSetMaxIter(sdata, 1); HYPRE_StructSMGSetTol(sdata, 0.0); if (solver -> zero_guess) { HYPRE_StructSMGSetZeroGuess(sdata); } HYPRE_StructSMGSetNumPreRelax(sdata, 1); HYPRE_StructSMGSetNumPostRelax(sdata, 1); HYPRE_StructSMGSetLogging(sdata, 0); HYPRE_StructSMGSetPrintLevel(sdata, 0); HYPRE_StructSMGSetup(sdata, sAH, syH, sxH); ssolve = HYPRE_StructSMGSolve; sdestroy = HYPRE_StructSMGDestroy; break; case HYPRE_PFMG: HYPRE_StructPFMGCreate(comm, (HYPRE_StructSolver *)&sdata); HYPRE_StructPFMGSetMaxIter(sdata, 1); HYPRE_StructPFMGSetTol(sdata, 0.0); if (solver -> zero_guess) { HYPRE_StructPFMGSetZeroGuess(sdata); } HYPRE_StructPFMGSetRelaxType(sdata, 1); HYPRE_StructPFMGSetNumPreRelax(sdata, 1); HYPRE_StructPFMGSetNumPostRelax(sdata, 1); HYPRE_StructPFMGSetLogging(sdata, 0); HYPRE_StructPFMGSetPrintLevel(sdata, 0); HYPRE_StructPFMGSetup(sdata, sAH, syH, sxH); ssolve = HYPRE_StructPFMGSolve; sdestroy = HYPRE_StructPFMGDestroy; break; } ssolver_solve[part][vi] = ssolve; ssolver_destroy[part][vi] = sdestroy; ssolver_data[part][vi] = sdata; } } (solver -> y) = y; (solver -> nparts) = nparts; (solver -> nvars) = nvars; (solver -> smatvec_data) = smatvec_data; (solver -> ssolver_solve) = ssolver_solve; (solver -> ssolver_destroy) = ssolver_destroy; (solver -> ssolver_data) = ssolver_data; if ((solver -> tol) > 0.0) { hypre_SStructMatvecCreate(&(solver -> matvec_data)); hypre_SStructMatvecSetup((solver -> matvec_data), A, x); } return hypre_error_flag; }