Beispiel #1
0
def _velocity(field, data, idir, prefix=None):
    """Velocity = linear momentum / density"""
    # This is meant to be used with functools.partial to produce
    # functions with only 2 arguments (field, data)
    # idir : int
    #    the direction index (1, 2 or 3)
    # prefix : str
    #    used to generalize to dust fields
    if prefix is None:
        prefix = ""
    moment = data["gas", "%smoment_%d" % (prefix, idir)]
    rho = data["gas", f"{prefix}density"]

    mask1 = rho == 0
    if mask1.any():
        mylog.info(
            "zeros found in %sdensity, "
            "patching them to compute corresponding velocity field.",
            prefix,
        )
        mask2 = moment == 0
        if not ((mask1 & mask2) == mask1).all():
            raise RuntimeError
        rho[mask1] = 1
    return moment / rho
Beispiel #2
0
 def check_model(self):
     n = len(self.ee)
     rho = np.zeros(n)
     rho_int = lambda e, psi: self.f(e)*np.sqrt(2*(psi-e))
     for i, e in enumerate(self.ee[::-1]):
         rho[i] = 4.*np.pi*quad(rho_int, 0., e, args=(e))[0]
     chk = np.abs(rho-self.pden)/self.pden
     mylog.info("The maximum relative deviation of this profile from "
                "virial equilibrium is %g" % np.abs(chk).max())
     return rho, chk
Beispiel #3
0
    def from_scratch(cls, num_particles, rmin, rmax, profile,
                     num_points=1000):

        rr = np.logspace(np.log10(rmin), np.log10(rmax), num_points, endpoint=True)

        pden = profile(rr)
        mylog.info("Integrating dark matter mass profile.")
        mdm = integrate_mass(profile, rr)
        mylog.info("Integrating gravitational potential profile.")
        gpot_profile = lambda r: profile(r)*r
        gpot = G.v*(mdm/rr + 4.*np.pi*integrate_toinf(gpot_profile, rr))

        return cls(num_particles, rr, gpot, pden, mdm)
 def check_model(self):
     r"""
     Determine the deviation of the model from hydrostatic equilibrium. Returns
     an array containing the relative deviation at each radius or height.
     """
     xx = self.fields[self.x_field].v
     pressure_spline = InterpolatedUnivariateSpline(xx, self.fields["pressure"].v)
     dPdx = YTArray(pressure_spline(xx, 1), "Msun/(Myr**2*kpc**2)")
     rhog = self.fields["density"] * self.fields["gravitational_field"]
     chk = dPdx - rhog
     chk /= rhog
     mylog.info(
         "The maximum relative deviation of this profile from " "hydrostatic equilibrium is %g" % np.abs(chk).max()
     )
     return chk
