bool BJacobiPreconditioner::solveSystem( SAMRAIVectorReal<NDIM,double>& x, SAMRAIVectorReal<NDIM,double>& b) { // Initialize the preconditioner, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(x,b); Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy(); const int coarsest_ln = x.getCoarsestLevelNumber(); const int finest_ln = x.getFinestLevelNumber() ; #ifdef DEBUG_CHECK_ASSERTIONS TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents()); TBOX_ASSERT(hierarchy == b.getPatchHierarchy()); TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber()); TBOX_ASSERT( finest_ln == b.getFinestLevelNumber() ); #endif const std::string& x_name = x.getName(); const std::string& b_name = b.getName(); bool ret_val = true; // Zero out the initial guess. #ifdef DEBUG_CHECK_ASSERTIONS TBOX_ASSERT(d_initial_guess_nonzero == false); #endif x.setToScalar(0.0, /*interior_only*/ false); for (int comp = 0; comp < x.getNumberOfComponents(); ++comp) { // Setup a SAMRAIVectorReal to correspond to the individual vector // component. std::ostringstream str; str << comp; SAMRAIVectorReal<NDIM,double> x_comp(x_name+"_component_"+str.str(), hierarchy, coarsest_ln, finest_ln); x_comp.addComponent(x.getComponentVariable(comp), x.getComponentDescriptorIndex(comp), x.getControlVolumeIndex(comp)); SAMRAIVectorReal<NDIM,double> b_comp(b_name+"_component_"+str.str(), hierarchy, coarsest_ln, finest_ln); b_comp.addComponent(b.getComponentVariable(comp), b.getComponentDescriptorIndex(comp), b.getControlVolumeIndex(comp)); // Configure the component preconditioner. Pointer<LinearSolver> pc_comp = d_pc_map[comp]; pc_comp->setInitialGuessNonzero(d_initial_guess_nonzero); pc_comp->setMaxIterations(d_max_iterations); pc_comp->setAbsoluteTolerance(d_abs_residual_tol); pc_comp->setRelativeTolerance(d_rel_residual_tol); // Apply the component preconditioner. const bool ret_val_comp = pc_comp->solveSystem(x_comp, b_comp); ret_val = ret_val && ret_val_comp; } // Deallocate the preconditioner, when necessary. if (deallocate_after_solve) deallocateSolverState(); return ret_val; }// solveSystem
bool PETScKrylovLinearSolver::solveSystem(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& b) { IBTK_TIMER_START(t_solve_system); #if !defined(NDEBUG) TBOX_ASSERT(d_A); #endif int ierr; // Initialize the solver, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(x, b); #if !defined(NDEBUG) TBOX_ASSERT(d_petsc_ksp); #endif resetKSPOptions(); // Allocate scratch data. d_b->allocateVectorData(); // Solve the system using a PETSc KSP object. d_b->copyVector(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false)); d_A->setHomogeneousBc(d_homogeneous_bc); d_A->modifyRhsForBcs(*d_b); d_A->setHomogeneousBc(true); PETScSAMRAIVectorReal::replaceSAMRAIVector(d_petsc_x, Pointer<SAMRAIVectorReal<NDIM, double> >(&x, false)); PETScSAMRAIVectorReal::replaceSAMRAIVector(d_petsc_b, d_b); ierr = KSPSolve(d_petsc_ksp, d_petsc_b, d_petsc_x); IBTK_CHKERRQ(ierr); d_A->setHomogeneousBc(d_homogeneous_bc); d_A->imposeSolBcs(x); // Get iterations count and residual norm. ierr = KSPGetIterationNumber(d_petsc_ksp, &d_current_iterations); IBTK_CHKERRQ(ierr); ierr = KSPGetResidualNorm(d_petsc_ksp, &d_current_residual_norm); IBTK_CHKERRQ(ierr); d_A->setHomogeneousBc(d_homogeneous_bc); // Determine the convergence reason. KSPConvergedReason reason; ierr = KSPGetConvergedReason(d_petsc_ksp, &reason); IBTK_CHKERRQ(ierr); const bool converged = (static_cast<int>(reason) > 0); if (d_enable_logging) reportKSPConvergedReason(reason, plog); // Dealocate scratch data. d_b->deallocateVectorData(); // Deallocate the solver, when necessary. if (deallocate_after_solve) deallocateSolverState(); IBTK_TIMER_STOP(t_solve_system); return converged; } // solveSystem
bool IBImplicitModHelmholtzPETScLevelSolver::solveSystem( SAMRAIVectorReal<NDIM,double>& x, SAMRAIVectorReal<NDIM,double>& b) { IBAMR_TIMER_START(t_solve_system); int ierr; if (d_enable_logging) plog << d_object_name << "::solveSystem():" << std::endl; // Initialize the solver, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(x,b); #if 0 // XXXX // Configure solver. ierr = KSPSetTolerances(d_petsc_ksp, d_rel_residual_tol, d_abs_residual_tol, PETSC_DEFAULT, d_max_iterations); IBTK_CHKERRQ(ierr); ierr = KSPSetInitialGuessNonzero(d_petsc_ksp, d_initial_guess_nonzero ? PETSC_TRUE : PETSC_FALSE); IBTK_CHKERRQ(ierr); #endif // Solve the system. Pointer<PatchLevel<NDIM> > patch_level = d_hierarchy->getPatchLevel(d_level_num); const int x_idx = x.getComponentDescriptorIndex(0); Pointer<SideVariable<NDIM,double> > x_var = x.getComponentVariable(0); const int b_idx = b.getComponentDescriptorIndex(0); Pointer<SideVariable<NDIM,double> > b_var = b.getComponentVariable(0); if (d_initial_guess_nonzero) PETScVecUtilities::copyToPatchLevelVec(d_petsc_x, x_idx, x_var, patch_level); PETScVecUtilities::copyToPatchLevelVec(d_petsc_b, b_idx, b_var, patch_level); PETScVecUtilities::constrainPatchLevelVec(d_petsc_b, d_dof_index_idx, d_dof_index_var, patch_level, d_dof_index_fill); ierr = KSPSolve(d_petsc_ksp, d_petsc_b, d_petsc_x); IBTK_CHKERRQ(ierr); PETScVecUtilities::copyFromPatchLevelVec(d_petsc_x, x_idx, x_var, patch_level); typedef SideDataSynchronization::SynchronizationTransactionComponent SynchronizationTransactionComponent; // XXXX SynchronizationTransactionComponent x_synch_transaction = SynchronizationTransactionComponent(x_idx, "CONSERVATIVE_COARSEN"); Pointer<SideDataSynchronization> side_synch_op = new SideDataSynchronization(); side_synch_op->initializeOperatorState(x_synch_transaction, x.getPatchHierarchy()); side_synch_op->synchronizeData(0.0); // Log solver info. KSPConvergedReason reason; ierr = KSPGetConvergedReason(d_petsc_ksp, &reason); IBTK_CHKERRQ(ierr); const bool converged = reason > 0; if (d_enable_logging) { plog << d_object_name << "::solveSystem(): solver " << (converged ? "converged" : "diverged") << "\n" << "iterations = " << d_current_its << "\n" << "residual norm = " << d_current_residual_norm << std::endl; } // Deallocate the solver, when necessary. if (deallocate_after_solve) deallocateSolverState(); IBAMR_TIMER_STOP(t_solve_system); return converged; }// solveSystem
bool FACPreconditioner::solveSystem( SAMRAIVectorReal<NDIM,double>& u, SAMRAIVectorReal<NDIM,double>& f) { // Initialize the solver, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(u,f); // Set the initial guess to equal zero. u.setToScalar(0.0, /*interior_only*/ false); // Keep track of whether we need to (re-)compute the residual. Because u is // initialized to equal zero, the initial residual is precisely the // right-hand-side vector f. We only need to recompute the residual once we // start modifying the solution vector u. d_recompute_residual = false; // Apply a single FAC cycle. if (d_cycle_type == V_CYCLE && d_num_pre_sweeps == 0) { // V-cycle MG without presmoothing keeps the residual equal to the // initial right-hand-side vector f, so we can simply use that vector // for the residual in the FAC algorithm. FACVCycleNoPreSmoothing(u, f, d_finest_ln); } else { d_f->copyVector(Pointer<SAMRAIVectorReal<NDIM,double> >(&f, false), false); d_r->copyVector(Pointer<SAMRAIVectorReal<NDIM,double> >(&f, false), false); switch (d_cycle_type) { case V_CYCLE: FACVCycle(u, *d_f, d_finest_ln); break; case W_CYCLE: FACWCycle(u, *d_f, d_finest_ln); break; case F_CYCLE: FACFCycle(u, *d_f, d_finest_ln); break; default: TBOX_ERROR(d_object_name << "::solveSystem():\n" << " unrecognized FAC cycle type: " << enum_to_string<MGCycleType>(d_cycle_type) << "." << std::endl); } } // Deallocate the solver, when necessary. if (deallocate_after_solve) deallocateSolverState(); return true; }// solveSystem
bool PETScPCLSWrapper::solveSystem(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& b) { if (!d_is_initialized) initializeSolverState(x, b); // Update the PETSc Vec wrappers. PETScSAMRAIVectorReal::replaceSAMRAIVector(d_petsc_x, Pointer<SAMRAIVectorReal<NDIM, double> >(&x, false)); PETScSAMRAIVectorReal::replaceSAMRAIVector(d_petsc_b, Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false)); // Apply the preconditioner. int ierr = PCApply(d_petsc_pc, d_petsc_x, d_petsc_b); IBTK_CHKERRQ(ierr); return true; } // solveSystem
bool CCDivGradHypreLevelSolver::solveSystem( SAMRAIVectorReal<NDIM,double>& x, SAMRAIVectorReal<NDIM,double>& b) { IBTK_TIMER_START(t_solve_system); if (d_enable_logging) plog << d_object_name << "::solveSystem():" << std::endl; // Initialize the solver, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(x,b); // Solve the system using the hypre solver. static const int comp = 0; const int x_idx = x.getComponentDescriptorIndex(comp); const int b_idx = b.getComponentDescriptorIndex(comp); bool converged = true; IntVector<NDIM> chkbrd_mode_id; #if (NDIM > 2) for (chkbrd_mode_id(2) = 0; chkbrd_mode_id(2) < 2; ++chkbrd_mode_id(2)) { #endif for (chkbrd_mode_id(1) = 0; chkbrd_mode_id(1) < 2; ++chkbrd_mode_id(1)) { for (chkbrd_mode_id(0) = 0; chkbrd_mode_id(0) < 2; ++chkbrd_mode_id(0)) { bool converged_mode = solveSystem(x_idx, b_idx, chkbrd_mode_id); if (d_enable_logging) { plog << d_object_name << "::solveSystem(): solver " << (converged_mode ? "converged" : "diverged") << "\n" << "chkbrd_mode_id = " << chkbrd_mode_id << "\n" << "iterations = " << d_current_its << "\n" << "residual norm = " << d_current_residual_norm << std::endl; } converged = converged && converged_mode; } } #if (NDIM > 2) } #endif // Deallocate the solver, when necessary. if (deallocate_after_solve) deallocateSolverState(); IBTK_TIMER_STOP(t_solve_system); return converged; }// solveSystem
bool FACPreconditioner::solveSystem( SAMRAIVectorReal<double>& u, SAMRAIVectorReal<double>& f) { d_residual_norm = tbox::MathUtilities<double>::getSignalingNaN(); d_avg_convergence_factor = tbox::MathUtilities<double>::getSignalingNaN(); /* * Set the solution-vector-dependent data if not preset. */ bool clear_hierarchy_configuration_when_done = false; if (!d_patch_hierarchy) { clear_hierarchy_configuration_when_done = true; initializeSolverState(u, f); } else { #ifdef DEBUG_CHECK_ASSERTIONS if (!checkVectorStateCompatibility(u, f)) { TBOX_ERROR(d_object_name << ": Incompatible vectors for\n" << "current state in solveSystem.\n"); } #endif } t_solve_system->start(); d_error_vector->setToScalar(0.0, false); if (d_tmp_error) { d_tmp_error->setToScalar(0.0, false); } d_residual_vector->setToScalar(0.0); const double initial_residual_norm = d_residual_norm = computeFullCompositeResidual(*d_residual_vector, u, f); /* * Above step has the side effect of filling the residual * vector d_residual_vector. */ double effective_residual_tolerance = d_residual_tolerance; if (d_relative_residual_tolerance >= 0) { double tmp = d_fac_operator->computeResidualNorm(f, d_finest_ln, d_coarsest_ln); tmp *= d_relative_residual_tolerance; if (effective_residual_tolerance < tmp) effective_residual_tolerance = tmp; } if (static_cast<int>(d_convergence_factor.size()) < d_max_iterations) d_convergence_factor.resize(d_max_iterations); d_number_iterations = 0; /* * Use a do loop instead of a while loop until convergence. * It is important to go through the loop at least once * because the residual norm can be less than the tolerance * when the solution is 0 and the rhs is less than the tolerance. */ do { /* * In zeroing the error vector, also zero out the ghost values. * This gives the FAC operator an oportunity to bypass the * ghost filling if it decides that the ghost values do not * change. */ d_error_vector->setToScalar(0.0, false); /* * Both the recursive and non-recursive fac cycling functions * were coded to find the problem due presmoothing. Both give * the same results, but the problem due to presmoothing still * exists. BTNG. */ if (d_algorithm_choice == "default") { facCycle_Recursive(*d_error_vector, *d_residual_vector, u, d_finest_ln, d_coarsest_ln, d_finest_ln); } else if (d_algorithm_choice == "mccormick-s4.3") { facCycle_McCormick(*d_error_vector, *d_residual_vector, u, d_finest_ln, d_coarsest_ln, d_finest_ln); } else if (d_algorithm_choice == "pernice") { facCycle(*d_error_vector, *d_residual_vector, u, d_finest_ln, d_coarsest_ln); } int i, num_components = d_error_vector->getNumberOfComponents(); /* * u += e */ for (i = 0; i < num_components; ++i) { int soln_id = u.getComponentDescriptorIndex(i); int err_id = d_error_vector->getComponentDescriptorIndex(i); d_controlled_level_ops[i]->resetLevels(d_coarsest_ln, d_finest_ln); d_controlled_level_ops[i]->add(soln_id, soln_id, err_id); } /* * Synchronize solution across levels by coarsening the * more accurate fine-level solutions. */ for (int ln = d_finest_ln - 1; ln >= d_coarsest_ln; --ln) { d_fac_operator->restrictSolution(u, u, ln); } /* * Compute convergence factor and new residual norm. * 1. Temporarily save pre-cycle residual norm in * convergence factor stack. * 2. Compute post-cycle residual norm. * 3. Set convergence factor to ratio of post-cycle to pre-cycle * residual norms. */ d_convergence_factor[d_number_iterations] = d_residual_norm; d_residual_norm = computeFullCompositeResidual(*d_residual_vector, u, f); // Disable Intel warning on real comparison #ifdef __INTEL_COMPILER #pragma warning (disable:1572) #endif if (d_convergence_factor[d_number_iterations] != 0) { d_convergence_factor[d_number_iterations] = d_residual_norm / d_convergence_factor[d_number_iterations]; } else { d_convergence_factor[d_number_iterations] = 0; } /* * Increment the iteration counter. * The rest of this block expects it to have the incremented value. * In particular, d_fac_operator->postprocessOneCycle does. */ ++d_number_iterations; /* * Compute the convergence factors because they may be accessed * from the operator's postprocessOneCycle function. */ d_net_convergence_factor = d_residual_norm / (initial_residual_norm + 1e-20); d_avg_convergence_factor = pow(d_net_convergence_factor, 1.0 / d_number_iterations); d_fac_operator->postprocessOneCycle(d_number_iterations - 1, u, *d_residual_vector); } while ((d_residual_norm > effective_residual_tolerance) && (d_number_iterations < d_max_iterations)); t_solve_system->stop(); if (clear_hierarchy_configuration_when_done) { deallocateSolverState(); } return d_residual_norm < effective_residual_tolerance; }
bool PETScNewtonKrylovSolver::solveSystem(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& b) { IBTK_TIMER_START(t_solve_system); int ierr; // Initialize the solver, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(x, b); #if !defined(NDEBUG) TBOX_ASSERT(d_petsc_snes); #endif resetSNESOptions(); Pointer<PETScKrylovLinearSolver> p_krylov_solver = d_krylov_solver; if (p_krylov_solver) p_krylov_solver->resetKSPOptions(); // Allocate scratch data. if (d_b) d_b->allocateVectorData(); if (d_r) d_r->allocateVectorData(); // Solve the system using a PETSc SNES object. PETScSAMRAIVectorReal::replaceSAMRAIVector( d_petsc_x, Pointer<SAMRAIVectorReal<NDIM, double> >(&x, false)); Pointer<LinearOperator> A = d_F; if (A) { d_b->copyVector(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false)); A->modifyRhsForInhomogeneousBc(*d_b); ierr = PetscObjectStateIncrease(reinterpret_cast<PetscObject>(d_petsc_b)); IBTK_CHKERRQ(ierr); PETScSAMRAIVectorReal::replaceSAMRAIVector(d_petsc_b, d_b); } else { PETScSAMRAIVectorReal::replaceSAMRAIVector( d_petsc_b, Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false)); } ierr = SNESSolve(d_petsc_snes, d_petsc_b, d_petsc_x); IBTK_CHKERRQ(ierr); ierr = SNESGetIterationNumber(d_petsc_snes, &d_current_iterations); IBTK_CHKERRQ(ierr); ierr = SNESGetLinearSolveIterations(d_petsc_snes, &d_current_linear_iterations); IBTK_CHKERRQ(ierr); ierr = SNESGetFunctionNorm(d_petsc_snes, &d_current_residual_norm); IBTK_CHKERRQ(ierr); // Determine the convergence reason. SNESConvergedReason reason; ierr = SNESGetConvergedReason(d_petsc_snes, &reason); IBTK_CHKERRQ(ierr); const bool converged = (static_cast<int>(reason) > 0); if (d_enable_logging) reportSNESConvergedReason(reason, plog); // Deallocate scratch data. if (d_b) d_b->deallocateVectorData(); if (d_r) d_r->deallocateVectorData(); // Deallocate the solver, when necessary. if (deallocate_after_solve) deallocateSolverState(); IBTK_TIMER_STOP(t_solve_system); return converged; } // solveSystem
bool StaggeredStokesProjectionPreconditioner::solveSystem(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& b) { IBAMR_TIMER_START(t_solve_system); // Initialize the solver (if necessary). const bool deallocate_at_completion = !d_is_initialized; if (!d_is_initialized) initializeSolverState(x, b); // Determine whether we are solving a steady-state problem. const bool steady_state = d_U_problem_coefs.cIsZero() || (d_U_problem_coefs.cIsConstant() && MathUtilities<double>::equalEps(d_U_problem_coefs.getCConstant(), 0.0)); // Get the vector components. const int F_U_idx = b.getComponentDescriptorIndex(0); const int F_P_idx = b.getComponentDescriptorIndex(1); const Pointer<Variable<NDIM> >& F_U_var = b.getComponentVariable(0); const Pointer<Variable<NDIM> >& F_P_var = b.getComponentVariable(1); Pointer<SideVariable<NDIM, double> > F_U_sc_var = F_U_var; Pointer<CellVariable<NDIM, double> > F_P_cc_var = F_P_var; const int U_idx = x.getComponentDescriptorIndex(0); const int P_idx = x.getComponentDescriptorIndex(1); const Pointer<Variable<NDIM> >& U_var = x.getComponentVariable(0); const Pointer<Variable<NDIM> >& P_var = x.getComponentVariable(1); Pointer<SideVariable<NDIM, double> > U_sc_var = U_var; Pointer<CellVariable<NDIM, double> > P_cc_var = P_var; // Setup the component solver vectors. Pointer<SAMRAIVectorReal<NDIM, double> > F_U_vec; F_U_vec = new SAMRAIVectorReal<NDIM, double>(d_object_name + "::F_U", d_hierarchy, d_coarsest_ln, d_finest_ln); F_U_vec->addComponent(F_U_sc_var, F_U_idx, d_velocity_wgt_idx, d_velocity_data_ops); Pointer<SAMRAIVectorReal<NDIM, double> > U_vec; U_vec = new SAMRAIVectorReal<NDIM, double>(d_object_name + "::U", d_hierarchy, d_coarsest_ln, d_finest_ln); U_vec->addComponent(U_sc_var, U_idx, d_velocity_wgt_idx, d_velocity_data_ops); Pointer<SAMRAIVectorReal<NDIM, double> > Phi_scratch_vec; Phi_scratch_vec = new SAMRAIVectorReal<NDIM, double>(d_object_name + "::Phi_scratch", d_hierarchy, d_coarsest_ln, d_finest_ln); Phi_scratch_vec->addComponent(d_Phi_var, d_Phi_scratch_idx, d_pressure_wgt_idx, d_pressure_data_ops); Pointer<SAMRAIVectorReal<NDIM, double> > F_Phi_vec; F_Phi_vec = new SAMRAIVectorReal<NDIM, double>(d_object_name + "::F_Phi", d_hierarchy, d_coarsest_ln, d_finest_ln); F_Phi_vec->addComponent(d_F_Phi_var, d_F_Phi_idx, d_pressure_wgt_idx, d_pressure_data_ops); Pointer<SAMRAIVectorReal<NDIM, double> > P_vec; P_vec = new SAMRAIVectorReal<NDIM, double>(d_object_name + "::P", d_hierarchy, d_coarsest_ln, d_finest_ln); P_vec->addComponent(P_cc_var, P_idx, d_pressure_wgt_idx, d_pressure_data_ops); // Allocate scratch data. for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln) { Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln); level->allocatePatchData(d_Phi_scratch_idx); level->allocatePatchData(d_F_Phi_idx); } // (1) Solve the velocity sub-problem for an initial approximation to U. // // U^* := inv(rho/dt - K*mu*L) F_U // // An approximate Helmholtz solver is used. d_velocity_solver->setHomogeneousBc(true); LinearSolver* p_velocity_solver = dynamic_cast<LinearSolver*>(d_velocity_solver.getPointer()); if (p_velocity_solver) p_velocity_solver->setInitialGuessNonzero(false); d_velocity_solver->solveSystem(*U_vec, *F_U_vec); // (2) Solve the pressure sub-problem. // // We treat two cases: // // (i) rho/dt = 0. // // In this case, // // U - U^* + G Phi = 0 // -D U = F_P // // so that // // Phi := inv(-L_p) * F_Phi = inv(-L_p) * (-F_P - D U^*) // P := -K*mu*F_Phi // // in which L_p = D*G. // // (ii) rho/dt != 0. // // In this case, // // rho (U - U^*) + G Phi = 0 // -D U = F_P // // so that // // Phi := inv(-L_rho) * F_phi = inv(-L_rho) * (-F_P - D U^*) // P := (1/dt - K*mu*L_rho)*Phi = (1/dt) Phi - K*mu*F_phi // // in which L_rho = D*(1/rho)*G. // // Approximate Poisson solvers are used in both cases. d_hier_math_ops->div(d_F_Phi_idx, d_F_Phi_var, -1.0, U_idx, U_sc_var, d_no_fill_op, d_new_time, /*cf_bdry_synch*/ true, -1.0, F_P_idx, F_P_cc_var); d_pressure_solver->setHomogeneousBc(true); LinearSolver* p_pressure_solver = dynamic_cast<LinearSolver*>(d_pressure_solver.getPointer()); p_pressure_solver->setInitialGuessNonzero(false); d_pressure_solver->solveSystem(*Phi_scratch_vec, *F_Phi_vec); if (steady_state) { d_pressure_data_ops->scale(P_idx, -d_U_problem_coefs.getDConstant(), d_F_Phi_idx); } else { d_pressure_data_ops->linearSum( P_idx, 1.0 / getDt(), d_Phi_scratch_idx, -d_U_problem_coefs.getDConstant(), d_F_Phi_idx); } // (3) Evaluate U in terms of U^* and Phi. // // We treat two cases: // // (i) rho = 0. In this case, // // U = U^* - G Phi // // (ii) rho != 0. In this case, // // U = U^* - (1.0/rho) G Phi double coef; if (steady_state) { coef = -1.0; } else { coef = d_P_problem_coefs.getDConstant(); } d_hier_math_ops->grad(U_idx, U_sc_var, /*cf_bdry_synch*/ true, coef, d_Phi_scratch_idx, d_Phi_var, d_Phi_bdry_fill_op, d_pressure_solver->getSolutionTime(), 1.0, U_idx, U_sc_var); // Account for nullspace vectors. correctNullspace(U_vec, P_vec); // Deallocate scratch data. for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln) { Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln); level->deallocatePatchData(d_Phi_scratch_idx); level->deallocatePatchData(d_F_Phi_idx); } // Deallocate the solver (if necessary). if (deallocate_at_completion) deallocateSolverState(); IBAMR_TIMER_STOP(t_solve_system); return true; } // solveSystem
bool BGaussSeidelPreconditioner::solveSystem(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& b) { // Initialize the preconditioner, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(x, b); #if !defined(NDEBUG) Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy(); const int coarsest_ln = x.getCoarsestLevelNumber(); const int finest_ln = x.getFinestLevelNumber(); TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents()); TBOX_ASSERT(hierarchy == b.getPatchHierarchy()); TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber()); TBOX_ASSERT(finest_ln == b.getFinestLevelNumber()); #endif bool ret_val = true; // Zero out the initial guess. #if !defined(NDEBUG) TBOX_ASSERT(d_initial_guess_nonzero == false); #endif x.setToScalar(0.0, /*interior_only*/ false); // Setup SAMRAIVectorReal objects to correspond to the individual vector // components. std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > x_comps = getComponentVectors(Pointer<SAMRAIVectorReal<NDIM, double> >(&x, false)); std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > b_comps = getComponentVectors(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false)); // Clone the right-hand-side vector to avoid modifying it during the // preconditioning operation. Pointer<SAMRAIVectorReal<NDIM, double> > f = b.cloneVector(b.getName()); f->allocateVectorData(); f->copyVector(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false), false); std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > f_comps = getComponentVectors(f); // Setup the order in which the component preconditioner are to be applied. const int ncomps = x.getNumberOfComponents(); std::vector<int> comps; comps.reserve(2 * ncomps - 1); if (!d_reverse_order) { // Standard order: Run from comp = 0 to comp = ncomp-1. for (int comp = 0; comp < ncomps; ++comp) { comps.push_back(comp); } if (d_symmetric_preconditioner) { for (int comp = ncomps - 2; comp >= 0; --comp) { comps.push_back(comp); } } } else { // Reversed order: Run from comp = ncomp-1 to comp = 0. for (int comp = ncomps - 1; comp >= 0; --comp) { comps.push_back(comp); } if (d_symmetric_preconditioner) { for (int comp = 1; comp < ncomps; ++comp) { comps.push_back(comp); } } } // Apply the component preconditioners. int count = 0; for (std::vector<int>::const_iterator it = comps.begin(); it != comps.end(); ++it, ++count) { const int comp = (*it); Pointer<SAMRAIVectorReal<NDIM, double> > x_comp = x_comps[comp]; Pointer<SAMRAIVectorReal<NDIM, double> > b_comp = b_comps[comp]; Pointer<SAMRAIVectorReal<NDIM, double> > f_comp = f_comps[comp]; // Update the right-hand-side vector. f_comp->setToScalar(0.0); for (int c = 0; c < ncomps; ++c) { if (c == comp) continue; d_linear_ops_map[comp][c]->applyAdd(*x_comps[c], *f_comp, *f_comp); } f_comp->subtract(b_comp, f_comp); // Configure the component preconditioner. Pointer<LinearSolver> pc_comp = d_pc_map[comp]; pc_comp->setInitialGuessNonzero(count >= ncomps); pc_comp->setMaxIterations(d_max_iterations); pc_comp->setAbsoluteTolerance(d_abs_residual_tol); pc_comp->setRelativeTolerance(d_rel_residual_tol); // Apply the component preconditioner. const bool ret_val_comp = pc_comp->solveSystem(*x_comp, *f_comp); ret_val = ret_val && ret_val_comp; } // Free the copied right-hand-side vector data. f->deallocateVectorData(); f->freeVectorComponents(); // Deallocate the preconditioner, when necessary. if (deallocate_after_solve) deallocateSolverState(); return ret_val; } // solveSystem