Пример #1
0
def test_missing_required_property(csvy_missing_fname):
    yaml_dict, csv = csvy.load_csvy(csvy_missing_fname)
    with pytest.raises(Exception):
        vy = validate_dict(yaml_dict,
                           schemapath=os.path.join(tardis.__path__[0], 'io',
                                                   'schemas',
                                                   'csvy_model.yml'))
Пример #2
0
    def from_config_dict(cls, config_dict, validate=True, config_dirname=''):
        """
        Validating and subsequently parsing a config file.

        Parameters
        ----------

        config_dict : ~dict
            dictionary of a raw unvalidated config file

        validate: ~bool
            Turn validation on or off.

        Returns
        -------

        `tardis.config_reader.Configuration`

        """

        if validate:
            validated_config_dict = config_validator.validate_dict(config_dict)
        else:
            validated_config_dict = config_dict

        validated_config_dict['config_dirname'] = config_dirname

        montecarlo_section = validated_config_dict['montecarlo']
        montecarlo_section['convergence_strategy'] = (
                parse_convergence_section(
                    montecarlo_section['convergence_strategy']))

        return cls(validated_config_dict)
Пример #3
0
    def from_config_dict(cls, config_dict, validate=True, config_dirname=""):
        """
        Validating and subsequently parsing a config file.

        Parameters
        ----------
        config_dict : dict
            dictionary of a raw unvalidated config file
        validate : bool
            Turn validation on or off.

        Returns
        -------
        `tardis.config_reader.Configuration`
        """

        if validate:
            validated_config_dict = config_validator.validate_dict(config_dict)
        else:
            validated_config_dict = config_dict

        validated_config_dict["config_dirname"] = config_dirname

        montecarlo_section = validated_config_dict["montecarlo"]
        if montecarlo_section["convergence_strategy"]["type"] == "damped":
            montecarlo_section[
                "convergence_strategy"
            ] = parse_convergence_section(
                montecarlo_section["convergence_strategy"]
            )
        elif montecarlo_section["convergence_strategy"]["type"] == "custom":
            raise NotImplementedError(
                'convergence_strategy is set to "custom"; '
                "you need to implement your specific convergence treatment"
            )
        else:
            raise ValueError(
                'convergence_strategy is not "damped" ' 'or "custom"'
            )

        enable_full_relativity = montecarlo_section["enable_full_relativity"]
        spectrum_integrated = (
            validated_config_dict["spectrum"]["method"] == "integrated"
        )
        if enable_full_relativity and spectrum_integrated:
            raise NotImplementedError(
                "The spectrum method is set to 'integrated' and "
                "enable_full_relativity to 'True'.\n"
                "The FormalIntegrator is not yet implemented for the full "
                "relativity mode. "
            )

        return cls(validated_config_dict)
Пример #4
0
    def from_config_dict(cls, config_dict):
        """
        Validating a config file.

        Parameters
        ----------
        config_dict : dict
            dictionary of a raw unvalidated config file

        Returns
        -------
        `tardis.config_reader.Configuration`
        """

        return cls(config_validator.validate_dict(config_dict))
Пример #5
0
    def from_config_dict(cls, config_dict, validate=True, config_dirname=''):
        """
        Validating and subsequently parsing a config file.

        Parameters
        ----------

        config_dict : ~dict
            dictionary of a raw unvalidated config file

        validate: ~bool
            Turn validation on or off.

        Returns
        -------

        `tardis.config_reader.Configuration`

        """

        if validate:
            validated_config_dict = config_validator.validate_dict(config_dict)
        else:
            validated_config_dict = config_dict

        validated_config_dict['config_dirname'] = config_dirname

        montecarlo_section = validated_config_dict['montecarlo']
        if montecarlo_section['convergence_strategy']['type'] == "damped":
            montecarlo_section['convergence_strategy'] = (
                    parse_convergence_section(
                        montecarlo_section['convergence_strategy']))
        elif montecarlo_section['convergence_strategy']['type'] == "custom":
            raise NotImplementedError(
                'convergence_strategy is set to "custom"; '
                'you need to implement your specific convergence treatment')
        else:
            raise ValueError('convergence_strategy is not "damped" '
                             'or "custom"')

        return cls(validated_config_dict)
Пример #6
0
    def from_config_dict(cls, config_dict):
        """
        Validating a config file.


        Parameters
        ----------

        config_dict : ~dict
            dictionary of a raw unvalidated config file



        Returns
        -------

        `tardis.config_reader.Configuration`

        """

        return cls(config_validator.validate_dict(config_dict))