Beispiel #5
0
    def setup_fluid_fields(self):

        setup_magnetic_field_aliases(self, "amrvac",
                                     [f"mag{ax}" for ax in "xyz"])
        self._setup_velocity_fields()  # gas velocities
        self._setup_dust_fields()  # dust derived fields (including velocities)

        # fields with nested dependencies are defined thereafter
        # by increasing level of complexity
        us = self.ds.unit_system

        def _kinetic_energy_density(field, data):
            # devnote : have a look at issue 1301
            return 0.5 * data["gas", "density"] * data["gas",
                                                       "velocity_magnitude"]**2

        self.add_field(
            ("gas", "kinetic_energy_density"),
            function=_kinetic_energy_density,
            units=us["density"] * us["velocity"]**2,
            dimensions=dimensions.density * dimensions.velocity**2,
            sampling_type="cell",
        )

        # magnetic energy density
        if ("amrvac", "b1") in self.field_list:

            def _magnetic_energy_density(field, data):
                emag = 0.5 * data["gas", "magnetic_1"]**2
                for idim in "23":
                    if not ("amrvac", f"b{idim}") in self.field_list:
                        break
                    emag += 0.5 * data["gas", f"magnetic_{idim}"]**2
                # in AMRVAC the magnetic field is defined in units where mu0 = 1,
                # such that
                # Emag = 0.5*B**2 instead of Emag = 0.5*B**2 / mu0
                # To correctly transform the dimensionality from gauss**2 -> rho*v**2,
                # we have to take mu0 into account. If we divide here, units when adding
                # the field should be us["density"]*us["velocity"]**2.
                # If not, they should be us["magnetic_field"]**2 and division should
                # happen elsewhere.
                emag /= 4 * np.pi
                # divided by mu0 = 4pi in cgs,
                # yt handles 'mks' and 'code' unit systems internally.
                return emag

            self.add_field(
                ("gas", "magnetic_energy_density"),
                function=_magnetic_energy_density,
                units=us["density"] * us["velocity"]**2,
                dimensions=dimensions.density * dimensions.velocity**2,
                sampling_type="cell",
            )

        # Adding the thermal pressure field.
        # In AMRVAC we have multiple physics possibilities:
        # - if HD/MHD + energy equation P = (gamma-1)*(e - ekin (- emag)) for (M)HD
        # - if HD/MHD but solve_internal_e is true in parfile, P = (gamma-1)*e for both
        # - if (m)hd_energy is false in parfile (isothermal), P = c_adiab * rho**gamma

        def _full_thermal_pressure_HD(field, data):
            # energy density and pressure are actually expressed in the same unit
            pthermal = (data.ds.gamma -
                        1) * (data["gas", "energy_density"] -
                              data["gas", "kinetic_energy_density"])
            return pthermal

        def _full_thermal_pressure_MHD(field, data):
            pthermal = (
                _full_thermal_pressure_HD(field, data) -
                (data.ds.gamma - 1) * data["gas", "magnetic_energy_density"])
            return pthermal

        def _polytropic_thermal_pressure(field, data):
            return (data.ds.gamma - 1) * data["gas", "energy_density"]

        def _adiabatic_thermal_pressure(field, data):
            return data.ds._c_adiab * data["gas", "density"]**data.ds.gamma

        pressure_recipe = None
        if ("amrvac", "e") in self.field_list:
            if self.ds._e_is_internal:
                pressure_recipe = _polytropic_thermal_pressure
                mylog.info("Using polytropic EoS for thermal pressure.")
            elif ("amrvac", "b1") in self.field_list:
                pressure_recipe = _full_thermal_pressure_MHD
                mylog.info("Using full MHD energy for thermal pressure.")
            else:
                pressure_recipe = _full_thermal_pressure_HD
                mylog.info("Using full HD energy for thermal pressure.")
        elif self.ds._c_adiab is not None:
            pressure_recipe = _adiabatic_thermal_pressure
            mylog.info(
                "Using adiabatic EoS for thermal pressure (isothermal).")
            mylog.warning("If you used usr_set_pthermal you should "
                          "redefine the thermal_pressure field.")

        if pressure_recipe is not None:
            self.add_field(
                ("gas", "thermal_pressure"),
                function=pressure_recipe,
                units=us["density"] * us["velocity"]**2,
                dimensions=dimensions.density * dimensions.velocity**2,
                sampling_type="cell",
            )

            # sound speed and temperature depend on thermal pressure
            def _sound_speed(field, data):
                return np.sqrt(data.ds.gamma *
                               data["gas", "thermal_pressure"] /
                               data["gas", "density"])

            self.add_field(
                ("gas", "sound_speed"),
                function=_sound_speed,
                units=us["velocity"],
                dimensions=dimensions.velocity,
                sampling_type="cell",
            )
        else:
            mylog.warning(
                "e not found and no parfile passed, can not set thermal_pressure."
            )
