void StaggeredStokesOperator::initializeOperatorState(const SAMRAIVectorReal<NDIM, double>& in, const SAMRAIVectorReal<NDIM, double>& out) { IBAMR_TIMER_START(t_initialize_operator_state); // Deallocate the operator state if the operator is already initialized. if (d_is_initialized) deallocateOperatorState(); // Setup solution and rhs vectors. d_x = in.cloneVector(in.getName()); d_b = out.cloneVector(out.getName()); d_x->allocateVectorData(); // Setup the interpolation transaction information. d_U_fill_pattern = new SideNoCornersFillPattern(SIDEG, false, false, true); d_P_fill_pattern = new CellNoCornersFillPattern(CELLG, false, false, true); typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent; d_transaction_comps.resize(2); d_transaction_comps[0] = InterpolationTransactionComponent(d_x->getComponentDescriptorIndex(0), in.getComponentDescriptorIndex(0), DATA_REFINE_TYPE, USE_CF_INTERPOLATION, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_U_bc_coefs, d_U_fill_pattern); d_transaction_comps[1] = InterpolationTransactionComponent(in.getComponentDescriptorIndex(1), DATA_REFINE_TYPE, USE_CF_INTERPOLATION, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_P_bc_coef, d_P_fill_pattern); // Initialize the interpolation operators. d_hier_bdry_fill = new HierarchyGhostCellInterpolation(); d_hier_bdry_fill->initializeOperatorState(d_transaction_comps, d_x->getPatchHierarchy()); // Initialize hierarchy math ops object. if (!d_hier_math_ops_external) { d_hier_math_ops = new HierarchyMathOps(d_object_name + "::HierarchyMathOps", in.getPatchHierarchy(), in.getCoarsestLevelNumber(), in.getFinestLevelNumber()); } #if !defined(NDEBUG) else { TBOX_ASSERT(d_hier_math_ops); } #endif // Indicate the operator is initialized. d_is_initialized = true; IBAMR_TIMER_STOP(t_initialize_operator_state); return; } // initializeOperatorState
void INSCollocatedPPMConvectiveOperator::initializeOperatorState( const SAMRAIVectorReal<NDIM,double>& in, const SAMRAIVectorReal<NDIM,double>& out) { IBAMR_TIMER_START(t_initialize_operator_state); if (d_is_initialized) deallocateOperatorState(); // Get the hierarchy configuration. d_hierarchy = in.getPatchHierarchy(); d_coarsest_ln = in.getCoarsestLevelNumber(); d_finest_ln = in.getFinestLevelNumber(); #ifdef DEBUG_CHECK_ASSERTIONS TBOX_ASSERT(d_hierarchy == out.getPatchHierarchy()); TBOX_ASSERT(d_coarsest_ln == out.getCoarsestLevelNumber()); TBOX_ASSERT(d_finest_ln == out.getFinestLevelNumber()); #else NULL_USE(out); #endif Pointer<CartesianGridGeometry<NDIM> > grid_geom = d_hierarchy->getGridGeometry(); // Setup the coarsen algorithm, operator, and schedules. Pointer<CoarsenOperator<NDIM> > coarsen_op = grid_geom->lookupCoarsenOperator(d_u_flux_var, "CONSERVATIVE_COARSEN"); d_coarsen_alg = new CoarsenAlgorithm<NDIM>(); if (d_difference_form == ADVECTIVE || d_difference_form == SKEW_SYMMETRIC) d_coarsen_alg->registerCoarsen(d_u_extrap_idx, d_u_extrap_idx, coarsen_op); if (d_difference_form == CONSERVATIVE || d_difference_form == SKEW_SYMMETRIC) d_coarsen_alg->registerCoarsen(d_u_flux_idx, d_u_flux_idx, coarsen_op); d_coarsen_scheds.resize(d_finest_ln+1); for (int ln = d_coarsest_ln+1; ln <= d_finest_ln; ++ln) { Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln ); Pointer<PatchLevel<NDIM> > coarser_level = d_hierarchy->getPatchLevel(ln-1); d_coarsen_scheds[ln] = d_coarsen_alg->createSchedule(coarser_level, level); } // Setup the refine algorithm, operator, patch strategy, and schedules. Pointer<RefineOperator<NDIM> > refine_op = grid_geom->lookupRefineOperator(d_U_var, "CONSERVATIVE_LINEAR_REFINE"); d_ghostfill_alg = new RefineAlgorithm<NDIM>(); d_ghostfill_alg->registerRefine(d_U_scratch_idx, in.getComponentDescriptorIndex(0), d_U_scratch_idx, refine_op); d_ghostfill_strategy = new CartExtrapPhysBdryOp(d_U_scratch_idx, d_bdry_extrap_type); d_ghostfill_scheds.resize(d_finest_ln+1); for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln) { Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln); d_ghostfill_scheds[ln] = d_ghostfill_alg->createSchedule(level, ln-1, d_hierarchy, d_ghostfill_strategy); } // Allocate scratch data. for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln) { Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln); if (!level->checkAllocated(d_U_scratch_idx)) { level->allocatePatchData(d_U_scratch_idx); level->allocatePatchData(d_u_extrap_idx); if (d_difference_form == CONSERVATIVE || d_difference_form == SKEW_SYMMETRIC) level->allocatePatchData(d_u_flux_idx); } } d_is_initialized = true; IBAMR_TIMER_STOP(t_initialize_operator_state); return; }// initializeOperatorState
void StaggeredStokesOperator::apply(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& y) { IBAMR_TIMER_START(t_apply); // Get the vector components. const int U_idx = x.getComponentDescriptorIndex(0); const int P_idx = x.getComponentDescriptorIndex(1); const int A_U_idx = y.getComponentDescriptorIndex(0); const int A_P_idx = y.getComponentDescriptorIndex(1); const int U_scratch_idx = d_x->getComponentDescriptorIndex(0); Pointer<SideVariable<NDIM, double> > U_sc_var = x.getComponentVariable(0); Pointer<CellVariable<NDIM, double> > P_cc_var = x.getComponentVariable(1); Pointer<SideVariable<NDIM, double> > A_U_sc_var = y.getComponentVariable(0); Pointer<CellVariable<NDIM, double> > A_P_cc_var = y.getComponentVariable(1); // Simultaneously fill ghost cell values for all components. typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent; std::vector<InterpolationTransactionComponent> transaction_comps(2); transaction_comps[0] = InterpolationTransactionComponent(U_scratch_idx, U_idx, DATA_REFINE_TYPE, USE_CF_INTERPOLATION, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_U_bc_coefs, d_U_fill_pattern); transaction_comps[1] = InterpolationTransactionComponent(P_idx, DATA_REFINE_TYPE, USE_CF_INTERPOLATION, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_P_bc_coef, d_P_fill_pattern); d_hier_bdry_fill->resetTransactionComponents(transaction_comps); d_hier_bdry_fill->setHomogeneousBc(d_homogeneous_bc); StaggeredStokesPhysicalBoundaryHelper::setupBcCoefObjects( d_U_bc_coefs, d_P_bc_coef, U_scratch_idx, P_idx, d_homogeneous_bc); d_hier_bdry_fill->fillData(d_solution_time); StaggeredStokesPhysicalBoundaryHelper::resetBcCoefObjects(d_U_bc_coefs, d_P_bc_coef); // d_bc_helper->enforceDivergenceFreeConditionAtBoundary(U_scratch_idx); d_hier_bdry_fill->resetTransactionComponents(d_transaction_comps); // Compute the action of the operator: // // A*[U;P] := [A_U;A_P] = [(C*I+D*L)*U + Grad P; -Div U] d_hier_math_ops->grad(A_U_idx, A_U_sc_var, /*cf_bdry_synch*/ false, 1.0, P_idx, P_cc_var, d_no_fill, d_new_time); d_hier_math_ops->laplace(A_U_idx, A_U_sc_var, d_U_problem_coefs, U_scratch_idx, U_sc_var, d_no_fill, d_new_time, 1.0, A_U_idx, A_U_sc_var); d_hier_math_ops->div(A_P_idx, A_P_cc_var, -1.0, U_scratch_idx, U_sc_var, d_no_fill, d_new_time, /*cf_bdry_synch*/ true); d_bc_helper->copyDataAtDirichletBoundaries(A_U_idx, U_scratch_idx); IBAMR_TIMER_STOP(t_apply); return; } // apply
void IBImplicitModHelmholtzPETScLevelSolver::initializeSolverState( const SAMRAIVectorReal<NDIM,double>& x, const SAMRAIVectorReal<NDIM,double>& b) { IBAMR_TIMER_START(t_initialize_solver_state); // Rudimentary error checking. #ifdef DEBUG_CHECK_ASSERTIONS if (x.getNumberOfComponents() != b.getNumberOfComponents()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have the same number of components" << std::endl); } const Pointer<PatchHierarchy<NDIM> >& patch_hierarchy = x.getPatchHierarchy(); if (patch_hierarchy != b.getPatchHierarchy()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have the same hierarchy" << std::endl); } const int coarsest_ln = x.getCoarsestLevelNumber(); if (coarsest_ln < 0) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " coarsest level number must not be negative" << std::endl); } if (coarsest_ln != b.getCoarsestLevelNumber()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have same coarsest level number" << std::endl); } const int finest_ln = x.getFinestLevelNumber(); if (finest_ln < coarsest_ln) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " finest level number must be >= coarsest level number" << std::endl); } if (finest_ln != b.getFinestLevelNumber()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " vectors must have same finest level number" << std::endl); } for (int ln = coarsest_ln; ln <= finest_ln; ++ln) { if (patch_hierarchy->getPatchLevel(ln).isNull()) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " hierarchy level " << ln << " does not exist" << std::endl); } } if (coarsest_ln != finest_ln) { TBOX_ERROR(d_object_name << "::initializeSolverState()\n" << " coarsest_ln != finest_ln in IBImplicitModHelmholtzPETScLevelSolver" << std::endl); } #endif // Deallocate the solver state if the solver is already initialized. if (d_is_initialized) deallocateSolverState(); // Get the hierarchy information. d_hierarchy = x.getPatchHierarchy(); d_level_num = x.getCoarsestLevelNumber(); #ifdef DEBUG_CHECK_ASSERTIONS TBOX_ASSERT(d_level_num == x.getFinestLevelNumber()); #endif 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); // Allocate DOF index data. VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); Pointer<SideDataFactory<NDIM,double> > x_fac = var_db->getPatchDescriptor()->getPatchDataFactory(x_idx); const int depth = x_fac->getDefaultDepth(); Pointer<SideDataFactory<NDIM,int> > dof_index_fac = var_db->getPatchDescriptor()->getPatchDataFactory(d_dof_index_idx); dof_index_fac->setDefaultDepth(depth); Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(d_level_num); if (!level->checkAllocated(d_dof_index_idx)) level->allocatePatchData(d_dof_index_idx); // Setup PETSc objects. int ierr; PETScVecUtilities::constructPatchLevelVec(d_petsc_x, x_idx, x_var, level); PETScVecUtilities::constructPatchLevelVec(d_petsc_b, b_idx, b_var, level); PETScVecUtilities::constructPatchLevelDOFIndices(d_dof_index_idx, d_dof_index_var, x_idx, x_var, level); const double C = d_poisson_spec.cIsZero() ? 0.0 : d_poisson_spec.getCConstant(); const double D = d_poisson_spec.getDConstant(); PETScMatUtilities::constructPatchLevelLaplaceOp(d_petsc_mat, C, D, x_idx, x_var, d_dof_index_idx, d_dof_index_var, level, d_dof_index_fill); if (d_SJR_mat != PETSC_NULL) { ierr = PETScMatOps::MatAXPY(d_petsc_mat, 1.0, d_SJR_mat); IBTK_CHKERRQ(ierr); } ierr = MatSetBlockSize(d_petsc_mat, NDIM); IBTK_CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD, &d_petsc_ksp); IBTK_CHKERRQ(ierr); ierr = KSPSetOperators(d_petsc_ksp, d_petsc_mat, d_petsc_mat, SAME_PRECONDITIONER); IBTK_CHKERRQ(ierr); if (!d_options_prefix.empty()) { ierr = KSPSetOptionsPrefix(d_petsc_ksp, d_options_prefix.c_str()); IBTK_CHKERRQ(ierr); } ierr = KSPSetFromOptions(d_petsc_ksp); IBTK_CHKERRQ(ierr); // Indicate that the solver is initialized. d_is_initialized = true; IBAMR_TIMER_STOP(t_initialize_solver_state); return; }// initializeSolverState
void FACPreconditioner::facCycle_McCormick( SAMRAIVectorReal<double>& e, SAMRAIVectorReal<double>& r, SAMRAIVectorReal<double>& u, int lmax, int lmin, int ln) { /* * The steps 1-4 in this function correspond to McCormick's steps * those in his description. * * 1. If on the coarsest level, solve it. * 2. Presmoothing. * 3. Recurse to next lower level. * 4. Postsmoothing. */ /* * Step 1. */ if (ln == lmin) { /* * Solve coarsest level. */ d_fac_operator->solveCoarsestLevel(e, r, ln); } else { int i, num_components = e.getNumberOfComponents(); /* * Step 2a. */ d_fac_operator->computeCompositeResidualOnLevel(*d_tmp_residual, e, r, ln, true); for (i = 0; i < num_components; ++i) { int tmp_id = d_tmp_error->getComponentDescriptorIndex(i); d_controlled_level_ops[i]->resetLevels(ln, ln); d_controlled_level_ops[i]->setToScalar(tmp_id, 0.0); } /* * Step 2b. */ d_fac_operator->smoothError(*d_tmp_error, *d_tmp_residual, ln, d_presmoothing_sweeps); /* * Step 2c. */ for (i = 0; i < num_components; ++i) { int tmp_id = d_tmp_error->getComponentDescriptorIndex(i); int id = e.getComponentDescriptorIndex(i); d_controlled_level_ops[i]->resetLevels(ln, ln); d_controlled_level_ops[i]->add(id, id, tmp_id); } /* * Step 3a. */ d_fac_operator->computeCompositeResidualOnLevel(*d_tmp_residual, e, r, ln, true); d_fac_operator->restrictResidual(*d_tmp_residual, *d_tmp_residual, ln - 1); /* * Step 3b. */ for (i = 0; i < num_components; ++i) { int tmp_id = e.getComponentDescriptorIndex(i); d_controlled_level_ops[i]->resetLevels(ln - 1, ln - 1); d_controlled_level_ops[i]->setToScalar(tmp_id, 0.0); } /* * Step 3c. */ facCycle_McCormick(e, r, u, lmax, lmin, ln - 1); /* * Step 3d. */ d_fac_operator->prolongErrorAndCorrect(e, e, ln); /* * Step 4a. */ d_fac_operator->computeCompositeResidualOnLevel(*d_tmp_residual, e, r, ln, true); for (i = 0; i < num_components; ++i) { int tmp_id = d_tmp_error->getComponentDescriptorIndex(i); d_controlled_level_ops[i]->resetLevels(ln, ln); d_controlled_level_ops[i]->setToScalar(tmp_id, 0.0); } /* * Step 4b. */ d_fac_operator->smoothError(*d_tmp_error, *d_tmp_residual, ln, d_postsmoothing_sweeps); /* * Step 4c. */ for (i = 0; i < num_components; ++i) { int tmp_id = d_tmp_error->getComponentDescriptorIndex(i); int id = e.getComponentDescriptorIndex(i); d_controlled_level_ops[i]->resetLevels(ln, ln); d_controlled_level_ops[i]->add(id, id, tmp_id); } } }
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; }
void INSStaggeredVCStokesOperator::apply( const bool /*homogeneous_bc*/, SAMRAIVectorReal<NDIM,double>& x, SAMRAIVectorReal<NDIM,double>& y) { IBAMR_TIMER_START(t_apply); // Get the vector components. // const int U_in_idx = x.getComponentDescriptorIndex(0); // const int P_in_idx = x.getComponentDescriptorIndex(1); const int U_out_idx = y.getComponentDescriptorIndex(0); const int P_out_idx = y.getComponentDescriptorIndex(1); const int U_scratch_idx = d_x_scratch->getComponentDescriptorIndex(0); const int P_scratch_idx = d_x_scratch->getComponentDescriptorIndex(1); const Pointer<Variable<NDIM> >& U_out_var = y.getComponentVariable(0); const Pointer<Variable<NDIM> >& P_out_var = y.getComponentVariable(1); Pointer<SideVariable<NDIM,double> > U_out_sc_var = U_out_var; Pointer<CellVariable<NDIM,double> > P_out_cc_var = P_out_var; const Pointer<Variable<NDIM> >& U_scratch_var = d_x_scratch->getComponentVariable(0); const Pointer<Variable<NDIM> >& P_scratch_var = d_x_scratch->getComponentVariable(1); Pointer<SideVariable<NDIM,double> > U_scratch_sc_var = U_scratch_var; Pointer<CellVariable<NDIM,double> > P_scratch_cc_var = P_scratch_var; d_x_scratch->copyVector(Pointer<SAMRAIVectorReal<NDIM,double> >(&x,false)); // Reset the interpolation operators and fill the data. typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent; InterpolationTransactionComponent U_scratch_component(U_scratch_idx, U_DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY); InterpolationTransactionComponent P_scratch_component(P_scratch_idx, P_DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY); InterpolationTransactionComponent mu_component(d_mu_data_idx, MU_DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY); std::vector<InterpolationTransactionComponent> U_P_MU_components(3); U_P_MU_components[0] = U_scratch_component; U_P_MU_components[1] = P_scratch_component; U_P_MU_components[2] = mu_component; d_U_P_MU_bdry_fill_op->resetTransactionComponents(U_P_MU_components); d_U_P_MU_bdry_fill_op->fillData(d_new_time); // Setup hierarchy data ops object for U. HierarchyDataOpsManager<NDIM>* hier_ops_manager = HierarchyDataOpsManager<NDIM>::getManager(); Pointer<PatchHierarchy<NDIM> > hierarchy = y.getPatchHierarchy(); Pointer<HierarchySideDataOpsReal<NDIM,double> > hier_sc_data_ops = hier_ops_manager->getOperationsDouble(U_out_var, hierarchy, true); // Compute the action of the operator: // A*[u;p] = [(rho/dt)*u-0.5*div*(mu*(grad u + (grad u)^T)) + grad p; -div u]. // static const bool cf_bdry_synch = true; d_hier_math_ops->pointwiseMultiply( U_out_idx, U_out_sc_var, d_rho_data_idx, d_rho_var, U_scratch_idx, U_scratch_sc_var, 0.0, -1, NULL); d_hier_math_ops->vc_laplace( U_out_idx, U_out_sc_var, -0.5, 0.0, d_mu_data_idx, d_mu_var, U_scratch_idx, U_scratch_sc_var, d_no_fill_op, d_new_time, 1.0/d_dt, U_out_idx, U_out_sc_var); d_hier_math_ops->grad( U_out_idx, U_out_sc_var, cf_bdry_synch, 1.0, P_scratch_idx, P_scratch_cc_var, d_no_fill_op, d_new_time, 1.0, U_out_idx, U_out_sc_var); d_hier_math_ops->div( P_out_idx, P_out_cc_var, -1.0, U_scratch_idx, U_scratch_sc_var, d_no_fill_op, d_new_time, cf_bdry_synch); IBAMR_TIMER_STOP(t_apply); return; }// apply
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