Esempio n. 1
0
    def get_interpolator(self, data_type, e_min, e_max, energy=True):
        data = getattr(self, "emissivity_%s" % data_type)
        if not energy:
            data = data[..., :] / self.emid.v
        e_min = YTQuantity(e_min, "keV")*(1.0+self.redshift)
        e_max = YTQuantity(e_max, "keV")*(1.0+self.redshift)
        if (e_min - self.ebin[0]) / e_min < -1e-3 or \
          (e_max - self.ebin[-1]) / e_max > 1e-3:
            raise EnergyBoundsException(self.ebin[0], self.ebin[-1])
        e_is, e_ie = np.digitize([e_min, e_max], self.ebin)
        e_is = np.clip(e_is - 1, 0, self.ebin.size - 1)
        e_ie = np.clip(e_ie, 0, self.ebin.size - 1)

        my_dE = self.dE[e_is: e_ie].copy()
        # clip edge bins if the requested range is smaller
        my_dE[0] -= e_min - self.ebin[e_is]
        my_dE[-1] -= self.ebin[e_ie] - e_max

        interp_data = (data[..., e_is:e_ie]*my_dE).sum(axis=-1)
        if data.ndim == 2:
            emiss = UnilinearFieldInterpolator(np.log10(interp_data),
                                               [self.log_T[0],  self.log_T[-1]],
                                               "log_T", truncate=True)
        else:
            emiss = BilinearFieldInterpolator(np.log10(interp_data),
                                              [self.log_nH[0], self.log_nH[-1],
                                               self.log_T[0],  self.log_T[-1]],
                                              ["log_nH", "log_T"], truncate=True)

        return emiss
Esempio n. 2
0
    def get_interpolator(self, data, e_min, e_max):
        e_min = YTQuantity(e_min, "keV")
        e_max = YTQuantity(e_max, "keV")
        if (e_min - self.E_bins[0]) / e_min < -1e-3 or \
          (e_max - self.E_bins[-1]) / e_max > 1e-3:
            raise EnergyBoundsException(self.E_bins[0], self.E_bins[-1])
        e_is, e_ie = np.digitize([e_min, e_max], self.E_bins)
        e_is = np.clip(e_is - 1, 0, self.E_bins.size - 1)
        e_ie = np.clip(e_ie, 0, self.E_bins.size - 1)

        my_dnu = self.dnu[e_is:e_ie].copy()
        # clip edge bins if the requested range is smaller
        my_dnu[0] -= ((e_min - self.E_bins[e_is]) / hcgs).in_units("Hz")
        my_dnu[-1] -= ((self.E_bins[e_ie] - e_max) / hcgs).in_units("Hz")

        interp_data = (data[..., e_is:e_ie] * my_dnu).sum(axis=-1)
        if len(data.shape) == 2:
            emiss = UnilinearFieldInterpolator(np.log10(interp_data),
                                               [self.log_T[0], self.log_T[-1]],
                                               "log_T",
                                               truncate=True)
        else:
            emiss = BilinearFieldInterpolator(np.log10(interp_data), [
                self.log_nH[0], self.log_nH[-1], self.log_T[0], self.log_T[-1]
            ], ["log_nH", "log_T"],
                                              truncate=True)

        return emiss