Пример #7
0
    def from_config_dict(cls,
                         config_dict,
                         atom_data=None,
                         test_parser=False,
                         validate=True,
                         config_dirname=''):
        """
        Validating and subsequently parsing a config file.


        Parameters
        ----------

        config_dict : ~dict
            dictionary of a raw unvalidated config file

        atom_data: ~tardis.atomic.AtomData
            atom data object. if `None` will be tried to be read from
            atom data file path in the config_dict [default=None]

        test_parser: ~bool
            switch on to ignore a working atom_data, mainly useful for
            testing this reader

        validate: ~bool
            Turn validation on or off.


        Returns
        -------

        `tardis.config_reader.Configuration`

        """

        if validate:
            validated_config_dict = config_validator.validate_dict(config_dict)
        else:
            validated_config_dict = config_dict

        #First let's see if we can find an atom_db anywhere:
        if test_parser:
            atom_data = None
        elif 'atom_data' in validated_config_dict.keys():
            if os.path.isabs(validated_config_dict['atom_data']):
                atom_data_fname = validated_config_dict['atom_data']
            else:
                atom_data_fname = os.path.join(
                    config_dirname, validated_config_dict['atom_data'])
            validated_config_dict['atom_data_fname'] = atom_data_fname
        else:
            raise ConfigurationError(
                'No atom_data key found in config or command line')

        if atom_data is None and not test_parser:
            logger.info('Reading Atomic Data from %s', atom_data_fname)
            atom_data = atomic.AtomData.from_hdf5(atom_data_fname)
        else:
            atom_data = atom_data

        #Parsing supernova dictionary
        validated_config_dict['supernova']['luminosity_nu_start'] = \
            validated_config_dict['supernova']['luminosity_wavelength_end'].to(
                u.Hz, u.spectral())
        try:
            validated_config_dict['supernova']['luminosity_nu_end'] = \
                (validated_config_dict['supernova']
                 ['luminosity_wavelength_start'].to(u.Hz, u.spectral()))
        except ZeroDivisionError:
            validated_config_dict['supernova']['luminosity_nu_end'] = (np.inf *
                                                                       u.Hz)

        validated_config_dict['supernova']['time_explosion'] = (
            validated_config_dict['supernova']['time_explosion'].cgs)

        validated_config_dict['supernova']['luminosity_requested'] = (
            validated_config_dict['supernova']['luminosity_requested'].cgs)

        #Parsing the model section

        model_section = validated_config_dict['model']
        v_inner = None
        v_outer = None
        mean_densities = None
        abundances = None

        structure_section = model_section['structure']

        if structure_section['type'] == 'specific':
            velocity = model_section['structure']['velocity']
            start, stop, num = velocity['start'], velocity['stop'], \
                               velocity['num']
            num += 1
            velocities = quantity_linspace(start, stop, num)

            v_inner, v_outer = velocities[:-1], velocities[1:]
            mean_densities = parse_density_section(
                model_section['structure']['density'], v_inner, v_outer,
                validated_config_dict['supernova']['time_explosion']).cgs

        elif structure_section['type'] == 'file':
            if os.path.isabs(structure_section['filename']):
                structure_fname = structure_section['filename']
            else:
                structure_fname = os.path.join(config_dirname,
                                               structure_section['filename'])

            v_inner, v_outer, mean_densities, inner_boundary_index, \
            outer_boundary_index = read_density_file(
                structure_fname, structure_section['filetype'],
                validated_config_dict['supernova']['time_explosion'],
                structure_section['v_inner_boundary'],
                structure_section['v_outer_boundary'])

        r_inner = validated_config_dict['supernova']['time_explosion'] * v_inner
        r_outer = validated_config_dict['supernova']['time_explosion'] * v_outer
        r_middle = 0.5 * (r_inner + r_outer)

        structure_section['v_inner'] = v_inner.cgs
        structure_section['v_outer'] = v_outer.cgs
        structure_section['mean_densities'] = mean_densities.cgs
        no_of_shells = len(v_inner)
        structure_section['no_of_shells'] = no_of_shells
        structure_section['r_inner'] = r_inner.cgs
        structure_section['r_outer'] = r_outer.cgs
        structure_section['r_middle'] = r_middle.cgs
        structure_section['volumes'] = ((4. / 3) * np.pi * \
                                       (r_outer ** 3 -
                                        r_inner ** 3)).cgs

        #### TODO the following is legacy code and should be removed
        validated_config_dict['structure'] = \
            validated_config_dict['model']['structure']
        # ^^^^^^^^^^^^^^^^

        abundances_section = model_section['abundances']

        if abundances_section['type'] == 'uniform':
            abundances = pd.DataFrame(columns=np.arange(no_of_shells),
                                      index=pd.Index(np.arange(1, 120),
                                                     name='atomic_number'),
                                      dtype=np.float64)

            for element_symbol_string in abundances_section:
                if element_symbol_string == 'type': continue
                z = element_symbol2atomic_number(element_symbol_string)
                abundances.ix[z] = float(
                    abundances_section[element_symbol_string])

        elif abundances_section['type'] == 'file':
            if os.path.isabs(abundances_section['filename']):
                abundances_fname = abundances_section['filename']
            else:
                abundances_fname = os.path.join(config_dirname,
                                                abundances_section['filename'])

            index, abundances = read_abundances_file(
                abundances_fname, abundances_section['filetype'],
                inner_boundary_index, outer_boundary_index)
            if len(index) != no_of_shells:
                raise ConfigurationError(
                    'The abundance file specified has not the same number of cells'
                    'as the specified density profile')

        abundances = abundances.replace(np.nan, 0.0)

        abundances = abundances[abundances.sum(axis=1) > 0]

        norm_factor = abundances.sum(axis=0)

        if np.any(np.abs(norm_factor - 1) > 1e-12):
            logger.warning(
                "Abundances have not been normalized to 1. - normalizing")
            abundances /= norm_factor

        validated_config_dict['abundances'] = abundances

        ########### DOING PLASMA SECTION ###############
        plasma_section = validated_config_dict['plasma']

        if plasma_section['initial_t_inner'] < 0.0 * u.K:
            luminosity_requested = validated_config_dict['supernova'][
                'luminosity_requested']
            plasma_section['t_inner'] = ((
                luminosity_requested /
                (4 * np.pi * r_inner[0]**2 * constants.sigma_sb))**.25).to('K')
            logger.info(
                '"initial_t_inner" is not specified in the plasma '
                'section - initializing to %s with given luminosity',
                plasma_section['t_inner'])
        else:
            plasma_section['t_inner'] = plasma_section['initial_t_inner']

        if plasma_section['initial_t_rad'] > 0 * u.K:
            plasma_section['t_rads'] = np.ones(no_of_shells) * \
                                       plasma_section['initial_t_rad']
        else:
            plasma_section['t_rads'] = None

        if plasma_section['disable_electron_scattering'] is False:
            logger.debug("Electron scattering switched on")
            validated_config_dict['montecarlo'][
                'sigma_thomson'] = 6.652486e-25 / (u.cm**2)
        else:
            logger.warn('Disabling electron scattering - this is not physical')
            validated_config_dict['montecarlo']['sigma_thomson'] = 1e-200 / (
                u.cm**2)

        if plasma_section['helium_treatment'] == 'recomb-nlte':
            validated_config_dict['plasma'][
                'helium_treatment'] == 'recomb-nlte'
        else:
            validated_config_dict['plasma']['helium_treatment'] == 'dilute-lte'

        ##### NLTE subsection of Plasma start
        nlte_validated_config_dict = {}
        nlte_species = []
        nlte_section = plasma_section['nlte']

        nlte_species_list = nlte_section.pop('species')
        for species_string in nlte_species_list:
            nlte_species.append(species_string_to_tuple(species_string))

        nlte_validated_config_dict['species'] = nlte_species
        nlte_validated_config_dict['species_string'] = nlte_species_list
        nlte_validated_config_dict.update(nlte_section)

        if 'coronal_approximation' not in nlte_section:
            logger.debug(
                'NLTE "coronal_approximation" not specified in NLTE section - defaulting to False'
            )
            nlte_validated_config_dict['coronal_approximation'] = False

        if 'classical_nebular' not in nlte_section:
            logger.debug(
                'NLTE "classical_nebular" not specified in NLTE section - defaulting to False'
            )
            nlte_validated_config_dict['classical_nebular'] = False

        elif nlte_section:  #checks that the dictionary is not empty
            logger.warn(
                'No "species" given - ignoring other NLTE options given:\n%s',
                pp.pformat(nlte_section))

        if not nlte_validated_config_dict:
            nlte_validated_config_dict['species'] = []

        plasma_section['nlte'] = nlte_validated_config_dict

        #^^^^^^^^^^^^^^ End of Plasma Section

        ##### Monte Carlo Section

        montecarlo_section = validated_config_dict['montecarlo']
        montecarlo_section['no_of_packets'] = \
            int(montecarlo_section['no_of_packets'])
        montecarlo_section['last_no_of_packets'] = \
            int(montecarlo_section['last_no_of_packets'])
        if montecarlo_section['last_no_of_packets'] < 0:
            montecarlo_section['last_no_of_packets'] = \
                montecarlo_section['no_of_packets']

        montecarlo_section['convergence_strategy'] = (
            parse_convergence_section(
                montecarlo_section['convergence_strategy']))

        black_body_section = montecarlo_section['black_body_sampling']
        montecarlo_section['black_body_sampling'] = {}
        montecarlo_section['black_body_sampling']['start'] = \
            black_body_section['start']
        montecarlo_section['black_body_sampling']['end'] = \
            black_body_section['stop']
        montecarlo_section['black_body_sampling']['samples'] = \
            black_body_section['num']
        virtual_spectrum_section = montecarlo_section['virtual_spectrum_range']
        montecarlo_section['virtual_spectrum_range'] = {}
        montecarlo_section['virtual_spectrum_range']['start'] = \
            virtual_spectrum_section['start']
        montecarlo_section['virtual_spectrum_range']['end'] = \
            virtual_spectrum_section['stop']
        montecarlo_section['virtual_spectrum_range']['samples'] = \
            virtual_spectrum_section['num']

        ###### END of convergence section reading

        validated_config_dict['spectrum'] = parse_spectrum_list2dict(
            validated_config_dict['spectrum'])

        return cls(validated_config_dict, atom_data)
