Line data Source code
1 : /********************************************************************/ 2 : /* SOFTWARE COPYRIGHT NOTIFICATION */ 3 : /* Cardinal */ 4 : /* */ 5 : /* (c) 2021 UChicago Argonne, LLC */ 6 : /* ALL RIGHTS RESERVED */ 7 : /* */ 8 : /* Prepared by UChicago Argonne, LLC */ 9 : /* Under Contract No. DE-AC02-06CH11357 */ 10 : /* With the U. S. Department of Energy */ 11 : /* */ 12 : /* Prepared by Battelle Energy Alliance, LLC */ 13 : /* Under Contract No. DE-AC07-05ID14517 */ 14 : /* With the U. S. Department of Energy */ 15 : /* */ 16 : /* See LICENSE for full restrictions */ 17 : /********************************************************************/ 18 : 19 : #ifdef ENABLE_NEK_COUPLING 20 : 21 : #include "NekTimeStepper.h" 22 : #include "MooseApp.h" 23 : #include "Transient.h" 24 : #include "NekInterface.h" 25 : 26 : registerMooseObject("CardinalApp", NekTimeStepper); 27 : 28 : InputParameters 29 1564 : NekTimeStepper::validParams() 30 : { 31 1564 : InputParameters params = TimeStepper::validParams(); 32 3128 : params.addParam<Real>("min_dt", 1e-9, "Minimum time step size to allow MOOSE to set in nekRS"); 33 1564 : params.addClassDescription("Select time step size based on NekRS time stepping schemes"); 34 1564 : return params; 35 0 : } 36 : 37 762 : NekTimeStepper::NekTimeStepper(const InputParameters & parameters) 38 1524 : : TimeStepper(parameters), _min_dt(getParam<Real>("min_dt")) 39 : { 40 : // Set a higher value for the timestep tolerance with which time steps are 41 : // compared between nekRS and other MOOSE apps in a multiapp hierarchy. For some reason, 42 : // it seems that floating point round-off accumulation is significant in nekRS, such 43 : // that with subcycling, I frequently see that MOOSE wants nekRS to take a time step 44 : // on the order of 5e-14 in order to "catch up" to a synchronization point. 45 762 : _executioner.setTimestepTolerance(_min_dt); 46 : 47 : // nekRS can end a simulation based on (1) a number of time steps, (2) an 48 : // end time, or (3) a total elapsed wall time. Because this wall timer would 49 : // keep incrementing while other applications are running in this multiphysics 50 : // environment, we don't want to base when to finish nekRS on this. Even if 51 : // Nek is the ultimate master app, we still probably don't want to use a wall 52 : // time to determine when to end the simulation, because other objects in the 53 : // MOOSE input file would consume that wall time. 54 762 : if (nekrs::endControlElapsedTime()) 55 0 : mooseError( 56 : "A wall time cannot be used to control the end of the nekRS simulation " 57 : "when other applications (i.e. MOOSE) are consuming the same wall time.\n\nPlease set " 58 : "'stopAt' to either 'numSteps' or 'endTime' in your .par file."); 59 : 60 : // The NekTimeStepper will take the end simulation control from the nekRS .par file. 61 : // If the Nek app is a sub-app, then the higher-up master app will automatically take 62 : // control of when the overall simulation ends. 63 762 : if (nekrs::endControlTime()) 64 24 : _end_time = nekrs::endTime(); 65 : 66 762 : if (nekrs::endControlNumSteps()) 67 738 : forceNumSteps(nekrs::numSteps()); 68 : 69 : // If running in JIT build mode, we don't want to do any time steps 70 762 : if (nekrs::buildOnly()) 71 0 : forceNumSteps(0); 72 : 73 : // When using this time stepper, the user should not try to set any constantDT-type 74 : // time stepping parameters with the Transient executioner. These could potentially 75 : // interfere with what nekRS is trying to use. 76 4572 : std::vector<std::string> invalid_params = {"end_time", "dt", "dtmin", "dtmax", "num_steps"}; 77 4572 : for (const auto & s : invalid_params) 78 3810 : if (_executioner.parameters().isParamSetByUser(s)) 79 0 : mooseError("Parameter '" + s + "' is unused by the Executioner because it is " + 80 : "already specified by 'NekTimeStepper'!"); 81 : 82 : // at this point, this is non-dimensional dt 83 762 : _nek_dt = nekrs::dt(1); 84 2286 : } 85 : 86 : Real 87 1506 : NekTimeStepper::computeInitialDT() 88 : { 89 1506 : return _nek_dt * nekrs::referenceTime(); 90 : } 91 : 92 : Real 93 32598 : NekTimeStepper::computeDT() 94 : { 95 32598 : Real dt = nekrs::hasVariableDt() ? nekrs::dt(_t_step) : _nek_dt; 96 32598 : return dt * nekrs::referenceTime(); 97 : } 98 : 99 : Real 100 33358 : NekTimeStepper::minDT() const 101 : { 102 33358 : return _min_dt; 103 : } 104 : 105 : Real 106 237351 : NekTimeStepper::nondimensionalDT(const Real & dimensional_dt) const 107 : { 108 237351 : return dimensional_dt / nekrs::referenceTime(); 109 : } 110 : 111 : #endif