Esempio n. 3
0
    def create_cooling_fields(self):
        num = os.path.basename(
            self.ds.parameter_filename).split(".")[0].split("_")[1]
        filename = "%s/cooling_%05i.out" % (os.path.dirname(
            self.ds.parameter_filename), int(num))

        if not os.path.exists(filename): return

        def _create_field(name, interp_object):
            def _func(field, data):
                shape = data["temperature"].shape
                d = {
                    'lognH': np.log10(_X * data["density"] / mh).ravel(),
                    'logT': np.log10(data["temperature"]).ravel()
                }
                rv = 10**interp_object(d).reshape(shape)
                # Return array in unit 'per volume' consistently with line below
                return data.ds.arr(rv, 'code_length**-3')

            self.add_field(name=name,
                           sampling_type="cell",
                           function=_func,
                           units="code_length**-3")

        avals = {}
        tvals = {}
        with open(filename, "rb") as f:
            n1, n2 = fpu.read_vector(f, 'i')
            n = n1 * n2
            for ax in _cool_axes:
                avals[ax] = fpu.read_vector(f, 'd')
            for tname in _cool_arrs:
                var = fpu.read_vector(f, 'd')
                if var.size == n1 * n2:
                    tvals[tname] = var.reshape((n1, n2), order='F')
                else:
                    var = var.reshape((n1, n2, var.size // (n1 * n2)),
                                      order='F')
                    for i in range(var.shape[-1]):
                        tvals[_cool_species[i]] = var[:, :, i]

        for n in tvals:
            interp = BilinearFieldInterpolator(tvals[n],
                                               (avals["lognH"], avals["logT"]),
                                               ["lognH", "logT"],
                                               truncate=True)
            _create_field(("gas", n), interp)
Esempio n. 4
0
    def create_cooling_fields(self):
        num = os.path.basename(
            self.ds.parameter_filename).split(".")[0].split("_")[1]
        filename = "%s/cooling_%05i.out" % (os.path.dirname(
            self.ds.parameter_filename), int(num))

        if not os.path.exists(filename):
            mylog.warning('This output has no cooling fields')
            return

        #Function to create the cooling fields
        def _create_field(name, interp_object, unit):
            def _func(field, data):
                shape = data["temperature"].shape
                d = {
                    'lognH': np.log10(_X * data["density"] / mh).ravel(),
                    'logT': np.log10(data["temperature"]).ravel()
                }
                rv = interp_object(d).reshape(shape)
                if name[-1] != 'mu':
                    rv = 10**interp_object(d).reshape(shape)
                cool = data.ds.arr(rv, unit)
                if 'metal' in name[-1].split('_'):
                    cool = cool * data[
                        'metallicity'] / 0.02  #Ramses uses Zsolar=0.02
                elif 'compton' in name[-1].split('_'):
                    cool = data.ds.arr(rv, unit + '/cm**3')
                    cool = cool / data[
                        'number_density']  #Compton cooling/heating is written to file in erg/s
                return cool

            self.add_field(name=name,
                           sampling_type="cell",
                           function=_func,
                           units=unit)

        #Load cooling files
        avals = {}
        tvals = {}
        with FortranFile(filename) as fd:
            n1, n2 = fd.read_vector('i')
            for ax in _cool_axes:
                avals[ax] = fd.read_vector('d')
            for i, (tname, unit) in enumerate(_cool_arrs):
                var = fd.read_vector('d')
                if var.size == n1 and i == 0:
                    #If this case occurs, the cooling files were produced pre-2010 in a format
                    #that is no longer supported
                    mylog.warning(
                        'This cooling file format is no longer supported. Cooling field loading skipped.'
                    )
                    return
                if var.size == n1 * n2:
                    tvals[tname] = dict(data=var.reshape((n1, n2), order='F'),
                                        unit=unit)
                else:
                    var = var.reshape((n1, n2, var.size // (n1 * n2)),
                                      order='F')
                    for i in range(var.shape[-1]):
                        tvals[_cool_species[i]] = dict(data=var[:, :, i],
                                                       unit="1/cm**3")

        #Add the mu field first, as it is needed for the number density
        interp = BilinearFieldInterpolator(tvals['mu']['data'],
                                           (avals["lognH"], avals["logT"]),
                                           ["lognH", "logT"],
                                           truncate=True)
        _create_field(("gas", 'mu'), interp, tvals['mu']['unit'])

        #Add the number density field, based on mu
        def _number_density(field, data):
            return data[('gas', 'density')] / mp / data['mu']

        self.add_field(name=('gas', 'number_density'),
                       sampling_type="cell",
                       function=_number_density,
                       units=number_density_unit)

        #Add the cooling and heating fields, which need the number density field
        for key in tvals:
            if key != 'mu':
                interp = BilinearFieldInterpolator(
                    tvals[key]['data'], (avals["lognH"], avals["logT"]),
                    ["lognH", "logT"],
                    truncate=True)
                _create_field(("gas", key), interp, tvals[key]['unit'])

        #Add total cooling and heating fields
        def _all_cool(field, data):
            return data['cooling_primordial'] + data['cooling_metal'] + data[
                'cooling_compton']

        def _all_heat(field, data):
            return data['heating_primordial'] + data['heating_compton']

        self.add_field(name=('gas', 'cooling_total'),
                       sampling_type="cell",
                       function=_all_cool,
                       units=cooling_function_units)
        self.add_field(name=('gas', 'heating_total'),
                       sampling_type="cell",
                       function=_all_heat,
                       units=cooling_function_units)

        #Add net cooling fields
        def _net_cool(field, data):
            return data['cooling_total'] - data['heating_total']

        self.add_field(name=('gas', 'cooling_net'),
                       sampling_type="cell",
                       function=_net_cool,
                       units=cooling_function_units)
Esempio n. 5
0
    def create_cooling_fields(self):
        num = os.path.basename(
            self.ds.parameter_filename).split(".")[0].split("_")[1]
        filename = "%s/cooling_%05i.out" % (
            os.path.dirname(self.ds.parameter_filename),
            int(num),
        )

        if not os.path.exists(filename):
            mylog.warning("This output has no cooling fields")
            return

        # Function to create the cooling fields
        def _create_field(name, interp_object, unit):
            def _func(field, data):
                shape = data[("gas", "temperature")].shape
                d = {
                    "lognH":
                    np.log10(_X * data[("gas", "density")] / mh).ravel(),
                    "logT": np.log10(data[("gas", "temperature")]).ravel(),
                }
                rv = interp_object(d).reshape(shape)
                if name[-1] != "mu":
                    rv = 10**interp_object(d).reshape(shape)
                cool = data.ds.arr(rv, unit)
                if "metal" in name[-1].split("_"):
                    cool = (cool * data[("gas", "metallicity")] / 0.02
                            )  # Ramses uses Zsolar=0.02
                elif "compton" in name[-1].split("_"):
                    cool = data.ds.arr(rv, unit + "/cm**3")
                    cool = (
                        cool / data[("gas", "number_density")]
                    )  # Compton cooling/heating is written to file in erg/s
                return cool

            self.add_field(name=name,
                           sampling_type="cell",
                           function=_func,
                           units=unit)

        # Load cooling files
        avals = {}
        tvals = {}
        with FortranFile(filename) as fd:
            n1, n2 = fd.read_vector("i")
            for ax in _cool_axes:
                avals[ax] = fd.read_vector("d")
            for i, (tname, unit) in enumerate(_cool_arrs):
                var = fd.read_vector("d")
                if var.size == n1 and i == 0:
                    # If this case occurs, the cooling files were produced pre-2010 in
                    # a format that is no longer supported
                    mylog.warning(
                        "This cooling file format is no longer supported. "
                        "Cooling field loading skipped.")
                    return
                if var.size == n1 * n2:
                    tvals[tname] = dict(data=var.reshape((n1, n2), order="F"),
                                        unit=unit)
                else:
                    var = var.reshape((n1, n2, var.size // (n1 * n2)),
                                      order="F")
                    for i in range(var.shape[-1]):
                        tvals[_cool_species[i]] = dict(data=var[:, :, i],
                                                       unit="1/cm**3")

        # Add the mu field first, as it is needed for the number density
        interp = BilinearFieldInterpolator(
            tvals["mu"]["data"],
            (avals["lognH"], avals["logT"]),
            ["lognH", "logT"],
            truncate=True,
        )
        _create_field(("gas", "mu"), interp, tvals["mu"]["unit"])

        # Add the number density field, based on mu
        def _number_density(field, data):
            return data[("gas", "density")] / mp / data[("gas", "mu")]

        self.add_field(
            name=("gas", "number_density"),
            sampling_type="cell",
            function=_number_density,
            units=number_density_unit,
        )

        # Add the cooling and heating fields, which need the number density field
        for key in tvals:
            if key != "mu":
                interp = BilinearFieldInterpolator(
                    tvals[key]["data"],
                    (avals["lognH"], avals["logT"]),
                    ["lognH", "logT"],
                    truncate=True,
                )
                _create_field(("gas", key), interp, tvals[key]["unit"])

        # Add total cooling and heating fields
        def _all_cool(field, data):
            return (data[("gas", "cooling_primordial")] +
                    data[("gas", "cooling_metal")] +
                    data[("gas", "cooling_compton")])

        def _all_heat(field, data):
            return (data[("gas", "heating_primordial")] +
                    data[("gas", "heating_compton")])

        self.add_field(
            name=("gas", "cooling_total"),
            sampling_type="cell",
            function=_all_cool,
            units=cooling_function_units,
        )
        self.add_field(
            name=("gas", "heating_total"),
            sampling_type="cell",
            function=_all_heat,
            units=cooling_function_units,
        )

        # Add net cooling fields
        def _net_cool(field, data):
            return data[("gas", "cooling_total")] - data[("gas",
                                                          "heating_total")]

        self.add_field(
            name=("gas", "cooling_net"),
            sampling_type="cell",
            function=_net_cool,
            units=cooling_function_units,
        )