Пример #8
0
    def from_csvy(cls, config):
        """
        Create a new Radial1DModel instance from a Configuration object.

        Parameters
        ----------
        config : tardis.io.config_reader.Configuration

        Returns
        -------
        Radial1DModel

        """
        if os.path.isabs(config.csvy_model):
            csvy_model_fname = config.csvy_model
        else:
            csvy_model_fname = os.path.join(config.config_dirname,
                                            config.csvy_model)
        csvy_model_config, csvy_model_data = load_csvy(csvy_model_fname)
        base_dir = os.path.abspath(os.path.dirname(__file__))
        schema_dir = os.path.join(base_dir, '..', 'io', 'schemas')
        csvy_schema_file = os.path.join(schema_dir, 'csvy_model.yml')
        csvy_model_config = Configuration(
            validate_dict(csvy_model_config, schemapath=csvy_schema_file))

        time_explosion = config.supernova.time_explosion.cgs

        electron_densities = None
        temperature = None

        if hasattr(csvy_model_config, 'v_inner_boundary'):
            v_boundary_inner = csvy_model_config.v_inner_boundary
        else:
            v_boundary_inner = None

        if hasattr(csvy_model_config, 'v_outer_boundary'):
            v_boundary_outer = csvy_model_config.v_outer_boundary
        else:
            v_boundary_outer = None

        if hasattr(csvy_model_config, 'velocity'):
            velocity = quantity_linspace(csvy_model_config.velocity.start,
                                         csvy_model_config.velocity.stop,
                                         csvy_model_config.velocity.num +
                                         1).cgs
        else:
            velocity_field_index = [
                field['name'] for field in csvy_model_config.datatype.fields
            ].index('velocity')
            velocity_unit = u.Unit(
                csvy_model_config.datatype.fields[velocity_field_index]
                ['unit'])
            velocity = csvy_model_data['velocity'].values * velocity_unit
            velocity = velocity.to('cm/s')

        if hasattr(csvy_model_config, 'density'):
            homologous_density = HomologousDensity.from_csvy(
                config, csvy_model_config)
        else:
            time_0 = csvy_model_config.model_density_time_0
            density_field_index = [
                field['name'] for field in csvy_model_config.datatype.fields
            ].index('density')
            density_unit = u.Unit(
                csvy_model_config.datatype.fields[density_field_index]['unit'])
            density_0 = csvy_model_data['density'].values * density_unit
            density_0 = density_0.to('g/cm^3')[1:]
            density_0 = density_0.insert(0, 0)
            homologous_density = HomologousDensity(density_0, time_0)

        no_of_shells = len(velocity) - 1

        # TODO -- implement t_radiative
        #t_radiative = None
        if temperature:
            t_radiative = temperature
        elif hasattr(csvy_model_data, 'columns'):
            if 't_rad' in csvy_model_data.columns:
                t_rad_field_index = [
                    field['name']
                    for field in csvy_model_config.datatype.fields
                ].index('t_rad')
                t_rad_unit = u.Unit(
                    csvy_model_config.datatype.fields[t_rad_field_index]
                    ['unit'])
                t_radiative = csvy_model_data['t_rad'].iloc[
                    0:].values * t_rad_unit
            else:
                t_radiative = None

        dilution_factor = None
        if hasattr(csvy_model_data, 'columns'):
            if 'w' in csvy_model_data.columns:
                dilution_factor = csvy_model_data['w'].iloc[0:].to_numpy()

        elif config.plasma.initial_t_rad > 0 * u.K:
            t_radiative = np.ones(no_of_shells) * config.plasma.initial_t_rad
        else:
            t_radiative = None

        if config.plasma.initial_t_inner < 0.0 * u.K:
            luminosity_requested = config.supernova.luminosity_requested
            t_inner = None
        else:
            luminosity_requested = None
            t_inner = config.plasma.initial_t_inner

        if hasattr(csvy_model_config, 'abundance'):
            abundances_section = csvy_model_config.abundance
            abundance, isotope_abundance = read_uniform_abundances(
                abundances_section, no_of_shells)
        else:
            index, abundance, isotope_abundance = parse_csv_abundances(
                csvy_model_data)

        abundance = abundance.replace(np.nan, 0.0)
        abundance = abundance[abundance.sum(axis=1) > 0]

        norm_factor = abundance.sum(axis=0) + isotope_abundance.sum(axis=0)

        if np.any(np.abs(norm_factor - 1) > 1e-12):
            logger.warning("Abundances have not been normalized to 1."
                           " - normalizing")
            abundance /= norm_factor
            isotope_abundance /= norm_factor

        #isotope_abundance = IsotopeAbundances(isotope_abundance)
        isotope_abundance = IsotopeAbundances(
            isotope_abundance, time_0=csvy_model_config.model_isotope_time_0)
        #isotope_abundance.time_0 = csvy_model_config.model_isotope_time_0

        return cls(velocity=velocity,
                   homologous_density=homologous_density,
                   abundance=abundance,
                   isotope_abundance=isotope_abundance,
                   time_explosion=time_explosion,
                   t_radiative=t_radiative,
                   t_inner=t_inner,
                   luminosity_requested=luminosity_requested,
                   dilution_factor=dilution_factor,
                   v_boundary_inner=v_boundary_inner,
                   v_boundary_outer=v_boundary_outer,
                   electron_densities=electron_densities)
