def test_coloured_spy(): from matplotlib.axes import Axes A = np.arange(9).reshape((3, 3)) for log in (False, True, -5): ax_im, ax_cb = coloured_spy(A, log=log) assert isinstance(ax_im, Axes) assert isinstance(ax_cb, Axes)
def integrate_rd(tend=10.0, N=1, nt=500, jac_spy=False, linear_solver='default', logy=False, logt=False, plot=False, savefig='None', verbose=False, graph=False, **kwargs): """ Integrates the reaction system defined by :download:`four_species.json <examples/four_species.json>` """ rd = load(os.path.join(os.path.dirname( __file__), 'four_species.json'), N=N, x=N, logy=logy, logt=logt) y0 = np.array([1.3, 1e-4, 0.7, 1e-4]) y0 = np.concatenate([y0/(i+1)*(0.25*i**2+1) for i in range(N)]) t0 = 1e-10 if linear_solver == 'default': if rd.N == 1: linear_solver = 'dense' elif rd.N > 1: linear_solver = 'banded' if linear_solver not in ('dense', 'banded'): raise NotImplementedError("dense or banded linear_solver") import matplotlib.pyplot as plt if jac_spy: fout = np.empty(rd.n*rd.N) rd.f(t0, y0, fout) print(fout) if linear_solver == 'dense': jout = np.zeros((rd.n*rd.N, rd.n*rd.N), order='F') rd.dense_jac_cmaj(t0, y0, jout) coloured_spy(np.log(np.abs(jout))) elif linear_solver == 'banded': # note rd.n*3 needed in call from scipy.integrate.ode jout = np.zeros((rd.n*2+1, rd.n*rd.N), order='F') rd.banded_packed_jac_cmaj(t0, y0, jout) coloured_spy(np.log(np.abs(jout))) print(jout) plt.show() else: tout = np.linspace(t0, tend, nt) integr = run(rd, y0, tout, **kwargs) if verbose: print(integr.info) if plot: plt.figure(figsize=(6, 4)) for i, l in enumerate('ABCD'): plt.plot(integr.tout, integr.Cout[:, 0, i], label=l) plt.title("Time evolution of concentrations") plt.legend() save_and_or_show_plot(savefig=savefig) plt.figure(figsize=(6, 10)) plot_jacobian( rd, np.log(integr.tout) if rd.logt else integr.tout, np.log(integr.Cout) if rd.logy else integr.Cout, 'ABCD', lintreshy=1e-10 ) plt.tight_layout() if savefig != 'None': base, ext = os.path.splitext(savefig) savefig = base + '_jacobian' + ext save_and_or_show_plot(savefig=savefig) plt.figure(figsize=(6, 10)) plot_per_reaction_contribution( integr, 'ABCD' ) plt.tight_layout() if savefig != 'None': savefig = base + '_per_reaction' + ext save_and_or_show_plot(savefig=savefig) if graph: print(rsys2graph(ReactionSystem.from_ReactionDiffusion(rd, 'ABCD'), 'four_species_graph.png', save='.')) return integr
def test_ReactionDiffusion__3_reactions_4_species_5_bins_k_factor( geom_refl): # UNSUPPORTED since `bin_k_factor` was replaced with `fields` # if a real world scenario need per bin modulation of binary # reactions and the functionality is reintroduced, this test # is useful from sympy import finite_diff_weights geom, refl = geom_refl lrefl, rrefl = refl # r[0]: A + B -> C # r[1]: D + C -> D + A + B # r[2]: B + B -> D # r[0] r[1] r[2] stoich_active = [[0, 1], [2, 3], [1, 1]] stoich_prod = [[2], [0, 1, 3], [3]] n = 4 N = 5 D = np.array([2.6, 3.7, 5.11, 7.13])*213 y0 = np.array([ 2.5, 1.2, 3.2, 4.3, 2.7, 0.8, 1.6, 2.4, 3.1, 0.3, 1.5, 1.8, 3.3, 0.6, 1.6, 1.4, 3.6, 0.9, 1.7, 1.2 ]).reshape((5, 4)) x = np.array([11.0, 13.3, 17.0, 23.2, 29.8, 37.2]) xc_ = x[:-1]+np.diff(x)/2 xc_ = [x[0]-(xc_[0]-x[0])]+list(xc_)+[x[-1]+(x[-1]-xc_[-1])] assert len(xc_) == 7 k = [31.0, 37.0, 41.0] # (r[0], r[1]) modulations over bins modulated_rxns = [0, 1] modulation = [[i+3 for i in range(N)], [i+4 for i in range(N)]] nstencil = 3 nsidep = 1 rd = ReactionDiffusion( 4, stoich_active, stoich_prod, k, N, D=D, x=x, geom=geom, nstencil=nstencil, lrefl=lrefl, rrefl=rrefl, modulated_rxns=modulated_rxns, modulation=modulation) assert np.allclose(xc_, rd.xc) lb = stencil_pxci_lbounds(nstencil, N, lrefl, rrefl) if lrefl: if rrefl: assert lb == [0, 1, 2, 3, 4] else: assert lb == [0, 1, 2, 3, 3] else: if rrefl: assert lb == [1, 1, 2, 3, 4] else: assert lb == [1, 1, 2, 3, 3] assert lb == list(map(rd._stencil_bi_lbound, range(N))) pxci2bi = pxci_to_bi(nstencil, N) assert pxci2bi == [0, 0, 1, 2, 3, 4, 4] assert pxci2bi == list(map(rd._xc_bi_map, range(N+2))) D_weight = [] for bi in range(N): local_x_serie = xc_[lb[bi]:lb[bi]+nstencil] local_x_around = xc_[nsidep+bi] w = finite_diff_weights( 2, local_x_serie, x0=local_x_around ) D_weight.append(w[-1][-1]) if geom == 'f': pass elif geom == 'c': for wi in range(nstencil): # first order derivative D_weight[bi][wi] += w[-2][-1][wi]*1/local_x_around elif geom == 's': for wi in range(nstencil): # first order derivative D_weight[bi][wi] += w[-2][-1][wi]*2/local_x_around else: raise RuntimeError assert np.allclose(rd.D_weight, np.array(D_weight, dtype=np.float64).flatten()) def cflux(si, bi): f = 0.0 for k in range(nstencil): f += rd.D_weight[bi*nstencil+k]*y0[pxci2bi[lb[bi]+k], si] return D[si]*f r = [ [k[0]*modulation[0][bi]*y0[bi, 0]*y0[bi, 1] for bi in range(N)], [k[1]*modulation[1][bi]*y0[bi, 3]*y0[bi, 2] for bi in range(N)], [k[2]*y0[bi, 1]**2 for bi in range(N)], ] fref = np.array([[ -r[0][bi] + r[1][bi] + cflux(0, bi), -r[0][bi] + r[1][bi] - 2*r[2][bi] + cflux(1, bi), r[0][bi] - r[1][bi] + cflux(2, bi), r[2][bi] + cflux(3, bi) ] for bi in range(N)]).flatten() # Now let's check that the Jacobian is correctly computed. def dfdC(bi, lri, lci): v = 0.0 for ri in range(len(stoich_active)): totl = (stoich_prod[ri].count(lri) - stoich_active[ri].count(lri)) if totl == 0: continue actv = stoich_active[ri].count(lci) if actv == 0: continue v += actv*totl*r[ri][bi]/y0[bi, lci] return v def jac_elem(ri, ci): bri, bci = ri // n, ci // n lri, lci = ri % n, ci % n elem = 0.0 def _diffusion(): _elem = 0.0 for k in range(nstencil): if pxci2bi[lb[bri]+k] == bci: _elem += D[lri]*rd.D_weight[bri*nstencil+k] return _elem if bri == bci: # on block diagonal elem += dfdC(bri, lri, lci) if lri == lci: elem += _diffusion() elif bri == bci - 1: if lri == lci: elem = _diffusion() elif bri == bci + 1: if lri == lci: elem = _diffusion() return elem jref = np.zeros((n*N, n*N), order='C') for ri, ci in np.ndindex(n*N, n*N): jref[ri, ci] = jac_elem(ri, ci) # Compare to what is calculated using our C++ callback _test_f_and_dense_jac_rmaj(rd, 0, y0.flatten(), fref, jref) jout_cmaj = np.zeros((n*N, n*N), order='F') rd.dense_jac_cmaj(0.0, y0.flatten(), jout_cmaj) assert np.allclose(jout_cmaj, jref) ref_banded_j = get_banded(jref, n, N) ref_banded_j_symbolic = rd.alloc_jout(order='F', pad=0) symrd = SymRD.from_rd(rd) symrd.banded_jac(0.0, y0.flatten(), ref_banded_j_symbolic) assert np.allclose(ref_banded_j_symbolic, ref_banded_j) jout_bnd_packed_cmaj = np.zeros((3*n+1, n*N), order='F') rd.banded_jac_cmaj(0.0, y0.flatten(), jout_bnd_packed_cmaj) if os.environ.get('plot_tests', False): import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from chemreac.util.plotting import coloured_spy fig = plt.figure() ax = fig.add_subplot(3, 1, 1) coloured_spy(ref_banded_j, ax=ax) plt.title('ref_banded_j') ax = fig.add_subplot(3, 1, 2) coloured_spy(jout_bnd_packed_cmaj[n:, :], ax=ax) plt.title('jout_bnd_packed_cmaj') ax = fig.add_subplot(3, 1, 3) coloured_spy(ref_banded_j-jout_bnd_packed_cmaj[n:, :], ax=ax) plt.title('diff') plt.savefig(__file__+'.png') assert np.allclose(jout_bnd_packed_cmaj[n:, :], ref_banded_j)