| 674 | } |
| 675 | |
| 676 | bool |
| 677 | FEProjector::computeL2Projection(PetscVector<double>& U_vec, |
| 678 | PetscVector<double>& F_vec, |
| 679 | const std::string& system_name, |
| 680 | const bool consistent_mass_matrix, |
| 681 | const bool close_U, |
| 682 | const bool close_F, |
| 683 | const double tol, |
| 684 | const unsigned int max_its) |
| 685 | { |
| 686 | tbox::Pointer<tbox::Timer>& system_timer = d_linear_solve_system_timers[system_name]; |
| 687 | if (system_timer.isNull()) |
| 688 | { |
| 689 | system_timer = |
| 690 | TimerManager::getManager()->getTimer("IBTK::FEProjector::computeL2Projection()[" + system_name + "]"); |
| 691 | TBOX_ASSERT(system_timer); |
| 692 | } |
| 693 | IBTK_TIMER_START(system_timer); |
| 694 | |
| 695 | int ierr; |
| 696 | bool converged = false; |
| 697 | |
| 698 | if (close_F) F_vec.close(); |
| 699 | const System& system = d_fe_data->getEquationSystems()->get_system(system_name); |
| 700 | |
| 701 | const MeshBase& mesh = d_fe_data->getEquationSystems()->get_mesh(); |
| 702 | const unsigned int dim = mesh.mesh_dimension(); |
| 703 | |
| 704 | FEType fe_type = system.get_dof_map().variable_type(0); |
| 705 | |
| 706 | // We can use the diagonal mass matrix directly if we do not need a |
| 707 | // consistent mass matrix *and* there are no constraints. |
| 708 | // |
| 709 | // TODO: this would also work with Dirichlet boundary constraints but it is not |
| 710 | // as easy to detect those constraints. |
| 711 | if (!consistent_mass_matrix && system.get_dof_map().n_constrained_dofs() == 0) |
| 712 | { |
| 713 | PetscVector<double>* M_diag_vec = buildDiagonalL2MassMatrix(system_name); |
| 714 | ierr = VecPointwiseDivide(U_vec.vec(), F_vec.vec(), M_diag_vec->vec()); |
| 715 | IBTK_CHKERRQ(ierr); |
| 716 | converged = true; |
| 717 | } |
| 718 | else |
| 719 | { |
| 720 | std::pair<PetscLinearSolver<double>*, PetscMatrix<double>*> proj_solver_components = |
| 721 | consistent_mass_matrix ? buildL2ProjectionSolver(system_name) : buildLumpedL2ProjectionSolver(system_name); |
| 722 | PetscMatrix<double>& lumped_mass = *buildLumpedL2ProjectionSolver(system_name).second; |
| 723 | PetscLinearSolver<double>* solver = proj_solver_components.first; |
| 724 | PetscMatrix<double>* M_mat = proj_solver_components.second; |
| 725 | PetscBool rtol_set; |
| 726 | double runtime_rtol; |
| 727 | ierr = PetscOptionsGetReal(nullptr, "", "-ksp_rtol", &runtime_rtol, &rtol_set); |
| 728 | IBTK_CHKERRQ(ierr); |
| 729 | PetscBool max_it_set; |
| 730 | int runtime_max_it; |
| 731 | ierr = PetscOptionsGetInt(nullptr, "", "-ksp_max_it", &runtime_max_it, &max_it_set); |
| 732 | IBTK_CHKERRQ(ierr); |
| 733 | ierr = KSPSetFromOptions(solver->ksp()); |
no test coverage detected