Пример #9
0
    def from_csvy(cls, config):
        """
        Create a new Radial1DModel instance from a Configuration object.

        Parameters
        ----------
        config : tardis.io.config_reader.Configuration

        Returns
        -------
        Radial1DModel

        """
        CSVY_SUPPORTED_COLUMNS = {
            'velocity', 'density', 't_rad', 'dilution_factor'
        }

        if os.path.isabs(config.csvy_model):
            csvy_model_fname = config.csvy_model
        else:
            csvy_model_fname = os.path.join(config.config_dirname,
                                            config.csvy_model)
        csvy_model_config, csvy_model_data = load_csvy(csvy_model_fname)
        base_dir = os.path.abspath(os.path.dirname(__file__))
        schema_dir = os.path.join(base_dir, '..', 'io', 'schemas')
        csvy_schema_file = os.path.join(schema_dir, 'csvy_model.yml')
        csvy_model_config = Configuration(
            validate_dict(csvy_model_config, schemapath=csvy_schema_file))

        if hasattr(csvy_model_data, 'columns'):
            abund_names = set([
                name for name in csvy_model_data.columns
                if nucname.iselement(name) or nucname.isnuclide(name)
            ])
            unsupported_columns = set(
                csvy_model_data.columns) - abund_names - CSVY_SUPPORTED_COLUMNS

            field_names = set(
                [field['name'] for field in csvy_model_config.datatype.fields])
            assert set(csvy_model_data.columns) - field_names == set(),\
                'CSVY columns exist without field descriptions'
            assert field_names - set(csvy_model_data.columns) == set(),\
                'CSVY field descriptions exist without corresponding csv data'
            if unsupported_columns != set():
                logger.warning(
                    "The following columns are specified in the csvy"
                    "model file, but are IGNORED by TARDIS: %s" %
                    (str(unsupported_columns)))

        time_explosion = config.supernova.time_explosion.cgs

        electron_densities = None
        temperature = None

        #if hasattr(csvy_model_config, 'v_inner_boundary'):
        #    v_boundary_inner = csvy_model_config.v_inner_boundary
        #else:
        #    v_boundary_inner = None

        #if hasattr(csvy_model_config, 'v_outer_boundary'):
        #    v_boundary_outer = csvy_model_config.v_outer_boundary
        #else:
        #    v_boundary_outer = None

        if hasattr(config, 'model'):
            if hasattr(config.model, 'v_inner_boundary'):
                v_boundary_inner = config.model.v_inner_boundary
            else:
                v_boundary_inner = None

            if hasattr(config.model, 'v_outer_boundary'):
                v_boundary_outer = config.model.v_outer_boundary
            else:
                v_boundary_outer = None
        else:
            v_boundary_inner = None
            v_boundary_outer = None

        if hasattr(csvy_model_config, 'velocity'):
            velocity = quantity_linspace(csvy_model_config.velocity.start,
                                         csvy_model_config.velocity.stop,
                                         csvy_model_config.velocity.num +
                                         1).cgs
        else:
            velocity_field_index = [
                field['name'] for field in csvy_model_config.datatype.fields
            ].index('velocity')
            velocity_unit = u.Unit(
                csvy_model_config.datatype.fields[velocity_field_index]
                ['unit'])
            velocity = csvy_model_data['velocity'].values * velocity_unit
            velocity = velocity.to('cm/s')

        if hasattr(csvy_model_config, 'density'):
            homologous_density = HomologousDensity.from_csvy(
                config, csvy_model_config)
        else:
            time_0 = csvy_model_config.model_density_time_0
            density_field_index = [
                field['name'] for field in csvy_model_config.datatype.fields
            ].index('density')
            density_unit = u.Unit(
                csvy_model_config.datatype.fields[density_field_index]['unit'])
            density_0 = csvy_model_data['density'].values * density_unit
            density_0 = density_0.to('g/cm^3')[1:]
            density_0 = density_0.insert(0, 0)
            homologous_density = HomologousDensity(density_0, time_0)

        no_of_shells = len(velocity) - 1

        # TODO -- implement t_radiative
        #t_radiative = None
        if temperature:
            t_radiative = temperature
        elif hasattr(csvy_model_data, 'columns'):
            if 't_rad' in csvy_model_data.columns:
                t_rad_field_index = [
                    field['name']
                    for field in csvy_model_config.datatype.fields
                ].index('t_rad')
                t_rad_unit = u.Unit(
                    csvy_model_config.datatype.fields[t_rad_field_index]
                    ['unit'])
                t_radiative = csvy_model_data['t_rad'].iloc[
                    0:].values * t_rad_unit
            else:
                t_radiative = None

        dilution_factor = None
        if hasattr(csvy_model_data, 'columns'):
            if 'dilution_factor' in csvy_model_data.columns:
                dilution_factor = csvy_model_data['dilution_factor'].iloc[
                    0:].to_numpy()

        elif config.plasma.initial_t_rad > 0 * u.K:
            t_radiative = np.ones(no_of_shells) * config.plasma.initial_t_rad
        else:
            t_radiative = None

        if config.plasma.initial_t_inner < 0.0 * u.K:
            luminosity_requested = config.supernova.luminosity_requested
            t_inner = None
        else:
            luminosity_requested = None
            t_inner = config.plasma.initial_t_inner

        if hasattr(csvy_model_config, 'abundance'):
            abundances_section = csvy_model_config.abundance
            abundance, isotope_abundance = read_uniform_abundances(
                abundances_section, no_of_shells)
        else:
            index, abundance, isotope_abundance = parse_csv_abundances(
                csvy_model_data)

        abundance = abundance.replace(np.nan, 0.0)
        abundance = abundance[abundance.sum(axis=1) > 0]
        abundance = abundance.loc[:, 1:]
        abundance.columns = np.arange(abundance.shape[1])

        norm_factor = abundance.sum(axis=0) + isotope_abundance.sum(axis=0)

        if np.any(np.abs(norm_factor - 1) > 1e-12):
            logger.warning("Abundances have not been normalized to 1."
                           " - normalizing")
            abundance /= norm_factor
            isotope_abundance /= norm_factor

        #isotope_abundance = IsotopeAbundances(isotope_abundance)
        isotope_abundance = IsotopeAbundances(
            isotope_abundance, time_0=csvy_model_config.model_isotope_time_0)
        #isotope_abundance.time_0 = csvy_model_config.model_isotope_time_0

        return cls(velocity=velocity,
                   homologous_density=homologous_density,
                   abundance=abundance,
                   isotope_abundance=isotope_abundance,
                   time_explosion=time_explosion,
                   t_radiative=t_radiative,
                   t_inner=t_inner,
                   luminosity_requested=luminosity_requested,
                   dilution_factor=dilution_factor,
                   v_boundary_inner=v_boundary_inner,
                   v_boundary_outer=v_boundary_outer,
                   electron_densities=electron_densities)