Beispiel #6
0
def save(obj, filename='test.hdf5'):
    """Function to save a CAESAR file to disk.

    Parameters
    ----------
    obj : :class:`main.CAESAR`
        Main caesar object to save.
    filename : str, optional
        Filename of the output file.

    Examples
    --------
    >>> obj.save('output.hdf5')
    
    """
    from yt.funcs import mylog

    if os.path.isfile(filename):
        mylog.warning('%s already present, overwriting!' % filename)
        os.remove(filename)
    mylog.info('Writing %s' % filename)

    outfile = h5py.File(filename, 'w')
    outfile.attrs.create('caesar', 315)

    unit_registry = obj.yt_dataset.unit_registry.to_json()
    outfile.attrs.create('unit_registry_json', unit_registry.encode('utf8'))

    serialize_global_attribs(obj, outfile)
    obj.simulation._serialize(obj, outfile)

    if hasattr(obj, 'halos') and obj.nhalos > 0:
        hd = outfile.create_group('halo_data')
        hdd = hd.create_group('lists')
        hddd = hd.create_group('dicts')

        # gather
        index_lists = ['dmlist']
        if 'gas' in obj.data_manager.ptypes: index_lists.append('glist')
        if 'star' in obj.data_manager.ptypes:
            index_lists.extend(['slist', 'galaxy_index_list'])
        if 'dm2' in obj.data_manager.ptypes: index_lists.append('dm2list')
        if 'dm3' in obj.data_manager.ptypes: index_lists.append('dm3list')
        if obj.data_manager.blackholes:
            index_lists.append('bhlist')
        if obj.data_manager.dust:
            index_lists.append('dlist')

        #write
        for vals in index_lists:
            serialize_list(obj.halos, vals, hdd)
        serialize_attributes(obj.halos, hd, hddd)

    if hasattr(obj, 'galaxies') and obj.ngalaxies > 0:
        hd = outfile.create_group('galaxy_data')
        hdd = hd.create_group('lists')
        hddd = hd.create_group('dicts')

        # gather
        index_lists = ['glist', 'slist', 'cloud_index_list']
        if obj.data_manager.blackholes:
            index_lists.append('bhlist')
        if obj.data_manager.dust:
            index_lists.append('dlist')

        # write
        for vals in index_lists:
            serialize_list(obj.galaxies, vals, hdd)
        serialize_attributes(obj.galaxies, hd, hddd)

    if hasattr(obj, 'clouds') and obj.nclouds > 0:
        hd = outfile.create_group('cloud_data')
        hdd = hd.create_group('lists')
        hddd = hd.create_group('dicts')

        # gather
        index_lists = ['glist']

        # write
        for vals in index_lists:
            serialize_list(obj.clouds, vals, hdd)
        serialize_attributes(obj.clouds, hd, hddd)

    if hasattr(obj, 'global_particle_lists'):
        hd = outfile.create_group('global_lists')

        # gather
        global_index_lists = [
            'halo_dmlist', 'halo_glist', 'halo_slist', 'galaxy_glist',
            'galaxy_slist', 'cloud_glist'
        ]
        if obj.data_manager.blackholes:
            global_index_lists.extend(['halo_bhlist', 'galaxy_bhlist'])
        if obj.data_manager.dust:
            global_index_lists.extend(['halo_dlist', 'galaxy_dlist'])

        # write
        for vals in global_index_lists:
            check_and_write_dataset(obj.global_particle_lists, vals, hd)

    outfile.close()
