core.CCModel
core.CCModel(
variable_name,
state_variables=None,
non_integrated_state_vars=None,
diagnostic_variables=None,
)The overarching model structure for ClimateCritters.
CCModel serves as the archetype/parent class for models within the model_critters directory. It is not meant to be instantiated directly.
Parameter handling
Models may define a param_values dict that maps parameter names to constants, callables, or Forcing objects. Use get_param_value(name, t, state) inside dydt to resolve any of these uniformly.
To make a parameter state- or time-dependent after construction, assign a callable via set_param_value::
model.set_param_value('rho', lambda t, state: 28.0 + 0.1 * state[0])
To replace a computation method (e.g. calc_albedo) on a single instance without subclassing, use set_function.
External forcings
Use register_forcing to attach a time-varying external driver to any named parameter or state variable after construction::
model.register_forcing('S0', forcing_obj) # parameter
model.register_forcing('x', forcing_obj, 'additive', timing='pre') # state
See register_forcing for the full contract and default timing rules.
Methods
| Name | Description |
|---|---|
| clear_forcings | Remove registered forcings. |
| doc | Pretty-print documentation for the requested category. |
| dydt | Define the system of differential equations. |
| get_forcings | Return registered forcings, optionally filtered by variable name. |
| get_param_value | Resolve a named parameter to its value at the current time and state. |
| get_param_vector | Resolve a parameter and broadcast it to a fixed-length vector. |
| integrate | Integrate the model over a time span and return a :class:CCOutput. |
| list | Return a list of names for the requested category. |
| populate_diagnostics_from_history | Compute diagnostic variables from the full solved trajectory. |
| post_integrate | Orchestrate post-solve output construction for uses_post_history models. |
| register_forcing | Attach an external forcing to a named parameter or state variable. |
| set_function | Swap out a model calculation function on a single instance. |
| set_param_value | Add or update a parameter and keep the attribute and param_values in sync. |
| validate_initial_state | Validate and normalize the initial state vector. |
clear_forcings
core.CCModel.clear_forcings(var_name=None)Remove registered forcings.
Parameters
var_name : str = None-
If given, clear only the forcings for that variable. If omitted, clear all forcings on the model.
doc
core.CCModel.doc(print_target)Pretty-print documentation for the requested category.
Descriptions are parsed from the NumPy-style docstrings of the class and its base classes. For parameters the current value is also shown.
Parameters
print_target : (state_variables,parameters,diagnostic_variables) = 'state_variables'-
The category to document.
dydt
core.CCModel.dydt(t, y)Define the system of differential equations.
Must be overridden by every subclass. The solver calls this at each timestep with the current time t and state vector y, and expects a list of derivatives of the same length as y. Use get_param inside the implementation to access parameters.
get_forcings
core.CCModel.get_forcings(var_name=None)Return registered forcings, optionally filtered by variable name.
Parameters
var_name : str = None-
If given, return the list of
ForcingSpecobjects for that variable. If omitted, return the full_forcingsdict.
get_param_value
core.CCModel.get_param_value(name, t, state)Resolve a named parameter to its value at the current time and state.
This is the standard way to access parameters inside dydt. It looks up the value from param_values by name and delegates resolution to _resolve_param, so callers in dydt don’t need to know whether a parameter is stored as a constant, a callable, or a Forcing object.
get_param_vector
core.CCModel.get_param_vector(name, t, state, size)Resolve a parameter and broadcast it to a fixed-length vector.
Spatial models often allow parameters to be either a single scalar (applied uniformly) or a full grid-length array. This method resolves the parameter via get_param and then either broadcasts a scalar or validates that an array has the expected size, eliminating that boilerplate from every dydt that works on a spatial grid.
integrate
core.CCModel.integrate(
t_span=None,
y0=None,
method='RK45',
dt=None,
output_time=None,
run_name=None,
kwargs=None,
)Integrate the model over a time span and return a :class:CCOutput.
Parameters
t_span : tuple of float = None-
(t0, tf)integration bounds for the solver. y0 : array -like= None-
Initial conditions. Length must match the number of integrated state variables.
method : str = 'RK45'-
Solver to use:
'RK45'(default),'euler','euler_maruyama','heun_maruyama','milstein','rk4', or any method accepted byscipy.integrate.solve_ivp. SDE solver guidance: *'euler_maruyama'— strong order 0.5; baseline stochastic. *'heun_maruyama'— strong order 1.0 for additive noise (diffusion independent of state); preferred for models like Melcher et al. (2025). *'milstein'— strong order 1.0 for multiplicative noise (diffusion depends on state); uses a finite-difference approximation of∂g/∂y, so no analytical Jacobian is required. dt : float = None-
Fixed timestep for
euler,euler_maruyama, andrk4. Required for those methods. output_time : array -like= None-
If provided, the returned
CCOutputis immediately reframed onto this time axis (e.g. to exclude a spin-up period).output.model_timealways retains the raw solver grid. run_name : str = None-
Label stored on the output. Defaults to
'<method>, dt=<dt>'. kwargs : dict = None-
Additional solver options. For
solve_ivpmethods these are forwarded directly (e.g.rtol,atol,t_eval). Foreuler_maruyama,random_seedis extracted here. Forrk4,si(sampling interval) is extracted here. .. deprecated:: Passingdtinsidekwargsis deprecated. Use the explicitdtparameter instead.
list
core.CCModel.list(list_target)Return a list of names for the requested category.
Parameters
list_target : (state_variables,parameters,diagnostic_variables) = 'state_variables'-
The category to enumerate.
Returns
names : list of str
populate_diagnostics_from_history
core.CCModel.populate_diagnostics_from_history(time, history)Compute diagnostic variables from the full solved trajectory.
Called by post_integrate for models where uses_post_history = True. The base implementation does nothing because diagnostics are model-specific; subclasses override this to derive any quantities that can only be computed once the complete trajectory is available (e.g. derived fields, fluxes).
post_integrate
core.CCModel.post_integrate(time, history)Orchestrate post-solve output construction for uses_post_history models.
Some models (e.g. spatial PDEs) cannot accumulate state during the solve without side effects; instead they store the full trajectory and derive all outputs here. This method sequences the required steps in the correct order: build the structured state array, set the time axis, populate diagnostics, and convert diagnostic lists to arrays. It is called automatically by integrate when uses_post_history = True.
register_forcing
core.CCModel.register_forcing(
var_name,
forcing_object,
attachment_style=None,
timing=None,
)Attach an external forcing to a named parameter or state variable.
Parameters
var_name : str-
Name of the target. Must exist in
param_values(parameter namespace) orstate_variables_names(state namespace). If the name appears in both, aValueErroris raised — this is a model design issue worth resolving explicitly. forcing_object :-
A
Forcinginstance, a callablef(t)→ scalar/array, or any object with aget_forcing(t)method. attachment_style : (replacement,additive) = "replacement"-
How the forcing value is applied. * Parameters default to
"replacement"."additive"is also supported and adds the forcing value to the nominal parameter at each step (e.g.k = k_0 + ε(t)). * State variables have no default —attachment_styleis required. This is intentional: injecting into a live state variable is a significant physical choice that should be explicit. timing : (pre,post) = "pre"-
When the forcing is applied relative to the integration step. Derived automatically in most cases: * parameter + any style →
"pre"(always; no override) * state + replacement →"post"(always; warns if"pre"passed) * state + additive → required; raise if not provided
Raises
: ValueError-
If
var_nameis not found, ifattachment_styleis missing for a state variable, iftimingis missing for state + additive, or if a second"replacement"is registered on the same variable.
set_function
core.CCModel.set_function(name, function, bind=None)Swap out a model calculation function on a single instance.
Subclassing is the right approach when a different formulation should apply everywhere, but for one-off experiments (e.g. testing an alternative albedo scheme without writing a new class) it is useful to replace a single method on one instance. The bind parameter handles whether the replacement expects self as its first argument.
Parameters
set_param_value
core.CCModel.set_param_value(name, value)Add or update a parameter and keep the attribute and param_values in sync.
__setattr__ syncs the direction model.alpha = v → param_values, but only for names already in param_values. This method handles the reverse and covers inserting new parameters that weren’t declared at initialization.
validate_initial_state
core.CCModel.validate_initial_state(y0)Validate and normalize the initial state vector.
Exists as a method so that subclasses with non-standard initial state requirements (e.g. a spatially discretised model that accepts a scalar and broadcasts it to the grid) can override it. The base implementation delegates to the utility in utils/solver.