Пример #10
0
    def from_config_dict(cls, config_dict, validate=True, config_dirname=""):
        """
        Validating and subsequently parsing a config file.

        Parameters
        ----------
        config_dict : dict
            dictionary of a raw unvalidated config file
        validate : bool
            Turn validation on or off.

        Returns
        -------
        `tardis.config_reader.Configuration`
        """

        if validate:
            validated_config_dict = config_validator.validate_dict(config_dict)
        else:
            validated_config_dict = config_dict

        validated_config_dict["config_dirname"] = config_dirname

        # Montecarlo Section Implementation
        montecarlo_section = validated_config_dict["montecarlo"]
        if montecarlo_section["convergence_strategy"]["type"] == "damped":
            montecarlo_section[
                "convergence_strategy"
            ] = parse_convergence_section(
                montecarlo_section["convergence_strategy"]
            )
        elif montecarlo_section["convergence_strategy"]["type"] == "custom":
            raise NotImplementedError(
                'convergence_strategy is set to "custom"; '
                "you need to implement your specific convergence treatment"
            )
        else:
            raise ValueError(
                'convergence_strategy is not "damped" ' 'or "custom"'
            )

        enable_full_relativity = montecarlo_section["enable_full_relativity"]
        spectrum_integrated = (
            validated_config_dict["spectrum"]["method"] == "integrated"
        )
        if enable_full_relativity and spectrum_integrated:
            raise NotImplementedError(
                "The spectrum method is set to 'integrated' and "
                "enable_full_relativity to 'True'.\n"
                "The FormalIntegrator is not yet implemented for the full "
                "relativity mode. "
            )

        if "csvy_model" in validated_config_dict.keys():
            pass
        elif "model" in validated_config_dict.keys():

            # Model Section Validation
            model_section = validated_config_dict["model"]

            if model_section["structure"]["type"] == "specific":
                start_velocity = model_section["structure"]["velocity"]["start"]
                stop_velocity = model_section["structure"]["velocity"]["stop"]
                if stop_velocity.value < start_velocity.value:
                    raise ValueError(
                        "Stop Velocity Cannot Be Less than Start Velocity. \n"
                        f"Start Velocity = {start_velocity} \n"
                        f"Stop Velocity = {stop_velocity}"
                    )
            elif model_section["structure"]["type"] == "file":
                v_inner_boundary = model_section["structure"][
                    "v_inner_boundary"
                ]
                v_outer_boundary = model_section["structure"][
                    "v_outer_boundary"
                ]
                if v_outer_boundary.value < v_inner_boundary.value:
                    raise ValueError(
                        "Outer Boundary Velocity Cannot Be Less than Inner Boundary Velocity. \n"
                        f"Inner Boundary Velocity = {v_inner_boundary} \n"
                        f"Outer Boundary Velocity = {v_outer_boundary}"
                    )
            if "density" in model_section["structure"].keys():
                if (
                    model_section["structure"]["density"]["type"]
                    == "exponential"
                ):
                    rho_0 = model_section["structure"]["density"]["rho_0"]
                    v_0 = model_section["structure"]["density"]["v_0"]
                    if not rho_0.value > 0:
                        raise ValueError(
                            f"Density Specified is Invalid, {rho_0}"
                        )
                    if not v_0.value > 0:
                        raise ValueError(
                            f"Velocity Specified is Invalid, {v_0}"
                        )
                    if "time_0" in model_section["structure"]["density"].keys():
                        time_0 = model_section["structure"]["density"]["time_0"]
                        if not time_0.value > 0:
                            raise ValueError(
                                f"Time Specified is Invalid, {time_0}"
                            )
                elif (
                    model_section["structure"]["density"]["type"] == "power_law"
                ):
                    rho_0 = model_section["structure"]["density"]["rho_0"]
                    v_0 = model_section["structure"]["density"]["v_0"]
                    if not rho_0.value > 0:
                        raise ValueError(
                            f"Density Specified is Invalid, {rho_0}"
                        )
                    if not v_0.value > 0:
                        raise ValueError(
                            f"Velocity Specified is Invalid, {v_0}"
                        )
                    if "time_0" in model_section["structure"]["density"].keys():
                        time_0 = model_section["structure"]["density"]["time_0"]
                        if not time_0.value > 0:
                            raise ValueError(
                                f"Time Specified is Invalid, {time_0}"
                            )
                elif model_section["structure"]["density"]["type"] == "uniform":
                    value = model_section["structure"]["density"]["value"]
                    if not value.value > 0:
                        raise ValueError(
                            f"Density Value Specified is Invalid, {value}"
                        )
                    if "time_0" in model_section["structure"]["density"].keys():
                        time_0 = model_section["structure"]["density"]["time_0"]
                        if not time_0.value > 0:
                            raise ValueError(
                                f"Time Specified is Invalid, {time_0}"
                            )

            # SuperNova Section Validation
            supernova_section = validated_config_dict["supernova"]

            time_explosion = supernova_section["time_explosion"]
            luminosity_wavelength_start = supernova_section[
                "luminosity_wavelength_start"
            ]
            luminosity_wavelength_end = supernova_section[
                "luminosity_wavelength_end"
            ]
            if not time_explosion.value > 0:
                raise ValueError(
                    f"Time Of Explosion is Invalid, {time_explosion}"
                )
            if (
                luminosity_wavelength_start.value
                > luminosity_wavelength_end.value
            ):
                raise ValueError(
                    "Integral Limits for Luminosity Wavelength are Invalid, Start Limit > End Limit \n"
                    f"Luminosity Wavelength Start : {luminosity_wavelength_start} \n"
                    f"Luminosity Wavelength End : {luminosity_wavelength_end}"
                )

            # Plasma Section Validation
            plasma_section = validated_config_dict["plasma"]

            initial_t_inner = plasma_section["initial_t_inner"]
            initial_t_rad = plasma_section["initial_t_rad"]
            if not initial_t_inner.value >= -1:
                raise ValueError(
                    f"Initial Temperature of Inner Boundary Black Body is Invalid, {initial_t_inner}"
                )
            if not initial_t_rad.value >= -1:
                raise ValueError(
                    f"Initial Radiative Temperature is Invalid, {initial_t_inner}"
                )

            # Spectrum Section Validation
            spectrum_section = validated_config_dict["spectrum"]

            start = spectrum_section["start"]
            stop = spectrum_section["stop"]
            if start.value > stop.value:
                raise ValueError(
                    "Start Value of Spectrum Cannot be Greater than Stop Value. \n"
                    f"Start : {start} \n"
                    f"Stop : {stop}"
                )

        return cls(validated_config_dict)
