Ejemplo n.º 1
0
    def _integrate(self):
        """
        Performs the integration by calling the callback chosen by
        :attr:`integrator`. If rd.logy == True, a transformation of self.C0 to
        log_b(C0) will be performed before running the integration (the same
        is done for self.tout / rd.logt == True).

        After the integration is done the attributes `Cout`, `info` and `yout`
        are set. Cout is guaranteed to be linear concentrations (transformed
        from yout by calling exp if rd.logy==True) and yout is the unprocessed
        output from the integrator.
        """
        # Pre-processing
        # --------------
        C0 = self.C0

        # Transform initial concentrations
        if self.rd.logy:
            if not self.C0_is_log:
                C0 = self.rd.logb(C0 + self.tiny)

            if self.sigm_damp is True:
                y0 = sigm(C0)
            elif isinstance(self.sigm_damp, tuple):
                y0 = sigm(C0, *self.sigm_damp)
            else:
                y0 = C0
        else:
            if self.C0_is_log:
                if self.sigm_damp is True:
                    y0 = self.rd.expb(sigm(C0))
                elif isinstance(self.sigm_damp, tuple):
                    y0 = self.rd.expb(sigm(C0, *self.sigm_damp))
                else:
                    y0 = self.rd.expb(C0)
            else:
                y0 = C0

        # Transform time
        tout = self.tout
        if tout[0] == 0.0 and self.rd.logt:
            t0_set = True
            t0 = suggest_t0(self.rd, y0)
            t = self.rd.logb(tout + t0)  # conserve total time
        else:
            t0_set = False
            t = self.rd.logb(tout) if self.rd.logt else tout

        # Run the integration
        # -------------------
        self.yout, self.internal_t, self.info = self._callbacks[self.integrator](self.rd, y0, t, **self.kwargs)
        self.info['t0_set'] = t0 if t0_set else False

        # Post processing
        # ---------------
        # Back-transform independent variable into linear time
        if self.rd.logt:
            self.tout = (self.rd.expb(self.internal_t) - (t0 if t0_set else 0))
        else:
            self.tout = self.internal_t

        # Back-transform integration output into linear concentration
        self.Cout = self.rd.expb(self.yout) if self.rd.logy else self.yout
Ejemplo n.º 2
0
def integrate_rd(tend=1e2, A0=1.0, B0=0.0, C0=0.0, k1=0.04, k2=1e4, k3=3e7,
                 t0=1e2, nt=100, N=1, nstencil=3, logt=False, logy=False,
                 plot=False, savefig='None', verbose=False, dump_expr='False',
                 use_chempy=False, D=2e-3):
    if N == 1:
        init_conc = (A0, B0, C0)
    else:
        init_conc = np.tile((A0, B0, C0), (N, 1))
        init_conc /= np.linspace(1, 2, N).reshape((N, 1))**.5

    rsys = ReactionSystem(get_reactions((k1, k2, k3)), 'ABC')
    if verbose:
        print([str(_) for _ in rsys.rxns])
    if use_chempy:
        from chempy.kinetics.ode import get_odesys
        odesys = get_odesys(rsys, include_params=True)
        if N != 1:
            raise ValueError("ChemPy does not support diffusion")
        odesys.integrate(np.logspace(log10(t0), log10(tend)), init_conc)
        if plot:
            odesys.plot_result(xscale='log', yscale='log')
        result = None
    else:
        rd = ReactionDiffusion.from_ReactionSystem(
            rsys, N=N, nstencil=1 if N == 1 else nstencil, logt=logt,
            logy=logy, D=[D/2, D/3, D/5])

        if dump_expr.lower() not in ('false', '0'):
            from chemreac.symbolic import SymRD
            import sympy as sp
            cb = {'latex': sp.latex,
                  'ccode': sp.ccode}.get(dump_expr.lower(), str)
            srd = SymRD.from_rd(rd, k=sp.symbols('k:3'))
            print('dydx:')
            print('\n'.join(map(cb, srd._f)))
            print('jac:')
            for ri, row in enumerate(srd.jacobian.tolist()):
                for ci, expr in enumerate(row):
                    if expr == 0:
                        continue
                    print(ri, ci, cb(expr))
            return None

        if t0 == 0 and logt:
            t0 = 1e-3*suggest_t0(rd, init_conc)
            if verbose:
                print("Using t0 = %12.5g" % t0)

        t = np.logspace(np.log10(t0), np.log10(tend), nt)
        print(t[0], t[-1])
        integr = run(rd, init_conc, t)

        if verbose:
            import pprint
            pprint.pprint(integr.info)

        if plot:
            if N == 1:
                plot_C_vs_t(integr, xscale='log', yscale='log')
            else:
                import matplotlib.pyplot as plt
                for idx, name in enumerate('ABC', 1):
                    plt.subplot(1, 3, idx)
                    rgb = [.5, .5, .5]
                    rgb[idx-1] = 1
                    plot_faded_time(integr, name, rgb=rgb, log_color=True)
        result = integr

    if plot:
        save_and_or_show_plot(savefig=savefig)

    return result