Beispiel #7
0
    def __init__(self, num_particles, rr, gpot, pden, mdm):

        fields = OrderedDict()

        ee = gpot[::-1]
        density_spline = InterpolatedUnivariateSpline(ee, pden[::-1])
        energy_spline = InterpolatedUnivariateSpline(rr, gpot)

        num_points = gpot.shape[0]

        g = np.zeros(num_points)
        dgdp = lambda t, e: 2*density_spline(e-t*t, 1)
        pbar = get_pbar("Computing particle DF.", num_points)
        for i in range(num_points):
            g[i] = quad(dgdp, 0., np.sqrt(ee[i]), args=(ee[i]))[0]
            pbar.update(i)
        pbar.finish()
        g_spline = InterpolatedUnivariateSpline(ee, g)
        f = lambda e: g_spline(e, 1)/(np.sqrt(8.)*np.pi**2)

        self.ee = ee
        self.f = f
        self.rr = rr
        self.pden = pden

        mylog.info("We will be assigning %d particles." % num_particles)
        mylog.info("Compute particle positions.")

        u = np.random.uniform(size=num_particles)
        P_r = np.insert(mdm, 0, 0.0)
        P_r /= P_r[-1]
        radius = np.interp(u, P_r, np.insert(rr, 0, 0.0), left=0.0, right=1.0)

        theta = np.arccos(np.random.uniform(low=-1.,high=1.,size=num_particles))
        phi = 2.*np.pi*np.random.uniform(size=num_particles)

        fields["particle_radius"] = YTArray(radius, "kpc")
        fields["particle_position_x"] = YTArray(radius*np.sin(theta)*np.cos(phi), "kpc")
        fields["particle_position_y"] = YTArray(radius*np.sin(theta)*np.sin(phi), "kpc")
        fields["particle_position_z"] = YTArray(radius*np.cos(theta), "kpc")

        mylog.info("Compute particle velocities.")

        psi = energy_spline(radius)
        vesc = 2.*psi
        fv2esc = vesc*f(psi)
        vesc = np.sqrt(vesc)
        velocity = generate_velocities(psi, vesc, fv2esc, f)
        theta = np.arccos(np.random.uniform(low=-1.,high=1.,size=num_particles))
        phi = 2.*np.pi*np.random.uniform(size=num_particles)

        fields["particle_velocity"] = YTArray(velocity, "kpc/Myr")
        fields["particle_velocity_x"] = YTArray(velocity*np.sin(theta)*np.cos(phi), "kpc/Myr")
        fields["particle_velocity_y"] = YTArray(velocity*np.sin(theta)*np.sin(phi), "kpc/Myr")
        fields["particle_velocity_z"] = YTArray(velocity*np.cos(theta), "kpc/Myr")

        fields["particle_mass"] = YTArray([mdm.max()/num_particles], "Msun")
        fields["particle_potential"] = YTArray(psi, "kpc**2/Myr**2")
        fields["particle_energy"] = fields["particle_potential"]-0.5*fields["particle_velocity"]**2

        super(VirialEquilibrium, self).__init__(num_particles, fields, "spherical")
    def from_scratch(
        cls, mode, xmin, xmax, profiles, input_units=None, num_points=1000, geometry="spherical", P_amb=0.0
    ):
        r"""
        Generate a set of profiles of physical quantities based on the assumption
        of hydrostatic equilibrium. Currently assumes an ideal gas with a gamma-law
        equation of state.

        Parameters
        ----------
        mode : string
            The method to generate the profiles from an initial set. Can be
            one of the following:
                "dens_temp": Generate the profiles given a gas density and
                gas temperature profile.
                "dens_tden": Generate the profiles given a gas density and
                total density profile.
                "dens_grav": Generate the profiles given a gas density and
                gravitational acceleration profile.
                "dm_only": Generate profiles of gravitational potential
                and acceleration assuming an initial DM density profile.
        xmin : float
            The minimum radius or height for the profiles, assumed to be in kpc.
        xmax : float
            The maximum radius or height for the profiles, assumed to be in kpc.
        profiles : dict of functions
            A dictionary of callable functions of radius or height which return
            quantities such as density, total density, and so on. The functions 
            are not unit-aware for speed purposes, but they assume that the base
            units are:
                "length": "kpc"
                "time": "Myr"
                "mass": "Msun"
                "temperature": "keV"
        parameters : dict of floats
            A dictionary of parameters needed for the calculation, which include:
                "mu": The mean molecular weight of the gas. Default is to assume a
                primordial H/He gas.
                "gamma": The ratio of specific heats. Default: 5/3.
        num_points : integer
            The number of points at which to evaluate the profile.
        geometry : string
            The geometry of the model. Can be "cartesian" or "spherical", which will
            determine whether or not the profiles are of "radius" or "height".
        """

        if not isinstance(P_amb, YTQuantity):
            P_amb = YTQuantity(P_amb, "erg/cm**3")
        P_amb.convert_to_units("Msun/(Myr**2*kpc)")

        for p in modes[mode]:
            if p not in profiles:
                raise RequiredProfilesError(mode)

        if mode in ["dens_tden", "dm_only"] and geometry != "spherical":
            raise NotImplemented(
                "Constructing a HydrostaticEquilibrium from gas density and/or "
                "total density profiles is only allowed in spherical geometry!"
            )

        extra_fields = [field for field in profiles if field not in cls.default_fields]

        if geometry == "cartesian":
            x_field = "height"
        elif geometry == "spherical":
            x_field = "radius"

        fields = OrderedDict()

        xx = np.logspace(np.log10(xmin), np.log10(xmax), num_points, endpoint=True)
        fields[x_field] = YTArray(xx, "kpc")

        if mode == "dm_only":
            fields["density"] = YTArray(np.zeros(num_points), "Msun/kpc**3")
            fields["pressure"] = YTArray(np.zeros(num_points), "Msun/kpc/Myr**2")
            fields["temperature"] = YTArray(np.zeros(num_points), "keV")
        else:
            fields["density"] = YTArray(profiles["density"](xx), "Msun/kpc**3")

        if mode == "dens_temp":

            mylog.info("Computing the profiles from density and temperature.")

            fields["temperature"] = YTArray(profiles["temperature"](xx), "keV")
            fields["pressure"] = fields["density"] * fields["temperature"]
            fields["pressure"] *= muinv / mp
            fields["pressure"].convert_to_units("Msun/(Myr**2*kpc)")

            pressure_spline = InterpolatedUnivariateSpline(xx, fields["pressure"].v)
            dPdx = YTArray(pressure_spline(xx, 1), "Msun/(Myr**2*kpc**2)")
            fields["gravitational_field"] = dPdx / fields["density"]
            fields["gravitational_field"].convert_to_units("kpc/Myr**2")

        else:

            if mode == "dens_tden" or mode == "dm_only":
                mylog.info("Computing the profiles from density and total density.")
                fields["total_density"] = YTArray(profiles["total_density"](xx), "Msun/kpc**3")
                mylog.info("Integrating total mass profile.")
                fields["total_mass"] = YTArray(integrate_mass(profiles["total_density"], xx), "Msun")
                fields["gravitational_field"] = -G * fields["total_mass"] / (fields["radius"] ** 2)
                fields["gravitational_field"].convert_to_units("kpc/Myr**2")
            elif mode == "dens_grav":
                mylog.info("Computing the profiles from density and gravitational acceleration.")
                fields["gravitational_field"] = YTArray(profiles["gravitational_field"](xx), "kpc/Myr**2")

            if mode != "dm_only":
                g = fields["gravitational_field"].in_units("kpc/Myr**2").v
                g_r = InterpolatedUnivariateSpline(xx, g)
                dPdr_int = lambda r: profiles["density"](r) * g_r(r)
                mylog.info("Integrating pressure profile.")
                fields["pressure"] = -YTArray(integrate(dPdr_int, xx), "Msun/kpc/Myr**2")
                fields["temperature"] = fields["pressure"] * mp / fields["density"] / muinv
                fields["temperature"].convert_to_units("keV")

        if geometry == "spherical":
            if "total_mass" not in fields:
                fields["total_mass"] = -fields["radius"] ** 2 * fields["gravitational_field"] / G
            if "total_density" not in fields:
                total_mass_spline = InterpolatedUnivariateSpline(xx, fields["total_mass"].v)
                dMdr = YTArray(total_mass_spline(xx, 1), "Msun/kpc")
                fields["total_density"] = dMdr / (4.0 * np.pi * fields["radius"] ** 2)
            mylog.info("Integrating gravitational potential profile.")
            if "total_density" in profiles:
                tdens_func = profiles["total_density"]
            else:
                tdens_func = InterpolatedUnivariateSpline(xx, fields["total_density"].d)
            gpot_profile = lambda r: tdens_func(r) * r
            gpot = YTArray(4.0 * np.pi * integrate(gpot_profile, xx), "Msun/kpc")
            fields["gravitational_potential"] = -G * (fields["total_mass"] / fields["radius"] + gpot)
            fields["gravitational_potential"].convert_to_units("kpc**2/Myr**2")
            if mode != "dm_only":
                mylog.info("Integrating gas mass profile.")
                fields["gas_mass"] = YTArray(integrate_mass(profiles["density"], xx), "Msun")

        mdm = fields["total_mass"].copy()
        ddm = fields["total_density"].copy()
        if mode != "dm_only":
            mdm -= fields["gas_mass"]
            ddm -= fields["density"]
            mdm[ddm.v < 0.0][:] = mdm.max()
            ddm[ddm.v < 0.0][:] = 0.0
        fields["dark_matter_density"] = ddm
        fields["dark_matter_mass"] = mdm

        fields["pressure"] += P_amb

        for field in extra_fields:
            fields[field] = profiles[field](xx)

        return cls(num_points, fields, geometry)