Пример #11
0
    def from_config_dict(cls, config_dict, atom_data=None, test_parser=False,
                         validate=True,
                         config_dirname=''):
        """
        Validating and subsequently parsing a config file.


        Parameters
        ----------

        config_dict : ~dict
            dictionary of a raw unvalidated config file

        atom_data: ~tardis.atomic.AtomData
            atom data object. if `None` will be tried to be read from
            atom data file path in the config_dict [default=None]

        test_parser: ~bool
            switch on to ignore a working atom_data, mainly useful for
            testing this reader

        validate: ~bool
            Turn validation on or off.


        Returns
        -------

        `tardis.config_reader.Configuration`

        """

        if validate:
            validated_config_dict = config_validator.validate_dict(config_dict)
        else:
            validated_config_dict = config_dict

        #First let's see if we can find an atom_db anywhere:
        if test_parser:
            atom_data = None
        elif 'atom_data' in validated_config_dict.keys():
            if os.path.isabs(validated_config_dict['atom_data']):
                atom_data_fname = validated_config_dict['atom_data']
            else:
                atom_data_fname = os.path.join(config_dirname,
                                               validated_config_dict['atom_data'])
            validated_config_dict['atom_data_fname'] = atom_data_fname
        else:
            raise ConfigurationError('No atom_data key found in config or command line')

        if atom_data is None and not test_parser:
            logger.info('Reading Atomic Data from %s', atom_data_fname)
            atom_data = atomic.AtomData.from_hdf5(atom_data_fname)
        else:
            atom_data = atom_data



        #Parsing supernova dictionary
        validated_config_dict['supernova']['luminosity_nu_start'] = \
            validated_config_dict['supernova']['luminosity_wavelength_end'].to(
                u.Hz, u.spectral())
        try:
            validated_config_dict['supernova']['luminosity_nu_end'] = \
                (validated_config_dict['supernova']
                 ['luminosity_wavelength_start'].to(u.Hz, u.spectral()))
        except ZeroDivisionError:
            validated_config_dict['supernova']['luminosity_nu_end'] = (
                np.inf * u.Hz)

        validated_config_dict['supernova']['time_explosion'] = (
            validated_config_dict['supernova']['time_explosion'].cgs)

        validated_config_dict['supernova']['luminosity_requested'] = (
            validated_config_dict['supernova']['luminosity_requested'].cgs)

        #Parsing the model section

        model_section = validated_config_dict['model']
        v_inner = None
        v_outer = None
        mean_densities = None
        abundances = None



        structure_section = model_section['structure']

        if structure_section['type'] == 'specific':
            velocity = model_section['structure']['velocity']
            start, stop, num = velocity['start'], velocity['stop'], \
                               velocity['num']
            num += 1
            velocities = quantity_linspace(start, stop, num)

            v_inner, v_outer = velocities[:-1], velocities[1:]
            mean_densities = parse_density_section(
                model_section['structure']['density'], v_inner, v_outer,
                validated_config_dict['supernova']['time_explosion']).cgs

        elif structure_section['type'] == 'file':
            if os.path.isabs(structure_section['filename']):
                structure_fname = structure_section['filename']
            else:
                structure_fname = os.path.join(config_dirname,
                                               structure_section['filename'])

            v_inner, v_outer, mean_densities, inner_boundary_index, \
            outer_boundary_index = read_density_file(
                structure_fname, structure_section['filetype'],
                validated_config_dict['supernova']['time_explosion'],
                structure_section['v_inner_boundary'],
                structure_section['v_outer_boundary'])

        r_inner = validated_config_dict['supernova']['time_explosion'] * v_inner
        r_outer = validated_config_dict['supernova']['time_explosion'] * v_outer
        r_middle = 0.5 * (r_inner + r_outer)

        structure_section['v_inner'] = v_inner.cgs
        structure_section['v_outer'] = v_outer.cgs
        structure_section['mean_densities'] = mean_densities.cgs
        no_of_shells = len(v_inner)
        structure_section['no_of_shells'] = no_of_shells
        structure_section['r_inner'] = r_inner.cgs
        structure_section['r_outer'] = r_outer.cgs
        structure_section['r_middle'] = r_middle.cgs
        structure_section['volumes'] = ((4. / 3) * np.pi * \
                                       (r_outer ** 3 -
                                        r_inner ** 3)).cgs


        #### TODO the following is legacy code and should be removed
        validated_config_dict['structure'] = \
            validated_config_dict['model']['structure']
        # ^^^^^^^^^^^^^^^^


        abundances_section = model_section['abundances']

        if abundances_section['type'] == 'uniform':
            abundances = pd.DataFrame(columns=np.arange(no_of_shells),
                                      index=pd.Index(np.arange(1, 120), name='atomic_number'), dtype=np.float64)

            for element_symbol_string in abundances_section:
                if element_symbol_string == 'type': continue
                z = element_symbol2atomic_number(element_symbol_string)
                abundances.ix[z] = float(abundances_section[element_symbol_string])

        elif abundances_section['type'] == 'file':
            if os.path.isabs(abundances_section['filename']):
                abundances_fname = abundances_section['filename']
            else:
                abundances_fname = os.path.join(config_dirname,
                                                abundances_section['filename'])

            index, abundances = read_abundances_file(abundances_fname,
                                                     abundances_section['filetype'],
                                                     inner_boundary_index, outer_boundary_index)
            if len(index) != no_of_shells:
                raise ConfigurationError('The abundance file specified has not the same number of cells'
                                         'as the specified density profile')

        abundances = abundances.replace(np.nan, 0.0)

        abundances = abundances[abundances.sum(axis=1) > 0]

        norm_factor = abundances.sum(axis=0)

        if np.any(np.abs(norm_factor - 1) > 1e-12):
            logger.warning("Abundances have not been normalized to 1. - normalizing")
            abundances /= norm_factor

        validated_config_dict['abundances'] = abundances



        ########### DOING PLASMA SECTION ###############
        plasma_section = validated_config_dict['plasma']

        if plasma_section['initial_t_inner'] < 0.0 * u.K:
            luminosity_requested = validated_config_dict['supernova']['luminosity_requested']
            plasma_section['t_inner'] = ((luminosity_requested /
                                          (4 * np.pi * r_inner[0] ** 2 *
                                           constants.sigma_sb)) ** .25).to('K')
            logger.info('"initial_t_inner" is not specified in the plasma '
                        'section - initializing to %s with given luminosity',
                        plasma_section['t_inner'])
        else:
            plasma_section['t_inner'] = plasma_section['initial_t_inner']

        if plasma_section['initial_t_rad'] > 0 * u.K:
            plasma_section['t_rads'] = np.ones(no_of_shells) * \
                                       plasma_section['initial_t_rad']
        else:
            plasma_section['t_rads'] = None

        if plasma_section['disable_electron_scattering'] is False:
            logger.debug("Electron scattering switched on")
            validated_config_dict['montecarlo']['sigma_thomson'] = 6.652486e-25 / (u.cm ** 2)
        else:
            logger.warn('Disabling electron scattering - this is not physical')
            validated_config_dict['montecarlo']['sigma_thomson'] = 1e-200 / (u.cm ** 2)

        if plasma_section['helium_treatment'] == 'recomb-nlte':
            validated_config_dict['plasma']['helium_treatment'] == 'recomb-nlte'
        else:
            validated_config_dict['plasma']['helium_treatment'] == 'dilute-lte'





        ##### NLTE subsection of Plasma start
        nlte_validated_config_dict = {}
        nlte_species = []
        nlte_section = plasma_section['nlte']

        nlte_species_list = nlte_section.pop('species')
        for species_string in nlte_species_list:
            nlte_species.append(species_string_to_tuple(species_string))

        nlte_validated_config_dict['species'] = nlte_species
        nlte_validated_config_dict['species_string'] = nlte_species_list
        nlte_validated_config_dict.update(nlte_section)

        if 'coronal_approximation' not in nlte_section:
            logger.debug('NLTE "coronal_approximation" not specified in NLTE section - defaulting to False')
            nlte_validated_config_dict['coronal_approximation'] = False

        if 'classical_nebular' not in nlte_section:
            logger.debug('NLTE "classical_nebular" not specified in NLTE section - defaulting to False')
            nlte_validated_config_dict['classical_nebular'] = False


        elif nlte_section:  #checks that the dictionary is not empty
            logger.warn('No "species" given - ignoring other NLTE options given:\n%s',
                        pp.pformat(nlte_section))

        if not nlte_validated_config_dict:
            nlte_validated_config_dict['species'] = []

        plasma_section['nlte'] = nlte_validated_config_dict

        #^^^^^^^^^^^^^^ End of Plasma Section

        ##### Monte Carlo Section

        montecarlo_section = validated_config_dict['montecarlo']
        montecarlo_section['no_of_packets'] = \
            int(montecarlo_section['no_of_packets'])
        montecarlo_section['last_no_of_packets'] = \
            int(montecarlo_section['last_no_of_packets'])
        if montecarlo_section['last_no_of_packets'] < 0:
            montecarlo_section['last_no_of_packets'] = \
                montecarlo_section['no_of_packets']

        montecarlo_section['convergence_strategy'] = (
                parse_convergence_section(
                    montecarlo_section['convergence_strategy']))

        black_body_section = montecarlo_section['black_body_sampling']
        montecarlo_section['black_body_sampling'] = {}
        montecarlo_section['black_body_sampling']['start'] = \
            black_body_section['start']
        montecarlo_section['black_body_sampling']['end'] = \
            black_body_section['stop']
        montecarlo_section['black_body_sampling']['samples'] = \
            black_body_section['num']
        virtual_spectrum_section = montecarlo_section['virtual_spectrum_range']
        montecarlo_section['virtual_spectrum_range'] = {}
        montecarlo_section['virtual_spectrum_range']['start'] = \
            virtual_spectrum_section['start']
        montecarlo_section['virtual_spectrum_range']['end'] = \
            virtual_spectrum_section['stop']
        montecarlo_section['virtual_spectrum_range']['samples'] = \
            virtual_spectrum_section['num']

        ###### END of convergence section reading


        validated_config_dict['spectrum'] = parse_spectrum_list2dict(
            validated_config_dict['spectrum'])

        return cls(validated_config_dict, atom_data)
