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 "MFEMTransient.h" 13 : #include "MFEMProblem.h" 14 : #include "TimeDependentEquationSystemProblemOperator.h" 15 : #include "TimeStepper.h" 16 : 17 : registerMooseObject("MooseApp", MFEMTransient); 18 : 19 : InputParameters 20 2744 : MFEMTransient::validParams() 21 : { 22 2744 : InputParameters params = MFEMProblemSolve::validParams(); 23 2744 : params += TransientBase::validParams(); 24 2744 : params.addClassDescription("Executioner for transient MFEM problems."); 25 2744 : return params; 26 0 : } 27 : 28 323 : MFEMTransient::MFEMTransient(const InputParameters & params) 29 : : TransientBase(params), 30 323 : _mfem_problem(dynamic_cast<MFEMProblem &>(feProblem())), 31 323 : _mfem_problem_data(_mfem_problem.getProblemData()), 32 646 : _mfem_problem_solve(*this, getProblemOperators()) 33 : { 34 : // If no ProblemOperators have been added by the user, add a default 35 323 : if (getProblemOperators().empty()) 36 : { 37 323 : _mfem_problem_data.eqn_system = std::make_shared<Moose::MFEM::TimeDependentEquationSystem>( 38 323 : _mfem_problem_data.time_derivative_map); 39 : auto problem_operator = 40 323 : std::make_shared<Moose::MFEM::TimeDependentEquationSystemProblemOperator>(_mfem_problem); 41 323 : addProblemOperator(std::move(problem_operator)); 42 323 : } 43 323 : } 44 : 45 : void 46 323 : MFEMTransient::init() 47 : { 48 323 : TransientBase::init(); 49 : 50 : // verify that the requested time integration scheme is actually supported by MFEM transient 51 323 : if (getTimeScheme() != Moose::TimeIntegratorType::TI_IMPLICIT_EULER) 52 2 : paramError("scheme", 53 2 : "Time Integration scheme \"" + stringify(getTimeScheme()) + 54 : "\" is not supported by MFEMTransient Executioner."); 55 : 56 321 : if (_mfem_problem_data.nonlinear_solver) 57 24 : _mfem_problem_data.eqn_system->SetSolverRequiresGradient( 58 24 : _mfem_problem_data.nonlinear_solver->RequiresGradient()); 59 : 60 : // Set up initial conditions 61 321 : _mfem_problem_data.eqn_system->Init( 62 321 : _mfem_problem_data.gridfunctions, 63 321 : _mfem_problem_data.cmplx_gridfunctions, 64 963 : getParam<MooseEnum>("assembly_level").getEnum<mfem::AssemblyLevel>()); 65 : 66 642 : for (const auto & problem_operator : getProblemOperators()) 67 : { 68 321 : problem_operator->SetGridFunctions(); 69 321 : problem_operator->Init(_mfem_problem_data.f); 70 : } 71 321 : } 72 : 73 : void 74 1572 : MFEMTransient::takeStep(Real input_dt) 75 : { 76 1572 : _dt_old = _dt; 77 : 78 1572 : if (input_dt == -1.0) 79 1294 : _dt = computeConstrainedDT(); 80 : else 81 278 : _dt = input_dt; 82 : 83 1572 : _time_stepper->preSolve(); 84 : 85 : // Unfortunately, time needs to be temporarily incremented so we get 86 : // meaningful console output in timestepSetup(). We decrement it back 87 : // immediately after so step() below behaves as expected. 88 1572 : _time += _dt; 89 1572 : _problem.timestepSetup(); 90 1572 : _time -= _dt; 91 : 92 1572 : _problem.onTimestepBegin(); 93 1572 : _problem.execTransfers(EXEC_TIMESTEP_BEGIN); 94 1572 : if (!_problem.execMultiApps(EXEC_TIMESTEP_BEGIN, true)) 95 : { 96 0 : _last_solve_converged = false; 97 0 : return; 98 : } 99 1572 : _problem.execute(EXEC_TIMESTEP_BEGIN); 100 : 101 : // Advance time step of the MFEM problem. Time is also updated here, and 102 : // _problem_operator->SetTime is called inside the ode_solver->Step method to 103 : // update the time used by time dependent (function) coefficients. 104 1572 : _time_stepper->step(); 105 : 106 : // Continue with usual TransientBase::takeStep() finalisation 107 1572 : _last_solve_converged = _time_stepper->converged(); 108 : 109 1572 : if (!lastSolveConverged()) 110 : { 111 0 : _console << "Aborting as solve did not converge" << std::endl; 112 0 : return; 113 : } 114 : 115 1572 : _problem.execute(EXEC_TIMESTEP_END); 116 1572 : _problem.execTransfers(EXEC_TIMESTEP_END); 117 1572 : _problem.execMultiApps(EXEC_TIMESTEP_END, true); 118 : 119 1572 : if (lastSolveConverged()) 120 1572 : _time_stepper->acceptStep(); 121 : else 122 0 : _time_stepper->rejectStep(); 123 : 124 : // Set time to time old, since final time is updated in TransientBase::endStep() 125 1572 : _time = _time_old; 126 : 127 1572 : _time_stepper->postSolve(); 128 : } 129 : 130 : #endif