Source code for edelweissfe.timesteppers.adaptivetimestepper

# -*- coding: utf-8 -*-
#  ---------------------------------------------------------------------
#
#  _____    _      _              _         _____ _____
# | ____|__| | ___| |_      _____(_)___ ___|  ___| ____|
# |  _| / _` |/ _ \ \ \ /\ / / _ \ / __/ __| |_  |  _|
# | |__| (_| |  __/ |\ V  V /  __/ \__ \__ \  _| | |___
# |_____\__,_|\___|_| \_/\_/ \___|_|___/___/_|   |_____|
#
#
#  Unit of Strength of Materials and Structural Analysis
#  University of Innsbruck,
#  2017 - today
#
#  Matthias Neuner matthias.neuner@uibk.ac.at
#
#  This file is part of EdelweissFE.
#
#  This library is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2.1 of the License, or (at your option) any later version.
#
#  The full text of the license can be found in the file LICENSE.md at
#  the top level directory of EdelweissFE.
#  ---------------------------------------------------------------------
# Created on Sat Jan  21 12:18:10 2017

from edelweissfe.journal.journal import Journal
from edelweissfe.timesteppers.timestep import TimeStep
from edelweissfe.utils.exceptions import ReachedMaxIncrements, ReachedMinIncrementSize


[docs]class AdaptiveTimeStepper: identification = "AdaptiveTimeStepper" def __init__( self, currentTime: float, stepLength: float, startIncrement: float, maxIncrement: float, minIncrement: float, maxNumberIncrements: int, journal: Journal, increaseFactor=1.1, ): """ An increment generator for incremental-iterative simulations. Implementation as generator class. Parameters ---------- currentTime The current (start) time. stepLength The total length of the step. startIncrement The size of the start increment. maxIncrement The maximum size of an increment. minIncrement The minimum size of an increment. maxNumberIncrements The maximum number of allowed increments. journal The journal instance for logging purposes. increaseFactor The ratio to increase the increments in case of good convergence. """ self.nPassedGoodIncrements = int(0) self.incrementCounter = int(0) self.startIncrement = startIncrement self.maxIncrement = maxIncrement self.minIncrement = minIncrement self.maxNumberIncrements = maxNumberIncrements self.finishedStepProgress = 0.0 self.increment = min(startIncrement, maxIncrement) self.allowedToIncreasedNext = True self.currentTime = currentTime self.stepLength = stepLength self.dT = 0.0 self.journal = journal self.increaseFactor = increaseFactor
[docs] def generateTimeStep(self) -> TimeStep: """ Generate the next increment. Returns ------- TimeStep The current time step. """ while self.finishedStepProgress < (1.0 - 1e-15): remainder = 1.0 - self.finishedStepProgress if remainder < self.increment: self.increment = remainder # # zero increment; return value for first function call theIncrement = self.increment if self.incrementCounter > 0 else 0.0 dT = self.stepLength * theIncrement self.finishedStepProgress += theIncrement endTimeOfIncrementInStep = self.stepLength * self.finishedStepProgress endTimeOfIncrementInTotal = self.currentTime + endTimeOfIncrementInStep yield TimeStep( self.incrementCounter, theIncrement, self.finishedStepProgress, dT, endTimeOfIncrementInStep, endTimeOfIncrementInTotal, ) if self.incrementCounter > self.maxNumberIncrements: self.journal.errorMessage("Reached maximum number of increments", self.identification) raise ReachedMaxIncrements() if (self.nPassedGoodIncrements >= 3) and self.allowedToIncreasedNext: self.increment *= self.increaseFactor if self.increment > self.maxIncrement: self.increment = self.maxIncrement self.allowedToIncreasedNext = True self.incrementCounter += 1 self.nPassedGoodIncrements += 1
[docs] def preventIncrementIncrease( self, ): """May be called before an increment is requested, to prevent from automatically increasing, e.g. in case of bad convergency.""" self.allowedToIncreasedNext = False
[docs] def reduceNextIncrement(self, scaleFactor: float): """Reduce the increment size for the next increment.""" if self.increment == self.minIncrement: self.journal.errorMessage("Cannot reduce increment size", self.identification) raise ReachedMinIncrementSize() newIncrement = self.increment * scaleFactor if newIncrement > self.maxIncrement: self.increment = self.maxIncrement elif newIncrement < self.minIncrement: self.increment = self.minIncrement else: self.increment = newIncrement self.journal.message( "Cutback to increment size {:}".format(self.increment), self.identification, 2, )
[docs] def discardAndChangeIncrement(self, scaleFactor: float): """Change increment size between minIncrement and maxIncrement by a given scale factor. Parameters ---------- scaleFactor The factor for scaling based on the previous increment. """ if self.incrementCounter == 0: self.journal.errorMessage("Failed zero increment", self.identification) raise ReachedMinIncrementSize() self.finishedStepProgress -= self.increment self.incrementCounter -= 1 self.nPassedGoodIncrements = 0 self.reduceNextIncrement(scaleFactor)
[docs] def writeRestart(self, restartFile): """Write restart information to a file. Parameters ---------- restartFile The file to write the restart information to. """ f = restartFile f.create_group("timestepper") f["timestepper"].attrs["currentTime"] = self.currentTime f["timestepper"].attrs["stepLength"] = self.stepLength f["timestepper"].attrs["startIncrement"] = self.startIncrement f["timestepper"].attrs["maxIncrement"] = self.maxIncrement f["timestepper"].attrs["minIncrement"] = self.minIncrement f["timestepper"].attrs["maxNumberIncrements"] = self.maxNumberIncrements f["timestepper"].attrs["nPassedGoodIncrements"] = self.nPassedGoodIncrements f["timestepper"].attrs["incrementCounter"] = self.incrementCounter f["timestepper"].attrs["finishedStepProgress"] = self.finishedStepProgress f["timestepper"].attrs["increment"] = self.increment f["timestepper"].attrs["allowedToIncreasedNext"] = self.allowedToIncreasedNext f["timestepper"].attrs["dT"] = self.dT
[docs] def readRestart(self, restartFile): """Read restart information from a file. Parameters ---------- restartFile The file to read the restart information from. """ f = restartFile self.currentTime = f["timestepper"].attrs["currentTime"] self.stepLength = f["timestepper"].attrs["stepLength"] self.startIncrement = f["timestepper"].attrs["startIncrement"] self.maxIncrement = f["timestepper"].attrs["maxIncrement"] self.minIncrement = f["timestepper"].attrs["minIncrement"] self.maxNumberIncrements = f["timestepper"].attrs["maxNumberIncrements"] self.nPassedGoodIncrements = f["timestepper"].attrs["nPassedGoodIncrements"] self.incrementCounter = f["timestepper"].attrs["incrementCounter"] self.finishedStepProgress = f["timestepper"].attrs["finishedStepProgress"] self.increment = f["timestepper"].attrs["increment"] self.allowedToIncreasedNext = f["timestepper"].attrs["allowedToIncreasedNext"] self.dT = f["timestepper"].attrs["dT"]