controller#

class Controller(controller_params: Dict[str, Any], description: Dict[str, Any], useMPI: bool | None = None)[source]#

Bases: object

Abstract base class of the controllers, which set up hooks and convergence controllers and run the steps in time.

add_convergence_controller(convergence_controller: Type[Any], description: Dict[str, Any], params: Dict[str, Any] | None = None, allow_double: bool = False) → None[source]#

Add an individual convergence controller to the list of convergence controllers and instantiate it. Afterwards, the order of the convergence controllers is updated.

Parameters:
  • convergence_controller (pySDC.ConvergenceController) – The convergence controller to be added

  • description (dict) – The description object used to instantiate the controller

  • params (dict) – Parameters for the convergence controller

  • allow_double (bool) – Allow adding the same convergence controller multiple times

Returns:

None

add_hook(hook: Type[Any]) → None[source]#

Add a hook to the controller which will be called in addition to all other hooks whenever something happens. The hook is only added if a hook of the same class is not already present.

Parameters:

hook (pySDC.Hook) – A hook class that is derived from the core hook class

Returns:

None

check_variable_coefficients(num_procs: int) → None[source]#

Reject k-dependent QDelta coefficients outside plain SDC.

MIN-SR-FLEX and the Jumper variants vary QDelta with the sweep index, and the nilpotency argument behind them is derived for SDC, where that index is the SDC iteration count. Anything needing more iterations (PFASST) or fewer (MLSDC) breaks that identity and would need its own analysis first.

They are also only refreshed by Sweeper.updateVariableCoeffs, which runs on the finest level of the Jacobi sweep alone, so on a coarse level or on the Gauss-Seidel path they silently degrade to a fixed preconditioner. Failing loudly beats either of those.

Note this gates parallelism across steps and the number of levels. Parallelism across collocation nodes (generic_implicit_MPI and friends) is still SDC and stays allowed.

Parameters:

num_procs (int) – number of parallel time steps

Raises:

ControllerError – if a k-dependent QDelta is combined with multiple levels or steps

dump_setup(step: Any, controller_params: Dict[str, Any], description: Dict[str, Any]) → None[source]#

Helper function to dump the setup used for this controller

Parameters:
  • step (pySDC.Step.step) – the step instance (will/should be the first one only)

  • controller_params (dict) – controller parameters

  • description (dict) – description of the problem

get_convergence_controllers_as_table(description: Dict[str, Any]) → str[source]#

This function is for debugging purposes to keep track of the different convergence controllers and their order.

Parameters:

description (dict) – Description of the problem

Returns:

str – Table of convergence controllers as a string

property hooks: List[Any][source]#

Getter for the hooks

Returns:

pySDC.Hooks.hooks – hooks

return_stats() → Dict[Any, Any][source]#

Return the merged stats from all hooks

Returns:

dict – Merged stats from all hooks

run(u0: Any, t0: float, Tend: float) → Any[source]#

Abstract interface to the run() method

Parameters:
  • u0 – initial values

  • t0 (float) – starting time

  • Tend (float) – ending time

setup_convergence_controllers(description: Dict[str, Any]) → None[source]#

Setup variables needed for convergence controllers, notably a list containing all of them and a list containing their order. Also, we add the CheckConvergence convergence controller, which takes care of maximum iteration count or a residual based stopping criterion, as well as all convergence controllers added to the description.

Parameters:

description (dict) – The description object used to instantiate the controller

Returns:

None

step_is_active(time: float, block_start: float, Tend: float) → bool[source]#

Whether a step starting at time, in a block starting at block_start, still has work.

The default is that a step runs if it starts before the end of the interval, so a block may be run partially. An algorithm that couples its steps too tightly to drop one of them answers this from block_start instead and runs the block whole.

Parameters:
  • time (float) – when this step starts

  • block_start (float) – when the first step of this step’s block starts

  • Tend (float) – ending time

Returns:

bool – whether this step takes part

property steps: List[Any][source]#

Getter for the steps this controller owns.

Controllers that hold the whole block expose them as MS; MPI controllers hold a single step as S. Dispatch on which of those exists rather than on the class name, so that subclasses keep working.

Returns:

list – the steps owned by this controller

welcome_message() → None[source]#

Log the pySDC welcome banner at info level.