def test_solver_linear_error_from_integration(atol): class Dummy: unit_registry = None def expb(self, x): return np.exp(x) integr = Dummy() integr.yout = np.array([1.0]).reshape((1, 1, 1)) print(integr.yout[slice(None), 0, 0]) integr.info = {'rtol': 1.0, 'atol': atol} integr.rd = Dummy() integr.rd.logy = False assert np.allclose(solver_linear_error_from_integration(integr), [[-1], [3]])
def plot_solver_linear_excess_error(integration, Cref, ax=None, x=None, ti=slice(None), bi=0, si=0, **kwargs): """ Plots the excess error commited by the intergrator, divided by the span of the tolerances (atol + rtol*|y_i|). Parameters ---------- integration: chemreac.integrate.Integration result from integration. Cref: array or float analytic solution to compare with ax: Axes instance or dict if ax is a dict it is used as \*\*kwargs passed to matplotlib.pyplot.axes (default: None) x: array (optional) x-values, when None it is deduced to be either t or x (when ti or bi are slices repecitvely) (default: None) ti: slice time indices bi: slice bin indices si: integer specie index plot_kwargs: dict keyword arguments passed to matplotlib.pyplot.plot (default: None) fill_between_kwargs: dict keyword arguments passed to matplotlib.pyplot.fill_between (default: None) scale_err: float value with which errors are scaled. (default: 1.0) fill: bool whether or not to fill error span \*\*kwargs: common keyword arguments of plot_kwargs and fill_between_kwargs, e.g. 'color', (default: None). See Also -------- plot_solver_linear_error """ if x is None: if isinstance(ti, slice): x = integration.tout[ti] elif isinstance(bi, slice): x = integration.rd.xcenters[bi] else: raise NotImplementedError("Failed to deduce x-axis.") ax = _init_axes(ax) le_l, le_u = solver_linear_error_from_integration(integration, ti, bi, si) Eexcess_l = Cref[ti, bi, si] - le_l # Excessive if negative Eexcess_u = Cref[ti, bi, si] - le_u # Excessive if positive u_conc = get_derived_unit(integration.rd.unit_registry, "concentration") Eexcess_l[np.argwhere(Eexcess_l >= 0)] = 0 * u_conc Eexcess_u[np.argwhere(Eexcess_u <= 0)] = 0 * u_conc fused = np.concatenate((Eexcess_l[..., np.newaxis], Eexcess_u[..., np.newaxis]), axis=-1) indices = np.argmax(abs(fused), axis=-1) Eexcess = fused[np.indices(indices.shape), indices][0, ...] le_span = le_u - le_l ax.plot(np.asarray(integration.tout), np.asarray(Eexcess / le_span), **kwargs) return ax
def plot_solver_linear_error( integration, Cref=0, ax=None, x=None, ti=slice(None), bi=0, si=0, plot_kwargs=None, fill_between_kwargs=None, scale_err=1.0, fill=True, **kwargs ): """ Parameters ---------- integration: chemreac.integrate.Integration result from integration. Cref: array or float analytic solution to compare with ax: Axes instance or dict if ax is a dict it is used as key word arguments passed to matplotlib.pyplot.axes (default: None) x: array (optional) x-values, when None it is deduced to be either t or x (when ti or bi are slices repecitvely) (default: None) ti: slice time indices bi: slice bin indices si: integer specie index plot_kwargs: dict keyword arguments passed to matplotlib.pyplot.plot (default: None) fill_between_kwargs: dict keyword arguments passed to matplotlib.pyplot.fill_between (default: None) scale_err: float value with which errors are scaled. (default: 1.0) fill: bool whether or not to fill error span \*\*kwargs common keyword arguments of plot_kwargs and fill_between_kwargs, e.g. 'color', (default: None). See Also -------- plot_solver_linear_excess_error """ ax = _init_axes(ax) Cerr = integration.Cout - to_unitless(Cref, get_derived_unit(integration.rd.unit_registry, "concentration")) if x is None: if isinstance(ti, slice): x = integration.tout[ti] elif isinstance(bi, slice): x = integration.rd.xcenters[bi] else: raise NotImplementedError("Failed to deduce x-axis.") plot_kwargs = plot_kwargs or {} set_dict_defaults_inplace(plot_kwargs, kwargs) plt.plot(np.asarray(x), np.asarray(scale_err * Cerr[ti, bi, si]), **plot_kwargs) if fill: le_l, le_u = solver_linear_error_from_integration(integration, ti=ti, bi=bi, si=si) Cerr_u = le_u - Cref[ti, bi, si] Cerr_l = le_l - Cref[ti, bi, si] fill_between_kwargs = fill_between_kwargs or {} set_dict_defaults_inplace(fill_between_kwargs, {"alpha": 0.2}, kwargs) plt.fill_between( np.asarray(x), np.asarray(scale_err * Cerr_l), np.asarray(scale_err * Cerr_u), **fill_between_kwargs ) return ax