Пример #12
0
    def from_csvy(cls, config):
        """
        Create a new Radial1DModel instance from a Configuration object.

        Parameters
        ----------
        config : tardis.io.config_reader.Configuration

        Returns
        -------
        Radial1DModel
        """
        CSVY_SUPPORTED_COLUMNS = {
            "velocity",
            "density",
            "t_rad",
            "dilution_factor",
        }

        if os.path.isabs(config.csvy_model):
            csvy_model_fname = config.csvy_model
        else:
            csvy_model_fname = os.path.join(
                config.config_dirname, config.csvy_model
            )
        csvy_model_config, csvy_model_data = load_csvy(csvy_model_fname)
        base_dir = os.path.abspath(os.path.dirname(__file__))
        schema_dir = os.path.join(base_dir, "..", "io", "schemas")
        csvy_schema_file = os.path.join(schema_dir, "csvy_model.yml")
        csvy_model_config = Configuration(
            validate_dict(csvy_model_config, schemapath=csvy_schema_file)
        )

        if hasattr(csvy_model_data, "columns"):
            abund_names = set(
                [
                    name
                    for name in csvy_model_data.columns
                    if is_valid_nuclide_or_elem(name)
                ]
            )
            unsupported_columns = (
                set(csvy_model_data.columns)
                - abund_names
                - CSVY_SUPPORTED_COLUMNS
            )

            field_names = set(
                [field["name"] for field in csvy_model_config.datatype.fields]
            )
            assert (
                set(csvy_model_data.columns) - field_names == set()
            ), "CSVY columns exist without field descriptions"
            assert (
                field_names - set(csvy_model_data.columns) == set()
            ), "CSVY field descriptions exist without corresponding csv data"
            if unsupported_columns != set():
                logger.warning(
                    "The following columns are "
                    "specified in the csvy model file,"
                    f" but are IGNORED by TARDIS: {str(unsupported_columns)}"
                )

        time_explosion = config.supernova.time_explosion.cgs

        electron_densities = None
        temperature = None

        # if hasattr(csvy_model_config, 'v_inner_boundary'):
        #    v_boundary_inner = csvy_model_config.v_inner_boundary
        # else:
        #    v_boundary_inner = None

        # if hasattr(csvy_model_config, 'v_outer_boundary'):
        #    v_boundary_outer = csvy_model_config.v_outer_boundary
        # else:
        #    v_boundary_outer = None

        if hasattr(config, "model"):
            if hasattr(config.model, "v_inner_boundary"):
                v_boundary_inner = config.model.v_inner_boundary
            else:
                v_boundary_inner = None

            if hasattr(config.model, "v_outer_boundary"):
                v_boundary_outer = config.model.v_outer_boundary
            else:
                v_boundary_outer = None
        else:
            v_boundary_inner = None
            v_boundary_outer = None

        if hasattr(csvy_model_config, "velocity"):
            velocity = quantity_linspace(
                csvy_model_config.velocity.start,
                csvy_model_config.velocity.stop,
                csvy_model_config.velocity.num + 1,
            ).cgs
        else:
            velocity_field_index = [
                field["name"] for field in csvy_model_config.datatype.fields
            ].index("velocity")
            velocity_unit = u.Unit(
                csvy_model_config.datatype.fields[velocity_field_index]["unit"]
            )
            velocity = csvy_model_data["velocity"].values * velocity_unit
            velocity = velocity.to("cm/s")

        if hasattr(csvy_model_config, "density"):
            homologous_density = HomologousDensity.from_csvy(
                config, csvy_model_config
            )
        else:
            time_0 = csvy_model_config.model_density_time_0
            density_field_index = [
                field["name"] for field in csvy_model_config.datatype.fields
            ].index("density")
            density_unit = u.Unit(
                csvy_model_config.datatype.fields[density_field_index]["unit"]
            )
            density_0 = csvy_model_data["density"].values * density_unit
            density_0 = density_0.to("g/cm^3")[1:]
            density_0 = density_0.insert(0, 0)
            homologous_density = HomologousDensity(density_0, time_0)

        no_of_shells = len(velocity) - 1

        # TODO -- implement t_radiative
        # t_radiative = None
        if temperature:
            t_radiative = temperature
        elif hasattr(csvy_model_data, "columns"):
            if "t_rad" in csvy_model_data.columns:
                t_rad_field_index = [
                    field["name"] for field in csvy_model_config.datatype.fields
                ].index("t_rad")
                t_rad_unit = u.Unit(
                    csvy_model_config.datatype.fields[t_rad_field_index]["unit"]
                )
                t_radiative = (
                    csvy_model_data["t_rad"].iloc[0:].values * t_rad_unit
                )
            else:
                t_radiative = None

        dilution_factor = None
        if hasattr(csvy_model_data, "columns"):
            if "dilution_factor" in csvy_model_data.columns:
                dilution_factor = (
                    csvy_model_data["dilution_factor"].iloc[0:].to_numpy()
                )

        elif config.plasma.initial_t_rad > 0 * u.K:
            t_radiative = np.ones(no_of_shells) * config.plasma.initial_t_rad
        else:
            t_radiative = None

        if config.plasma.initial_t_inner < 0.0 * u.K:
            luminosity_requested = config.supernova.luminosity_requested
            t_inner = None
        else:
            luminosity_requested = None
            t_inner = config.plasma.initial_t_inner

        if hasattr(csvy_model_config, "abundance"):
            abundances_section = csvy_model_config.abundance
            abundance, isotope_abundance = read_uniform_abundances(
                abundances_section, no_of_shells
            )
        else:
            index, abundance, isotope_abundance = parse_csv_abundances(
                csvy_model_data
            )
            abundance = abundance.loc[:, 1:]
            abundance.columns = np.arange(abundance.shape[1])
            isotope_abundance = isotope_abundance.loc[:, 1:]
            isotope_abundance.columns = np.arange(isotope_abundance.shape[1])

        abundance = abundance.replace(np.nan, 0.0)
        abundance = abundance[abundance.sum(axis=1) > 0]
        isotope_abundance = isotope_abundance.replace(np.nan, 0.0)
        isotope_abundance = isotope_abundance[isotope_abundance.sum(axis=1) > 0]
        norm_factor = abundance.sum(axis=0) + isotope_abundance.sum(axis=0)

        if np.any(np.abs(norm_factor - 1) > 1e-12):
            logger.warning(
                "Abundances have not been normalized to 1." " - normalizing"
            )
            abundance /= norm_factor
            isotope_abundance /= norm_factor

        # isotope_abundance = IsotopeAbundances(isotope_abundance)
        isotope_abundance = IsotopeAbundances(
            isotope_abundance, time_0=csvy_model_config.model_isotope_time_0
        )
        # isotope_abundance.time_0 = csvy_model_config.model_isotope_time_0

        return cls(
            velocity=velocity,
            homologous_density=homologous_density,
            abundance=abundance,
            isotope_abundance=isotope_abundance,
            time_explosion=time_explosion,
            t_radiative=t_radiative,
            t_inner=t_inner,
            luminosity_requested=luminosity_requested,
            dilution_factor=dilution_factor,
            v_boundary_inner=v_boundary_inner,
            v_boundary_outer=v_boundary_outer,
            electron_densities=electron_densities,
        )