Пример #1
0
class DustDynamicsModel(object):
    """
    """
    def __init__(self,
                 disc,
                 diffusion=False,
                 radial_drift=False,
                 viscous_evo=False,
                 evaporation=False,
                 settling=False,
                 Sc=1,
                 t0=0):

        self._disc = disc

        self._visc = None
        if viscous_evo:
            bound = 'power_law'
            # Power law extrapolation fails with zero-density, use simple
            # boundary condition instead
            if evaporation:
                bound = 'Zero'

            self._visc = ViscousEvolution(boundary=bound)

        self._diffusion = None
        if diffusion:
            diffusion = TracerDiffusion(Sc)

        # Diffusion can be handled by the radial drift object, without dust we
        # include it ourself.
        self._radial_drift = None
        if radial_drift:
            self._radial_drift = SingleFluidDrift(diffusion, settling)
        else:
            self._diffusion = diffusion

        self._evaporation = False
        if evaporation:
            self._evaporation = evaporation

        self._t = t0

    def __call__(self, tmax):
        """Evolve the disc for a single timestep

        args:
            dtmax : Upper limit to time-step

        returns:
            dt : Time step taken
        """
        # Compute the maximum time-step
        dt = tmax - self.t
        if self._visc:
            dt = min(dt, self._visc.max_timestep(self._disc))
        if self._radial_drift:
            dt = min(dt, self._radial_drift.max_timestep(self._disc))

        disc = self._disc

        # Do Advection-diffusion update
        if self._visc:
            dust = None
            size = None
            try:
                dust = disc.dust_frac
                size = disc.grain_size
            except AttributeError:
                pass
            self._visc(dt, disc, [dust, size])

        if self._radial_drift:
            self._radial_drift(dt, disc)

        # Pin the values to >= 0:
        disc.Sigma[:] = np.maximum(disc.Sigma, 0)
        disc.dust_frac[:] = np.maximum(disc.dust_frac, 0)

        # Apply any photo-evaporation:
        if self._evaporation:
            self._evaporation(disc, dt)

        # Now we should update the auxillary properties, do grain growth etc
        disc.update(dt)

        self._t += dt
        return dt

    @property
    def disc(self):
        return self._disc

    @property
    def t(self):
        return self._t

    def dump(self, filename):
        """Write the current state to a file, including header information"""

        # Put together a header containing information about the physics
        # included
        head = self.disc.header() + '\n'
        if self._visc:
            head += self._visc.header() + '\n'
        if self._radial_drift:
            head += self._radial_drift.header() + '\n'
        if self._diffusion:
            head += self._diffusion.header() + '\n'
        if self._chem:
            head += self._chem.header() + '\n'

        with open(filename, 'w') as f:
            f.write(head, '# time: {}yr\n'.format(self.t / (2 * np.pi)))

            # Construct the list of variables that we are going to print
            Ncell = self.disc.Ncells

            Ndust = 0
            try:
                Ndust = self.disc.dust_frac.shape[0]
            except AttributeError:
                pass

            head = '# R Sigma T'
            for i in range(Ndust):
                head += ' epsilon[{}]'.format(i)
            for i in range(Ndust):
                head += ' a[{}]'.format(i)
            chem = None
            try:
                chem = self.disc.chem
                for k in chem.gas:
                    head += ' {}'.format(k)
                for k in chem.ice:
                    head += ' s{}'.format(k)
            except AttributeError:
                pass

            f.write(head + '\n')

            R, Sig, T = self.disc.R, self.disc.Sigma, self.disc.T
            for i in range(Ncell):
                f.write('{} {} {}'.format(R[i], Sig[i], T[i]))
                for j in range(Ndust):
                    f.write(' {}'.format(self.disc.dust_frac[j, i]))
                for j in range(Ndust):
                    f.write(' {}', format(self.disc.grain_size[j, i]))
                if chem:
                    for k in chem.gas:
                        f.write(' {}'.format(chem.gas[k][i]))
                    for k in chem.ice:
                        f.write(' {}'.format(chem.ice[k][i]))
                f.write('\n')
