def test_chained_parameter_variation(): # A -> B names = ['A', 'B'] rd = ReactionDiffusion(len(names), [], [], k=[], substance_names=names, g_value_parents=[0], g_values=[[0, 1]], param_names=['doserate']) durations = [1., 3., 2.] y0 = [13., 7.] ic = dict(zip(names, y0)) doserates = [.3, .11, .7] npoints = 3 odesys = rd._as_odesys(variables_from_params=dict( density=lambda self, params: 1.0 )) res = odesys.chained_parameter_variation( durations, ic, {'doserate': doserates}, npoints=npoints, integrate_kwargs=dict(atol={k: 1e-8 for k in odesys.names})) assert res.xout.size == npoints*len(durations) + 1 assert res.xout[0] == 0 assert np.all(res.yout[0, :] == y0) expected = [.3]*npoints + [.11]*npoints + [.7]*(npoints+1) assert np.all(res.params[:, odesys.param_names.index('doserate')] == expected) cumulative = 0.0 for dr, dur in zip(doserates, durations): mask = (cumulative <= res.xout) & (res.xout <= cumulative + dur) cumulative += dur t, y = res.xout[mask], res.yout[mask, :] a, b = y[:, 0], y[:, 1] refa = a[0] refb = b[0] + (t - t[0])*dr*a[0] assert np.allclose(refa, a) assert np.allclose(refb, b) res.extend_by_integration(np.sum(durations)+1, dict(doserate=doserates[-1]), integrator='cvode') assert abs(res.yout[-1, 1] - (refb[-1] + doserates[-1]*a[0])) < 1e-8
def _get_odesys(): names = ['A', 'B', 'C'] pns = ['kA', 'kB'] rd = ReactionDiffusion(len(names), [[0], [1]], [[1], [2]], k=[0, 0], substance_names=names, param_names=pns) return rd._as_odesys(k_from_params=lambda self, p: [p[k] for k in self.param_names])