Beispiel #9
0
    def setup_fluid_fields(self):
        def _v1(field, data):
            return data["gas", "moment_1"] / data["gas", "density"]

        def _v2(field, data):
            return data["gas", "moment_2"] / data["gas", "density"]

        def _v3(field, data):
            return data["gas", "moment_3"] / data["gas", "density"]

        us = self.ds.unit_system
        aliases = direction_aliases[self.ds.geometry]
        for idir, alias, func in zip("123", aliases, (_v1, _v2, _v3)):
            if not ("amrvac", "m%s" % idir) in self.field_list:
                break
            self.add_field(("gas", "velocity_%s" % alias),
                           function=func,
                           units=us['velocity'],
                           dimensions=dimensions.velocity,
                           sampling_type="cell")
            self.alias(("gas", "velocity_%s" % idir),
                       ("gas", "velocity_%s" % alias),
                       units=us["velocity"])
            self.alias(("gas", "moment_%s" % alias),
                       ("gas", "moment_%s" % idir),
                       units=us["density"] * us["velocity"])

        setup_magnetic_field_aliases(self, "amrvac",
                                     ["mag%s" % ax for ax in "xyz"])

        # fields with nested dependencies are defined thereafter by increasing level of complexity

        # kinetic pressure is given by 0.5 * rho * v**2
        def _kinetic_energy_density(field, data):
            # devnote : have a look at issue 1301
            return 0.5 * data['gas', 'density'] * data['gas',
                                                       'velocity_magnitude']**2

        self.add_field(("gas", "kinetic_energy_density"),
                       function=_kinetic_energy_density,
                       units=us["density"] * us["velocity"]**2,
                       dimensions=dimensions.density * dimensions.velocity**2,
                       sampling_type="cell")

        # magnetic energy density
        if ('amrvac', 'b1') in self.field_list:

            def _magnetic_energy_density(field, data):
                emag = 0.5 * data['gas', 'magnetic_1']**2
                for idim in '23':
                    if not ('amrvac', 'b%s' % idim) in self.field_list:
                        break
                    emag += 0.5 * data['gas', 'magnetic_%s' % idim]**2
                # important note: in AMRVAC the magnetic field is defined in units where mu0 = 1, such that
                # Emag = 0.5*B**2 instead of Emag = 0.5*B**2 / mu0
                # To correctly transform the dimensionality from gauss**2 -> rho*v**2, we have to take mu0 into account.
                # If we divide here, units when adding the field should be us["density"]*us["velocity"]**2
                # If not, they should be us["magnetic_field"]**2 and division should happen elsewhere.
                emag /= 4 * np.pi
                # divided by mu0 = 4pi in cgs, yt handles 'mks' and 'code' unit systems internally.
                return emag

            self.add_field(
                ('gas', 'magnetic_energy_density'),
                function=_magnetic_energy_density,
                units=us["density"] * us["velocity"]**2,
                dimensions=dimensions.density * dimensions.velocity**2,
                sampling_type='cell')

        # Adding the thermal pressure field.
        # In AMRVAC we have multiple physics possibilities:
        # - if HD/MHD + energy equation, pressure is (gamma-1)*(e - ekin (- emag)) for (M)HD
        # - if HD/MHD but solve_internal_e is true in parfile, pressure is (gamma-1)*e for both
        # - if (m)hd_energy is false in parfile (isothermal), pressure is c_adiab * rho**gamma

        def _full_thermal_pressure_HD(field, data):
            # important note : energy density and pressure are actually expressed in the same unit
            pthermal = (data.ds.gamma -
                        1) * (data['gas', 'energy_density'] -
                              data['gas', 'kinetic_energy_density'])
            return pthermal

        def _full_thermal_pressure_MHD(field, data):
            pthermal = _full_thermal_pressure_HD(field, data) \
                       - (data.ds.gamma - 1) * data["gas", "magnetic_energy_density"]
            return pthermal

        def _polytropic_thermal_pressure(field, data):
            return (data.ds.gamma - 1) * data['gas', 'energy_density']

        def _adiabatic_thermal_pressure(field, data):
            return data.ds._c_adiab * data["gas", "density"]**data.ds.gamma

        pressure_recipe = None
        if ("amrvac", "e") in self.field_list:
            if self.ds._e_is_internal:
                pressure_recipe = _polytropic_thermal_pressure
                mylog.info('Using polytropic EoS for thermal pressure.')
            elif ('amrvac', 'b1') in self.field_list:
                pressure_recipe = _full_thermal_pressure_MHD
                mylog.info('Using full MHD energy for thermal pressure.')
            else:
                pressure_recipe = _full_thermal_pressure_HD
                mylog.info('Using full HD energy for thermal pressure.')
        elif self.ds._c_adiab is not None:
            pressure_recipe = _adiabatic_thermal_pressure
            mylog.info(
                'Using adiabatic EoS for thermal pressure (isothermal).')
            mylog.warning(
                'If you used usr_set_pthermal you should redefine the thermal_pressure field.'
            )

        if pressure_recipe is not None:
            self.add_field(
                ('gas', 'thermal_pressure'),
                function=pressure_recipe,
                units=us['density'] * us['velocity']**2,
                dimensions=dimensions.density * dimensions.velocity**2,
                sampling_type='cell')

            # sound speed and temperature depend on thermal pressure
            def _sound_speed(field, data):
                return np.sqrt(data.ds.gamma *
                               data["gas", "thermal_pressure"] /
                               data["gas", "density"])

            self.add_field(("gas", "sound_speed"),
                           function=_sound_speed,
                           units=us["velocity"],
                           dimensions=dimensions.velocity,
                           sampling_type="cell")
        else:
            mylog.warning(
                "e not found and no parfile passed, can not set thermal_pressure."
            )