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 1440 : ProblemOperatorBase::ProblemOperatorBase(MFEMProblem & problem) 21 1440 : : _problem(problem), _problem_data(problem.getProblemData()) 22 : { 23 1440 : } 24 : 25 : void 26 1403 : ProblemOperatorBase::SetGridFunctions() 27 : { 28 1403 : _trial_variables = _problem_data.gridfunctions.Get(_trial_var_names); 29 1403 : _test_variables = _problem_data.gridfunctions.Get(_test_var_names); 30 : 31 : // Set operator size and block structure for trial spaces 32 1403 : _block_true_offsets_trial.SetSize(_trial_variables.size() + 1); 33 1403 : _block_true_offsets_trial[0] = 0; 34 2392 : for (const auto ind : index_range(_trial_variables)) 35 989 : _block_true_offsets_trial[ind + 1] = _trial_variables.at(ind)->ParFESpace()->TrueVSize(); 36 1403 : _block_true_offsets_trial.PartialSum(); 37 : 38 : // Set operator size and block structure for test spaces 39 1403 : _block_true_offsets_test.SetSize(_test_variables.size() + 1); 40 1403 : _block_true_offsets_test[0] = 0; 41 2392 : for (const auto ind : index_range(_test_variables)) 42 989 : _block_true_offsets_test[ind + 1] = _test_variables.at(ind)->ParFESpace()->TrueVSize(); 43 1403 : _block_true_offsets_test.PartialSum(); 44 : 45 1403 : _true_x.Update(_block_true_offsets_trial); 46 1403 : _true_rhs.Update(_block_true_offsets_test); 47 1403 : } 48 : 49 : void 50 1440 : ProblemOperatorBase::Init(mfem::BlockVector & X) 51 : { 52 1440 : X.Update(_block_true_offsets_trial); 53 2403 : for (const auto i : index_range(_trial_variables)) 54 963 : 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 1440 : 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 2403 : for (const auto i : index_range(_trial_variables)) 61 1926 : _trial_variables[i]->MakeTRef( 62 963 : _trial_variables[i]->ParFESpace(), X, _block_true_offsets_trial[i]); 63 1440 : _trial_true_vector = &X; 64 1440 : } 65 : 66 : void 67 1324 : ProblemOperatorBase::SetTrialVariablesFromTrueVectors() 68 : { 69 : mooseAssert(_trial_true_vector, "The true vector should already have been set"); 70 2666 : for (const auto trial_var : _trial_variables) 71 : { 72 : // Sync the memory flags from the global true vector to the gridfunction aliases 73 1342 : trial_var->GetTrueVector().SyncMemory(*_trial_true_vector); 74 1342 : trial_var->SetFromTrueVector(); 75 : } 76 1324 : } 77 : 78 : void 79 2135 : ProblemOperatorBase::SolveWithOperator(EquationSystem & equation_system, 80 : const mfem::Vector & rhs, 81 : mfem::Vector & x) 82 : { 83 2135 : 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 2135 : if (nonlinear || _problem_data.nonlinear_solver) 89 : { 90 378 : if (nonlinear && !_problem_data.nonlinear_solver) 91 0 : mooseError("A nonlinear MFEM solve requires a nonlinear solver, but none was provided."); 92 : 93 378 : auto & nonlinear_solver = *_problem_data.nonlinear_solver; 94 378 : if (nonlinear_solver.RequiresExternalLinearSolver()) 95 : { 96 371 : if (!_problem_data.jacobian_solver) 97 0 : mooseError("The configured MFEM nonlinear solver requires an external linear solver, but " 98 : "none was provided."); 99 371 : auto & linear_solver = *_problem_data.jacobian_solver; 100 371 : equation_system.PrepareLinearSolver(linear_solver); 101 371 : nonlinear_solver.SetLinearSolver(linear_solver.GetSolver()); 102 : } 103 : 104 378 : nonlinear_solver.SetOperator(equation_system); 105 378 : nonlinear_solver.Mult(rhs, x); 106 378 : return; 107 : } 108 : else 109 : { 110 : // 111 : // pure linear path 112 : // 113 : 114 1757 : if (!_problem_data.jacobian_solver) 115 0 : mooseError("A linear MFEM solve requires a linear solver, but none was provided."); 116 : 117 1757 : auto & linear_solver = *_problem_data.jacobian_solver; 118 1757 : equation_system.PrepareLinearSolver(linear_solver); 119 1757 : linear_solver.GetSolver().Mult(rhs, x); 120 : } 121 : } 122 : 123 : } // namespace Moose::MFEM 124 : 125 : #endif