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 : #include "SolutionTimeAdaptiveDT.h" 11 : #include "FEProblem.h" 12 : #include "Transient.h" 13 : 14 : #include <chrono> 15 : 16 : registerMooseObject("MooseApp", SolutionTimeAdaptiveDT); 17 : 18 : InputParameters 19 28584 : SolutionTimeAdaptiveDT::validParams() 20 : { 21 28584 : InputParameters params = TimeStepper::validParams(); 22 57168 : params.addClassDescription("Compute simulation timestep based on actual solution time."); 23 85752 : params.addParam<Real>( 24 57168 : "percent_change", 0.1, "Fraction to change the timestep by. Should be between 0 and 1"); 25 85752 : params.addParam<int>( 26 57168 : "initial_direction", 1, "Direction for the first step. 1 for up... -1 for down. "); 27 114336 : params.addParam<bool>("adapt_log", false, "Output adaptive time step log"); 28 85752 : params.addRequiredParam<Real>("dt", "The timestep size between solves"); 29 : 30 28584 : return params; 31 0 : } 32 : 33 28 : SolutionTimeAdaptiveDT::SolutionTimeAdaptiveDT(const InputParameters & parameters) 34 : : TimeStepper(parameters), 35 84 : _direction(declareRestartableData<int>("direction", getParam<int>("initial_direction"))), 36 56 : _percent_change(getParam<Real>("percent_change")), 37 28 : _older_sol_time_vs_dt( 38 56 : declareRestartableData<Real>("older_sol_time_vs_dt", std::numeric_limits<Real>::max())), 39 28 : _old_sol_time_vs_dt( 40 56 : declareRestartableData<Real>("old_sol_time_vs_dt", std::numeric_limits<Real>::max())), 41 28 : _sol_time_vs_dt( 42 56 : declareRestartableData<Real>("sol_time_vs_dt", std::numeric_limits<Real>::max())), 43 112 : _adapt_log(getParam<bool>("adapt_log")) 44 : { 45 28 : if ((_adapt_log) && (processor_id() == 0)) 46 : { 47 0 : static const std::string log("adaptive_log"); 48 0 : _adaptive_log.open(log); 49 0 : if (_adaptive_log.fail()) 50 0 : mooseError("Unable to open file ", log); 51 0 : _adaptive_log << "Adaptive Times Step Log" << std::endl; 52 : } 53 28 : } 54 : 55 24 : SolutionTimeAdaptiveDT::~SolutionTimeAdaptiveDT() { _adaptive_log.close(); } 56 : 57 : void 58 193 : SolutionTimeAdaptiveDT::step() 59 : { 60 193 : auto elapsed_time = stepAndRecordElapsedTime(); 61 : 62 : // Take the maximum time over all processors so all processors compute and use the same dt 63 193 : TimeStepper::_communicator.max(elapsed_time); 64 : 65 193 : _older_sol_time_vs_dt = _old_sol_time_vs_dt; 66 193 : _old_sol_time_vs_dt = _sol_time_vs_dt; 67 193 : _sol_time_vs_dt = elapsed_time / _dt; 68 193 : } 69 : 70 : std::chrono::milliseconds::rep 71 0 : SolutionTimeAdaptiveDT::stepAndRecordElapsedTime() 72 : { 73 0 : auto start = std::chrono::system_clock::now(); 74 0 : TimeStepper::step(); 75 0 : auto end = std::chrono::system_clock::now(); 76 0 : return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); 77 : } 78 : 79 : Real 80 54 : SolutionTimeAdaptiveDT::computeInitialDT() 81 : { 82 162 : return getParam<Real>("dt"); 83 : } 84 : 85 : Real 86 188 : SolutionTimeAdaptiveDT::computeDT() 87 : { 88 : // Ratio grew so switch direction 89 188 : if (_sol_time_vs_dt > _old_sol_time_vs_dt && _sol_time_vs_dt > _older_sol_time_vs_dt) 90 : { 91 36 : _direction *= -1; 92 : 93 : // Make sure we take at least two steps in this new direction 94 36 : _old_sol_time_vs_dt = std::numeric_limits<Real>::max(); 95 36 : _older_sol_time_vs_dt = std::numeric_limits<Real>::max(); 96 : } 97 : 98 188 : Real local_dt = _dt + _dt * _percent_change * _direction; 99 : 100 188 : if ((_adapt_log) && (processor_id() == 0)) 101 : { 102 0 : Real out_dt = getCurrentDT(); 103 0 : if (out_dt > _dt_max) 104 0 : out_dt = _dt_max; 105 : 106 0 : _adaptive_log << "***Time step: " << _t_step << ", time = " << _time + out_dt 107 0 : << "\nCur DT: " << out_dt << "\nOlder Ratio: " << _older_sol_time_vs_dt 108 0 : << "\nOld Ratio: " << _old_sol_time_vs_dt << "\nNew Ratio: " << _sol_time_vs_dt 109 0 : << std::endl; 110 : } 111 : 112 188 : return local_dt; 113 : } 114 : 115 : void 116 0 : SolutionTimeAdaptiveDT::rejectStep() 117 : { 118 0 : _console << "Solve failed... cutting timestep" << std::endl; 119 0 : if (_adapt_log) 120 0 : _adaptive_log << "Solve failed... cutting timestep" << std::endl; 121 : 122 : // Reverse progression of quantities 123 0 : _sol_time_vs_dt = _old_sol_time_vs_dt; 124 0 : _old_sol_time_vs_dt = _older_sol_time_vs_dt; 125 : 126 0 : TimeStepper::rejectStep(); 127 0 : }