Source code for core.level
from typing import Any, Dict, List, Optional, Type
from pySDC.core.sweeper import Sweeper
from pySDC.core.problem import Problem
from pySDC.helpers.pysdc_helper import FrozenClass
# short helper class to add params as attributes
class _Pars(FrozenClass):
def __init__(self, params: Dict[str, Any]) -> None:
self.dt: Optional[float] = None
self.dt_initial: Optional[float] = None
self.restol: float = -1.0
self.nsweeps: int = 1
self.residual_type: str = 'full_abs'
for k, v in params.items():
setattr(self, k, v)
# freeze class, no further attributes allowed from this point
self._freeze()
self.dt_initial = self.dt * 1.0 if self.dt is not None else None
# short helper class to bundle all status variables
class _Status(FrozenClass):
"""
This class carries the status of the level. All variables that the core SDC / PFASST functionality depend on are
initialized here.
"""
def __init__(self) -> None:
self.residual: Optional[float] = None
self.unlocked: bool = False
self.updated: bool = False
self.time: Optional[float] = None
self.dt_new: Optional[float] = None
self.sweep: Optional[int] = None
# freeze class, no further attributes allowed from this point
self._freeze()
[docs]
class Level(FrozenClass):
"""
Level class containing all management functionality for a single level
A level contains all data structures, types and objects to perform sweeps on this particular level. It does not
know about other levels.
Attributes:
params (__Pars): parameter object containing the custom parameters passed by the user
status (__Status): status object
level_index (int): custom string naming this level
uend: dof values at the right end point of the interval
u (list of dtype_u): dof values at the nodes
uold (list of dtype_u): copy of dof values for saving data during restriction)
f (list of dtype_f): RHS values at the nodes
fold (list of dtype_f): copy of RHS values for saving data during restriction
tau (list of dtype_u): FAS correction, allocated via step class if necessary
"""
def __init__(
self,
problem_class: Type[Problem],
problem_params: Dict[str, Any],
sweeper_class: Type[Sweeper],
sweeper_params: Dict[str, Any],
level_params: Dict[str, Any],
level_index: int,
) -> None:
"""
Initialization routine
Args:
problem_class: problem class
problem_params (dict): parameters for the problem to be initialized
sweeper_class: sweeper class
sweeper_params (dict): parameters for the sweeper (contains collocation)
level_params (dict): parameters given by the user, will be added as attributes
level_index (int): custom name for this level
"""
# set level parameters and status
self.params: _Pars = _Pars(level_params)
self.status: _Status = _Status()
# instantiate sweeper, problem and hooks
self.__sweep: Sweeper = sweeper_class(sweeper_params, self)
self.__prob: Problem = problem_class(**problem_params)
# set name
self.level_index: int = level_index
# empty data at the nodes, the right end point and tau
self.uend: Optional[Any] = None
self.u: List[Optional[Any]] = [None] * (self.sweep.coll.num_nodes + 1)
self.uold: List[Optional[Any]] = [None] * (self.sweep.coll.num_nodes + 1)
self.u_avg: List[Optional[Any]] = [None] * self.sweep.coll.num_nodes
self.residual: List[Optional[Any]] = [None] * self.sweep.coll.num_nodes
self.increment: List[Optional[Any]] = [None] * self.sweep.coll.num_nodes
self.f: List[Optional[Any]] = [None] * (self.sweep.coll.num_nodes + 1)
self.fold: List[Optional[Any]] = [None] * (self.sweep.coll.num_nodes + 1)
self.tau: List[Optional[Any]] = [None] * self.sweep.coll.num_nodes
self.__tag: Optional[Any] = None
# freeze class, no further attributes allowed from this point
self._freeze()
[docs]
def reset_level(self, reset_status: bool = True) -> None:
"""
Routine to clean-up the level for the next time step
Args:
reset_status (bool): Reset the status or only the solution
Returns:
None
"""
# reset status
if reset_status:
self.status = _Status()
# all data back to None
self.uend = None
self.u = [None] * (self.sweep.coll.num_nodes + 1)
self.uold = [None] * (self.sweep.coll.num_nodes + 1)
self.f = [None] * (self.sweep.coll.num_nodes + 1)
self.fold = [None] * (self.sweep.coll.num_nodes + 1)
self.tau = [None] * self.sweep.coll.num_nodes
@property
def sweep(self) -> Sweeper:
"""
Getter for the sweeper
Returns:
pySDC.Sweeper.sweeper: the sweeper associated to this level
"""
return self.__sweep
@property
def prob(self) -> Problem:
"""
Getter for the problem
Returns:
pySDC.Problem.ptype: the problem associated to this level
"""
return self.__prob
@property
def time(self) -> Optional[float]:
"""
Meta-getter for the current time
Returns:
float: referencing status time for convenience
"""
return self.status.time
@property
def dt(self) -> Optional[float]:
"""
Meta-getter for the time-step size
Returns:
float: referencing dt from parameters for convenience
"""
return self.params.dt
@property
def tag(self) -> Optional[Any]:
"""
Getter for tag
Returns:
tag for sending/receiving
"""
return self.__tag
@tag.setter
def tag(self, t: Any) -> None:
"""
Setter for tag
Args:
t: new tag for sending/receiving
"""
self.__tag = t