HYPRE_Int HYPRE_StructSMGCreate( MPI_Comm comm, HYPRE_StructSolver *solver ) { *solver = ( (HYPRE_StructSolver) hypre_SMGCreate( comm ) ); return 0; }
HYPRE_Int hypre_HybridSolve( void *hybrid_vdata, hypre_StructMatrix *A, hypre_StructVector *b, hypre_StructVector *x ) { hypre_HybridData *hybrid_data = hybrid_vdata; MPI_Comm comm = (hybrid_data -> comm); HYPRE_Real tol = (hybrid_data -> tol); HYPRE_Real cf_tol = (hybrid_data -> cf_tol); HYPRE_Real pcg_atolf = (hybrid_data -> pcg_atolf); HYPRE_Int dscg_max_its = (hybrid_data -> dscg_max_its); HYPRE_Int pcg_max_its = (hybrid_data -> pcg_max_its); HYPRE_Int two_norm = (hybrid_data -> two_norm); HYPRE_Int stop_crit = (hybrid_data -> stop_crit); HYPRE_Int rel_change = (hybrid_data -> rel_change); HYPRE_Int logging = (hybrid_data -> logging); HYPRE_Int print_level = (hybrid_data -> print_level); HYPRE_Int solver_type = (hybrid_data -> solver_type); HYPRE_Int k_dim = (hybrid_data -> k_dim); HYPRE_Int pcg_default = (hybrid_data -> pcg_default); HYPRE_Int (*pcg_precond_solve)(); HYPRE_Int (*pcg_precond_setup)(); void *pcg_precond; void *pcg_solver; hypre_PCGFunctions * pcg_functions; hypre_GMRESFunctions * gmres_functions; hypre_BiCGSTABFunctions * bicgstab_functions; HYPRE_Int dscg_num_its; HYPRE_Int pcg_num_its; HYPRE_Int converged; HYPRE_Real res_norm; HYPRE_Int myid; if (solver_type == 1) { /*-------------------------------------------------------------------- * Setup DSCG. *--------------------------------------------------------------------*/ pcg_functions = hypre_PCGFunctionsCreate( hypre_CAlloc, hypre_StructKrylovFree, hypre_StructKrylovCommInfo, hypre_StructKrylovCreateVector, hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate, hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy, hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector, hypre_StructKrylovClearVector, hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy, hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity ); pcg_solver = hypre_PCGCreate( pcg_functions ); hypre_PCGSetMaxIter(pcg_solver, dscg_max_its); hypre_PCGSetTol(pcg_solver, tol); hypre_PCGSetAbsoluteTolFactor(pcg_solver, pcg_atolf); hypre_PCGSetConvergenceFactorTol(pcg_solver, cf_tol); hypre_PCGSetTwoNorm(pcg_solver, two_norm); hypre_PCGSetStopCrit(pcg_solver, stop_crit); hypre_PCGSetRelChange(pcg_solver, rel_change); hypre_PCGSetPrintLevel(pcg_solver, print_level); hypre_PCGSetLogging(pcg_solver, logging); pcg_precond = NULL; hypre_PCGSetPrecond(pcg_solver, HYPRE_StructDiagScale, HYPRE_StructDiagScaleSetup, pcg_precond); hypre_PCGSetup(pcg_solver, (void*) A, (void*) b, (void*) x); /*-------------------------------------------------------------------- * Solve with DSCG. *--------------------------------------------------------------------*/ hypre_PCGSolve(pcg_solver, (void*) A, (void*) b, (void*) x); /*-------------------------------------------------------------------- * Get information for DSCG. *--------------------------------------------------------------------*/ hypre_PCGGetNumIterations(pcg_solver, &dscg_num_its); (hybrid_data -> dscg_num_its) = dscg_num_its; hypre_PCGGetFinalRelativeResidualNorm(pcg_solver, &res_norm); /*-------------------------------------------------------------------- * Get additional information from PCG if logging on for hybrid solver. * Currently used as debugging flag to print norms. *--------------------------------------------------------------------*/ if( logging > 1 ) { hypre_MPI_Comm_rank(comm, &myid ); hypre_PCGPrintLogging(pcg_solver, myid); } /*-------------------------------------------------------------------- * check if converged. *--------------------------------------------------------------------*/ hypre_PCGGetConverged(pcg_solver, &converged); } else if (solver_type == 2) { /*-------------------------------------------------------------------- * Setup GMRES *--------------------------------------------------------------------*/ gmres_functions = hypre_GMRESFunctionsCreate( hypre_CAlloc, hypre_StructKrylovFree, hypre_StructKrylovCommInfo, hypre_StructKrylovCreateVector, hypre_StructKrylovCreateVectorArray, hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate, hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy, hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector, hypre_StructKrylovClearVector, hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy, hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity ); pcg_solver = hypre_GMRESCreate( gmres_functions ); hypre_GMRESSetMaxIter(pcg_solver, dscg_max_its); hypre_GMRESSetTol(pcg_solver, tol); hypre_GMRESSetKDim(pcg_solver, k_dim); hypre_GMRESSetConvergenceFactorTol(pcg_solver, cf_tol); hypre_GMRESSetStopCrit(pcg_solver, stop_crit); hypre_GMRESSetRelChange(pcg_solver, rel_change); hypre_GMRESSetPrintLevel(pcg_solver, print_level); hypre_GMRESSetPrintLevel(pcg_solver, print_level); hypre_GMRESSetLogging(pcg_solver, logging); pcg_precond = NULL; hypre_GMRESSetPrecond(pcg_solver, HYPRE_StructDiagScale, HYPRE_StructDiagScaleSetup, pcg_precond); hypre_GMRESSetup(pcg_solver, (void*) A, (void*) b, (void*) x); /*-------------------------------------------------------------------- * Solve with GMRES *--------------------------------------------------------------------*/ hypre_GMRESSolve(pcg_solver, (void*) A, (void*) b, (void*) x); /*-------------------------------------------------------------------- * Get information for GMRES *--------------------------------------------------------------------*/ hypre_GMRESGetNumIterations(pcg_solver, &dscg_num_its); (hybrid_data -> dscg_num_its) = dscg_num_its; hypre_GMRESGetFinalRelativeResidualNorm(pcg_solver, &res_norm); /*-------------------------------------------------------------------- * check if converged. *--------------------------------------------------------------------*/ hypre_GMRESGetConverged(pcg_solver, &converged); } else { /*-------------------------------------------------------------------- * Setup BiCGSTAB *--------------------------------------------------------------------*/ bicgstab_functions = hypre_BiCGSTABFunctionsCreate( hypre_StructKrylovCreateVector, hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate, hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy, hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector, hypre_StructKrylovClearVector, hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy, hypre_StructKrylovCommInfo, hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity ); pcg_solver = hypre_BiCGSTABCreate( bicgstab_functions ); hypre_BiCGSTABSetMaxIter(pcg_solver, dscg_max_its); hypre_BiCGSTABSetTol(pcg_solver, tol); hypre_BiCGSTABSetConvergenceFactorTol(pcg_solver, cf_tol); hypre_BiCGSTABSetStopCrit(pcg_solver, stop_crit); hypre_BiCGSTABSetPrintLevel(pcg_solver, print_level); hypre_BiCGSTABSetLogging(pcg_solver, logging); pcg_precond = NULL; hypre_BiCGSTABSetPrecond(pcg_solver, HYPRE_StructDiagScale, HYPRE_StructDiagScaleSetup, pcg_precond); hypre_BiCGSTABSetup(pcg_solver, (void*) A, (void*) b, (void*) x); /*-------------------------------------------------------------------- * Solve with BiCGSTAB *--------------------------------------------------------------------*/ hypre_BiCGSTABSolve(pcg_solver, (void*) A, (void*) b, (void*) x); /*-------------------------------------------------------------------- * Get information for BiCGSTAB *--------------------------------------------------------------------*/ hypre_BiCGSTABGetNumIterations(pcg_solver, &dscg_num_its); (hybrid_data -> dscg_num_its) = dscg_num_its; hypre_BiCGSTABGetFinalRelativeResidualNorm(pcg_solver, &res_norm); /*-------------------------------------------------------------------- * check if converged. *--------------------------------------------------------------------*/ hypre_BiCGSTABGetConverged(pcg_solver, &converged); } /*----------------------------------------------------------------------- * if converged, done... *-----------------------------------------------------------------------*/ if( converged ) { (hybrid_data -> final_rel_res_norm) = res_norm; if (solver_type == 1) hypre_PCGDestroy(pcg_solver); else if (solver_type == 2) hypre_GMRESDestroy(pcg_solver); else hypre_BiCGSTABDestroy(pcg_solver); } /*----------------------------------------------------------------------- * ... otherwise, use SMG+solver *-----------------------------------------------------------------------*/ else { /*-------------------------------------------------------------------- * Free up previous PCG solver structure and set up a new one. *--------------------------------------------------------------------*/ if (solver_type == 1) { hypre_PCGDestroy(pcg_solver); pcg_functions = hypre_PCGFunctionsCreate( hypre_CAlloc, hypre_StructKrylovFree, hypre_StructKrylovCommInfo, hypre_StructKrylovCreateVector, hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate, hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy, hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector, hypre_StructKrylovClearVector, hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy, hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity ); pcg_solver = hypre_PCGCreate( pcg_functions ); hypre_PCGSetMaxIter(pcg_solver, pcg_max_its); hypre_PCGSetTol(pcg_solver, tol); hypre_PCGSetAbsoluteTolFactor(pcg_solver, pcg_atolf); hypre_PCGSetTwoNorm(pcg_solver, two_norm); hypre_PCGSetStopCrit(pcg_solver, stop_crit); hypre_PCGSetRelChange(pcg_solver, rel_change); hypre_PCGSetPrintLevel(pcg_solver, print_level); hypre_PCGSetLogging(pcg_solver, logging); } else if (solver_type == 2) { hypre_GMRESDestroy(pcg_solver); gmres_functions = hypre_GMRESFunctionsCreate( hypre_CAlloc, hypre_StructKrylovFree, hypre_StructKrylovCommInfo, hypre_StructKrylovCreateVector, hypre_StructKrylovCreateVectorArray, hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate, hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy, hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector, hypre_StructKrylovClearVector, hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy, hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity ); pcg_solver = hypre_GMRESCreate( gmres_functions ); hypre_GMRESSetMaxIter(pcg_solver, pcg_max_its); hypre_GMRESSetTol(pcg_solver, tol); hypre_GMRESSetKDim(pcg_solver, k_dim); hypre_GMRESSetStopCrit(pcg_solver, stop_crit); hypre_GMRESSetRelChange(pcg_solver, rel_change); hypre_GMRESSetPrintLevel(pcg_solver, print_level); hypre_GMRESSetLogging(pcg_solver, logging); hypre_GMRESSetConvergenceFactorTol(pcg_solver, 0.0); } else { hypre_BiCGSTABDestroy(pcg_solver); bicgstab_functions = hypre_BiCGSTABFunctionsCreate( hypre_StructKrylovCreateVector, hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate, hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy, hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector, hypre_StructKrylovClearVector, hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy, hypre_StructKrylovCommInfo, hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity ); pcg_solver = hypre_BiCGSTABCreate( bicgstab_functions ); hypre_BiCGSTABSetMaxIter(pcg_solver, pcg_max_its); hypre_BiCGSTABSetTol(pcg_solver, tol); hypre_BiCGSTABSetStopCrit(pcg_solver, stop_crit); hypre_BiCGSTABSetPrintLevel(pcg_solver, print_level); hypre_BiCGSTABSetLogging(pcg_solver, logging); hypre_BiCGSTABSetConvergenceFactorTol(pcg_solver, 0.0); } /* Setup preconditioner */ if (pcg_default) { pcg_precond = hypre_SMGCreate(comm); hypre_SMGSetMaxIter(pcg_precond, 1); hypre_SMGSetTol(pcg_precond, 0.0); hypre_SMGSetNumPreRelax(pcg_precond, 1); hypre_SMGSetNumPostRelax(pcg_precond, 1); hypre_SMGSetLogging(pcg_precond, 0); pcg_precond_solve = hypre_SMGSolve; pcg_precond_setup = hypre_SMGSetup; } else { pcg_precond = (hybrid_data -> pcg_precond); pcg_precond_solve = (hybrid_data -> pcg_precond_solve); pcg_precond_setup = (hybrid_data -> pcg_precond_setup); } /* Complete setup of solver+SMG */ if (solver_type == 1) { hypre_PCGSetPrecond(pcg_solver, pcg_precond_solve, pcg_precond_setup, pcg_precond); hypre_PCGSetup(pcg_solver, (void*) A, (void*) b, (void*) x); /* Solve */ hypre_PCGSolve(pcg_solver, (void*) A, (void*) b, (void*) x); /* Get information from PCG that is always logged in hybrid solver*/ hypre_PCGGetNumIterations(pcg_solver, &pcg_num_its); (hybrid_data -> pcg_num_its) = pcg_num_its; hypre_PCGGetFinalRelativeResidualNorm(pcg_solver, &res_norm); (hybrid_data -> final_rel_res_norm) = res_norm; /*----------------------------------------------------------------- * Get additional information from PCG if logging on for hybrid solver. * Currently used as debugging flag to print norms. *-----------------------------------------------------------------*/ if( logging > 1 ) { hypre_MPI_Comm_rank(comm, &myid ); hypre_PCGPrintLogging(pcg_solver, myid); } /* Free PCG and preconditioner */ hypre_PCGDestroy(pcg_solver); } else if (solver_type == 2) { hypre_GMRESSetPrecond(pcg_solver, pcg_precond_solve, pcg_precond_setup, pcg_precond); hypre_GMRESSetup(pcg_solver, (void*) A, (void*) b, (void*) x); /* Solve */ hypre_GMRESSolve(pcg_solver, (void*) A, (void*) b, (void*) x); /* Get information from GMRES that is always logged in hybrid solver*/ hypre_GMRESGetNumIterations(pcg_solver, &pcg_num_its); (hybrid_data -> pcg_num_its) = pcg_num_its; hypre_GMRESGetFinalRelativeResidualNorm(pcg_solver, &res_norm); (hybrid_data -> final_rel_res_norm) = res_norm; /* Free GMRES and preconditioner */ hypre_GMRESDestroy(pcg_solver); } else { hypre_BiCGSTABSetPrecond(pcg_solver, pcg_precond_solve, pcg_precond_setup, pcg_precond); hypre_BiCGSTABSetup(pcg_solver, (void*) A, (void*) b, (void*) x); /* Solve */ hypre_BiCGSTABSolve(pcg_solver, (void*) A, (void*) b, (void*) x); /* Get information from BiCGSTAB that is always logged in hybrid solver*/ hypre_BiCGSTABGetNumIterations(pcg_solver, &pcg_num_its); (hybrid_data -> pcg_num_its) = pcg_num_its; hypre_BiCGSTABGetFinalRelativeResidualNorm(pcg_solver, &res_norm); (hybrid_data -> final_rel_res_norm) = res_norm; /* Free BiCGSTAB and preconditioner */ hypre_BiCGSTABDestroy(pcg_solver); } if (pcg_default) { hypre_SMGDestroy(pcg_precond); } } return hypre_error_flag; }
int hypre_SMGRelaxSetupASol( void *relax_vdata, hypre_StructMatrix *A, hypre_StructVector *b, hypre_StructVector *x ) { hypre_SMGRelaxData *relax_data = relax_vdata; int num_spaces = (relax_data -> num_spaces); int *space_indices = (relax_data -> space_indices); int *space_strides = (relax_data -> space_strides); hypre_StructVector *temp_vec = (relax_data -> temp_vec); int num_pre_relax = (relax_data -> num_pre_relax); int num_post_relax = (relax_data -> num_post_relax); hypre_StructStencil *stencil = hypre_StructMatrixStencil(A); hypre_Index *stencil_shape = hypre_StructStencilShape(stencil); int stencil_size = hypre_StructStencilSize(stencil); int stencil_dim = hypre_StructStencilDim(stencil); hypre_StructMatrix *A_sol; void **solve_data; hypre_Index base_index; hypre_Index base_stride; int num_stencil_indices; int *stencil_indices; int i; int ierr = 0; /*---------------------------------------------------------- * Free up old data before putting new data into structure *----------------------------------------------------------*/ hypre_SMGRelaxDestroyASol(relax_vdata); /*---------------------------------------------------------- * Set up data *----------------------------------------------------------*/ hypre_CopyIndex((relax_data -> base_index), base_index); hypre_CopyIndex((relax_data -> base_stride), base_stride); stencil_indices = hypre_TAlloc(int, stencil_size); num_stencil_indices = 0; for (i = 0; i < stencil_size; i++) { if (hypre_IndexD(stencil_shape[i], (stencil_dim - 1)) == 0) { stencil_indices[num_stencil_indices] = i; num_stencil_indices++; } } A_sol = hypre_StructMatrixCreateMask(A, num_stencil_indices, stencil_indices); hypre_StructStencilDim(hypre_StructMatrixStencil(A_sol)) = stencil_dim - 1; hypre_TFree(stencil_indices); /* Set up solve_data */ solve_data = hypre_TAlloc(void *, num_spaces); for (i = 0; i < num_spaces; i++) { hypre_IndexD(base_index, (stencil_dim - 1)) = space_indices[i]; hypre_IndexD(base_stride, (stencil_dim - 1)) = space_strides[i]; if (stencil_dim > 2) { solve_data[i] = hypre_SMGCreate(relax_data -> comm); hypre_SMGSetNumPreRelax( solve_data[i], num_pre_relax); hypre_SMGSetNumPostRelax( solve_data[i], num_post_relax); hypre_SMGSetBase(solve_data[i], base_index, base_stride); hypre_SMGSetMemoryUse(solve_data[i], (relax_data -> memory_use)); hypre_SMGSetTol(solve_data[i], 0.0); hypre_SMGSetMaxIter(solve_data[i], 1); hypre_SMGSetup(solve_data[i], A_sol, temp_vec, x); } else { solve_data[i] = hypre_CyclicReductionCreate(relax_data -> comm); hypre_CyclicReductionSetBase(solve_data[i], base_index, base_stride); hypre_CyclicReductionSetup(solve_data[i], A_sol, temp_vec, x); } } (relax_data -> A_sol) = A_sol; (relax_data -> solve_data) = solve_data; (relax_data -> setup_a_sol) = 0; return ierr; }