コード例 #1
0
    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
コード例 #2
0
def test_LP_model():
    alpha = 5e-3

    M = 1e-2 * Msun
    Rd = 30.
    T0 = (2 * np.pi)
    N = 100

    grid = Grid(1.0, 1000, N, spacing='natural')
    star = SimpleStar()
    eos = LocallyIsothermalEOS(star, 1 / 30., -0.25, alpha)
    eos.set_grid(grid)

    nud = np.interp(Rd, grid.Rc, eos.nu)
    sol = LBP_Solution(M, Rd, nud, 1)

    Sigma = sol(grid.Rc, 0.)

    disc = AccretionDisc(grid, star, eos, Sigma)

    visc = ViscousEvolution()

    yr = 2*np.pi
    
    # Integrate to specfi

    times = np.logspace(0, 6, 7)*yr

    max_err   = [3.6e-4, 3.6e-3, 3.6e-2, 3.6e-1, 2.2, 7.9, 17.5]

    t = 0
    for i, ti in enumerate(times):
        while t < ti:
            dt = visc.max_timestep(disc)
            dti = min(dt, ti - t)

            visc(dti, disc)

            t = min(t + dt, ti)

        # Check L1, L2 and max norm
        exact = sol(grid.Rc, t)
        error = (exact - disc.Sigma) / exact.mean()

        L1   = np.linalg.norm(error, ord=1) 

        assert(L1   < max_err[i])
コード例 #3
0
    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
コード例 #4
0
def setup_model(model,
                disc,
                history,
                start_time=0,
                internal_photo_type="Primordial",
                R_hole=None):
    '''Setup the physics of the model'''

    gas = None
    dust = None
    diffuse = None
    chemistry = None

    if model['transport']['gas']:
        try:
            gas = ViscousEvolution(boundary=model['grid']['outer_bound'],
                                   in_bound=model['grid']['inner_bound'])
        except KeyError:
            print("Default boundaries")
            gas = ViscousEvolution(boundary='Mdot_out')

    if model['transport']['diffusion']:
        diffuse = TracerDiffusion(Sc=model['disc']['Schmidt'])
    if model['transport']['radial drift']:
        dust = SingleFluidDrift(diffuse)
        diffuse = None

    # Inititate the correct external photoevaporation routine
    # FRIED should be considered default
    try:
        p = model['fuv']
    except KeyError:
        p = model['uv']
    if start_time > 0:
        _, Mcum_gas = history.mass
        _, Mcum_dust = history.mass_dust
        Mcum_gas = Mcum_gas[-1]
        Mcum_dust = Mcum_dust[-1]
    else:
        Mcum_gas = 0.0
        Mcum_dust = 0.0
    if (p['photoevaporation'] == "Constant"):
        photoevap = photoevaporation.FixedExternalEvaporation(disc, 1e-9)
    elif (p['photoevaporation'] == "FRIED" and disc.FUV > 0):
        # Using 2DMS at 400 au
        photoevap = photoevaporation.FRIEDExternalEvaporationMS(
            disc, Mcum_gas=Mcum_gas, Mcum_dust=Mcum_dust)
    elif (p['photoevaporation'] == "FRIED" and disc.FUV <= 0):
        photoevap = None
    elif (p['photoevaporation'] == "Integrated"):
        # Using integrated M(<R), extrapolated to M400
        photoevap = photoevaporation.FRIEDExternalEvaporationM(
            disc, Mcum_gas=Mcum_gas, Mcum_dust=Mcum_dust)
    elif (p['photoevaporation'] == "None"):
        photoevap = None
    else:
        print("Photoevaporation Mode Unrecognised: Default to 'None'")
        photoevap = None

    # Add internal photoevaporation
    try:
        if model['x-ray']['L_X'] > 0:
            try:
                photomodel = model['x-ray']['model']
            except KeyError:
                photomodel = 'Picogna'
            InnerHole = internal_photo_type.startswith('InnerHole')
            if InnerHole:
                if photomodel == 'Picogna':
                    internal_photo = XrayDiscPicogna(disc,
                                                     Type='InnerHole',
                                                     R_hole=R_hole)
                elif photomodel == 'Owen':
                    internal_photo = XrayDiscOwen(disc,
                                                  Type='InnerHole',
                                                  R_hole=R_hole)
                else:
                    print(
                        "Photoevaporation Mode Unrecognised: Default to 'None'"
                    )
                    internal_photo = None
            else:
                if photomodel == 'Picogna':
                    internal_photo = XrayDiscPicogna(disc)
                elif photomodel == 'Owen':
                    internal_photo = XrayDiscOwen(disc)
                else:
                    print(
                        "Photoevaporation Mode Unrecognised: Default to 'None'"
                    )
                    internal_photo = None
                if internal_photo and R_hole:
                    internal_photo._Hole = True
        elif model['euv']['Phi'] > 0:
            InnerHole = internal_photo_type.startswith('InnerHole')
            if InnerHole:
                internal_photo = EUVDiscAlexander(disc, Type='InnerHole')
            else:
                internal_photo = EUVDiscAlexander(disc)
                if R_hole:
                    internal_photo._Hole = True
        else:
            internal_photo = None
    except KeyError:
        internal_photo = None

    return DiscEvolutionDriver(disc,
                               gas=gas,
                               dust=dust,
                               diffusion=diffuse,
                               ext_photoevaporation=photoevap,
                               int_photoevaporation=internal_photo,
                               history=history,
                               t0=start_time)
コード例 #5
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')
コード例 #6
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')