Пример #2
0
class ChemoDynamicsModel(object):
    """
    """
    def __init__(self,
                 disc,
                 chem=None,
                 diffusion=False,
                 radial_drift=False,
                 viscous_evo=False,
                 Sc=1,
                 t0=0):

        self._disc = disc
        self._chem = chem

        self._visc = None
        if viscous_evo:
            self._visc = ViscousEvolution()

        self._diffusion = None
        if diffusion:
            diffusion = TracerDiffusion(Sc)

        # Diffusion can be handled by the radial drift object, without dust we
        # include it ourself.
        self._radial_drift = None
        if radial_drift:
            self._radial_drift = SingleFluidDrift(diffusion)
        else:
            self._diffusion = diffusion

        self._t = t0

    def __call__(self, tmax):
        """Evolve the disc for a single timestep

        args:
            dtmax : Upper limit to time-step

        returns:
            dt : Time step taken
        """
        # Compute the maximum time-step
        dt = tmax - self.t
        if self._visc:
            dt = min(dt, self._visc.max_timestep(self._disc))
        if self._radial_drift:
            dt = min(dt, self._radial_drift.max_timestep(self._disc))

        disc = self._disc

        gas_chem, ice_chem = None, None
        try:
            gas_chem = disc.chem.gas.data
            ice_chem = disc.chem.ice.data
        except AttributeError:
            pass

        # Do Advection-diffusion update
        if self._visc:
            dust = None
            try:
                dust = disc.dust_frac
            except AttributeError:
                pass
            self._visc(dt, disc, [dust, gas_chem, ice_chem])

        if self._radial_drift:
            self._radial_drift(dt,
                               disc,
                               gas_tracers=gas_chem,
                               dust_tracers=ice_chem)

        if self._diffusion:
            if gas_chem is not None:
                gas_chem[:] += dt * self._diffusion(disc, gas_chem)
            if ice_chem is not None:
                ice_chem[:] += dt * self._diffusion(disc, ice_chem)

        # Pin the values to >= 0:
        disc.Sigma[:] = np.maximum(disc.Sigma, 0)
        disc.dust_frac[:] = np.maximum(disc.dust_frac, 0)
        if self._chem:
            disc.chem.gas.data[:] = np.maximum(disc.chem.gas.data, 0)
            disc.chem.ice.data[:] = np.maximum(disc.chem.ice.data, 0)

        # Chemistry
        if self._chem:
            rho = disc.midplane_gas_density
            eps = disc.dust_frac.sum(0)
            T = disc.T

            self._chem.update(dt, T, rho, eps, disc.chem)

            # If we have dust, we should update it now the ice fraction has
            # changed
            disc.update_ices(disc.chem.ice)

        # Now we should update the auxillary properties, do grain growth etc
        disc.update(dt)

        self._t += dt
        return dt

    @property
    def disc(self):
        return self._disc

    @property
    def t(self):
        return self._t

    def dump(self, filename):
        """Write the current state to a file, including header information"""

        # Put together a header containing information about the physics
        # included
        head = self.disc.header() + '\n'
        if self._visc:
            head += self._visc.header() + '\n'
        if self._radial_drift:
            head += self._radial_drift.header() + '\n'
        if self._diffusion:
            head += self._diffusion.header() + '\n'
        if self._chem:
            head += self._chem.header() + '\n'

        with open(filename, 'w') as f:
            f.write(head, '# time: {}yr\n'.format(self.t / (2 * np.pi)))

            # Construct the list of variables that we are going to print
            Ncell = self.disc.Ncells

            Ndust = 0
            try:
                Ndust = self.disc.dust_frac.shape[0]
            except AttributeError:
                pass

            head = '# R Sigma T'
            for i in range(Ndust):
                head += ' epsilon[{}]'.format(i)
            for i in range(Ndust):
                head += ' a[{}]'.format(i)
            chem = None
            try:
                chem = self.disc.chem
                for k in chem.gas:
                    head += ' {}'.format(k)
                for k in chem.ice:
                    head += ' s{}'.format(k)
            except AttributeError:
                pass

            f.write(head + '\n')

            R, Sig, T = self.disc.R, self.disc.Sigma, self.disc.T
            for i in range(Ncell):
                f.write('{} {} {}'.format(R[i], Sig[i], T[i]))
                for j in range(Ndust):
                    f.write(' {}'.format(self.disc.dust_frac[j, i]))
                for j in range(Ndust):
                    f.write(' {}', format(self.disc.grain_size[j, i]))
                if chem:
                    for k in chem.gas:
                        f.write(' {}'.format(chem.gas[k][i]))
                    for k in chem.ice:
                        f.write(' {}'.format(chem.ice[k][i]))
                f.write('\n')