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