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 1584 : ProblemOperatorBase::ProblemOperatorBase(MFEMProblem & problem) 21 1584 : : _problem(problem), _problem_data(problem.getProblemData()) 22 : { 23 1584 : } 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 2511 : const bool nonlinear = equation_system.Nonlinear(); 84 : 85 : // `nonlinear` describes the assembled MFEM operator, not whether the user configured a 86 : // nonlinear solver object. A linear problem may still intentionally be solved through the 87 : // nonlinear solver machinery when one is provided. 88 2511 : if (nonlinear || _problem_data.nonlinear_solver) 89 : { 90 680 : if (nonlinear && !_problem_data.nonlinear_solver) 91 0 : mooseError("A nonlinear MFEM solve requires a nonlinear solver, but none was provided."); 92 : 93 680 : auto & nonlinear_solver = *_problem_data.nonlinear_solver; 94 680 : if (nonlinear_solver.RequiresExternalLinearSolver()) 95 : { 96 673 : if (!_problem_data.jacobian_solver) 97 0 : mooseError("The configured MFEM nonlinear solver requires an external linear solver, but " 98 : "none was provided."); 99 673 : auto & linear_solver = *_problem_data.jacobian_solver; 100 673 : equation_system.PrepareLinearSolver(linear_solver); 101 671 : nonlinear_solver.SetLinearSolver(linear_solver.GetSolver()); 102 : } 103 : 104 678 : nonlinear_solver.SetOperator(equation_system); 105 678 : nonlinear_solver.Mult(rhs, x); 106 : } 107 : else 108 : { 109 : // 110 : // pure linear path 111 : // 112 : 113 1831 : if (!_problem_data.jacobian_solver) 114 0 : mooseError("A linear MFEM solve requires a linear solver, but none was provided."); 115 : 116 1831 : auto & linear_solver = *_problem_data.jacobian_solver; 117 1831 : equation_system.PrepareLinearSolver(linear_solver); 118 1831 : linear_solver.Mult(rhs, x); 119 : } 120 2509 : } 121 : 122 : } // namespace Moose::MFEM 123 : 124 : #endif