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_PCGSetLogging( HYPRE_Solver solver, int level ) { return ( hypre_PCGSetLogging( (void *) solver, level ) ); }