Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #ifdef MOOSE_MFEM_ENABLED 11 : 12 : #include "ProblemOperatorBase.h" 13 : #include "EquationSystem.h" 14 : 15 : class MFEMProblem; 16 : 17 : namespace Moose::MFEM 18 : { 19 : 20 1590 : ProblemOperatorBase::ProblemOperatorBase(MFEMProblem & problem) 21 1590 : : _problem(problem), _problem_data(problem.getProblemData()) 22 : { 23 1590 : } 24 : 25 : void 26 1539 : ProblemOperatorBase::SetGridFunctions() 27 : { 28 1539 : _trial_variables = _problem_data.gridfunctions.Get(_trial_var_names); 29 1539 : _test_variables = _problem_data.gridfunctions.Get(_test_var_names); 30 : 31 : // Set operator size and block structure for trial spaces 32 1539 : _block_true_offsets_trial.SetSize(_trial_variables.size() + 1); 33 1539 : _block_true_offsets_trial[0] = 0; 34 2612 : for (const auto ind : index_range(_trial_variables)) 35 1073 : _block_true_offsets_trial[ind + 1] = _trial_variables.at(ind)->ParFESpace()->TrueVSize(); 36 1539 : _block_true_offsets_trial.PartialSum(); 37 : 38 : // Set operator size and block structure for test spaces 39 1539 : _block_true_offsets_test.SetSize(_test_variables.size() + 1); 40 1539 : _block_true_offsets_test[0] = 0; 41 2612 : for (const auto ind : index_range(_test_variables)) 42 1073 : _block_true_offsets_test[ind + 1] = _test_variables.at(ind)->ParFESpace()->TrueVSize(); 43 1539 : _block_true_offsets_test.PartialSum(); 44 : 45 1539 : _true_x.Update(_block_true_offsets_trial); 46 1539 : _true_rhs.Update(_block_true_offsets_test); 47 1539 : } 48 : 49 : void 50 1576 : ProblemOperatorBase::Init(mfem::BlockVector & X) 51 : { 52 1576 : X.Update(_block_true_offsets_trial); 53 2623 : for (const auto i : index_range(_trial_variables)) 54 1047 : X.GetBlock(i) = _trial_variables[i]->GetTrueVector(); 55 : // Sync the flags from the global vector with the sub-vectors (copies to global vector location) 56 1576 : X.SyncFromBlocks(); 57 : 58 : // After initial assignment of X from the grid function, which may contain initial conditions, 59 : // we alias the grid function to X 60 2623 : for (const auto i : index_range(_trial_variables)) 61 2094 : _trial_variables[i]->MakeTRef( 62 1047 : _trial_variables[i]->ParFESpace(), X, _block_true_offsets_trial[i]); 63 1576 : _trial_true_vector = &X; 64 1576 : } 65 : 66 : void 67 1624 : ProblemOperatorBase::SetTrialVariablesFromTrueVectors() 68 : { 69 : mooseAssert(_trial_true_vector, "The true vector should already have been set"); 70 3266 : for (const auto trial_var : _trial_variables) 71 : { 72 : // Sync the memory flags from the global true vector to the gridfunction aliases 73 1642 : trial_var->GetTrueVector().SyncMemory(*_trial_true_vector); 74 1642 : trial_var->SetFromTrueVector(); 75 : } 76 1624 : } 77 : 78 : void 79 2511 : ProblemOperatorBase::SolveWithOperator(EquationSystem & equation_system, 80 : const mfem::Vector & rhs, 81 : mfem::Vector & x) 82 : { 83 : // `IsNonlinear()` describes the assembled operator, not whether a nonlinear solver is available. 84 2511 : if (equation_system.IsNonlinear() && !_problem_data.nonlinear_solver) 85 0 : mooseError("A nonlinear MFEM solve requires a nonlinear solver, but none was provided."); 86 : 87 : // Nonlinear solver path for both linear and nonlinear problems. (as a linear problem may still 88 : // intentionally be solved through the nonlinear solver machinery when one is provided) 89 2511 : if (_problem_data.nonlinear_solver) 90 : { 91 680 : auto & nonlinear_solver = *_problem_data.nonlinear_solver; 92 680 : if (nonlinear_solver.RequiresExternalLinearSolver()) 93 : { 94 673 : if (!_problem_data.jacobian_solver) 95 0 : mooseError("The configured MFEM nonlinear solver requires an external linear solver, but " 96 : "none was provided."); 97 673 : auto & linear_solver = *_problem_data.jacobian_solver; 98 673 : equation_system.PrepareLinearSolver(linear_solver); 99 671 : nonlinear_solver.SetLinearSolver(linear_solver.GetSolver()); 100 : } 101 : 102 678 : nonlinear_solver.SetOperator(equation_system); 103 678 : nonlinear_solver.Mult(rhs, x); 104 : } 105 : // Linear solver path for linear problems. 106 : else 107 : { 108 1831 : if (!_problem_data.jacobian_solver) 109 0 : mooseError("A linear MFEM solve requires a linear solver, but none was provided."); 110 : 111 1831 : auto & linear_solver = *_problem_data.jacobian_solver; 112 1831 : equation_system.PrepareLinearSolver(linear_solver); 113 1831 : linear_solver.Mult(rhs, x); 114 : } 115 2509 : } 116 : 117 : } // namespace Moose::MFEM 118 : 119 : #endif