Configure a Simulation#

This example demonstrates the various ways to configure a HYDRAD simulation.

import pathlib
import tempfile

import astropy.units as u

from pydrad.configure import Configure
from pydrad.configure.data import get_defaults
from pydrad.configure.util import get_clean_hydrad

HYDRAD requires setting many different configuration files, making it difficult and tedious to configure a simulation by hand. Fortunately, the pydrad package makes it easy to quickly configure a new simulation using Python.

Rather than editing each configuration file individually, an entire simulation can be configured using a single Python dict. Below is an example of a dictionary for configuring a simulation of a 80 Mm loop lasting 5000 s heated by a single 200 s nanoflare solved on an adaptive grid. A complete list of configuration parameters can be found in the `configuration-tables`_ page.

config_dict = {
    'general': {
        'loop_length': 80*u.Mm,
        'total_time': 5000*u.s,
        'footpoint_height': 5*u.Mm,
        'loop_inclination': 0*u.deg,
        'force_single_fluid': False,
        'heat_flux_timestep_limit':  1e-10*u.s,
        'logging_frequency': 1000,
        'minimum_collisional_coupling_timescale':  0.01*u.s,
        'output_interval':  10*u.s,
        'heat_flux_limiting_coefficient': 0.167,
        'use_kinetic_model': False,
        'write_file_equation_terms': True,
        'write_file_hydrogen_level_populations': True,
        'write_file_ion_populations': True,
        'write_file_physical': True,
        'write_file_timescales': True,
    },
    'grid': {
        'adapt': True,
        'adapt_every_n_time_steps': 1000,
        'enforce_conservation': True,
        'linear_restriction': True,
        'maximum_cell_width':  0.5*u.Mm,
        'maximum_fractional_difference': 0.1,
        'maximum_refinement_level': 12,
        'initial_refinement_level': 10,
        'maximum_variation': 0.1,
        'minimum_delta_s':  1.*u.cm,
        'minimum_fractional_difference': 0.05,
        'refine_on_density': True,
        'refine_on_electron_energy': True,
        'refine_on_hydrogen_energy': True,
    },
    'heating': {
        'alfven_wave': False,
        'background': {'use_initial_conditions': True},
        'beam': False,
        'electron_heating': 1.0,
        'events': [
            {'time_start': 0.*u.s,
             'rise_duration': 100*u.s,
             'decay_duration': 100*u.s,
             'total_duration': 200*u.s,
             'location': 40*u.Mm,
             'scale_height': 1e300 * u.cm,
             'rate': 0.1 * u.erg/u.s/(u.cm**3)},
        ],
    },
    'initial_conditions': {
        'footpoint_density':  1.e+12*u.cm**(-3),
        'footpoint_temperature':  10000.*u.K,
        'heating_range_fine_tuning': 10000.0,
        'heating_range_lower_bound':  1.e-08*u.erg / (u.cm**3*u.s),
        'heating_range_step_size': 0.01,
        'heating_range_upper_bound':  100.*u.erg / (u.cm**3*u.s),
        'isothermal': False,
        'use_poly_fit_gravity': False,
        'use_poly_fit_magnetic_field': False,
        'heating_location':  45.*u.Mm,
        'heating_scale_height':  1.e+300*u.cm
    },
    'radiation': {
        'abundance_dataset': 'asplund',
        'decouple_ionization_state_solver': False,
        'density_dependent_rates': False,
        'elements_equilibrium': [],
        'elements_nonequilibrium': [],
        'emissivity_dataset': 'chianti_v7',
        'nlte_chromosphere': False,
        'optically_thick_radiation': False,
        'ranges_dataset': 'ranges',
        'rates_dataset': 'chianti_v7',
        'use_power_law_radiative_losses': True
    },
    'solver': {
        'cutoff_ion_fraction': 1e-15,
        'epsilon': 0.01,
        'epsilon_d': 0.1,
        'epsilon_r': 1.8649415311920072,
        'maximum_optically_thin_density': 1.e+12*u.cm**(-3),
        'minimum_radiation_temperature':  20000.*u.K,
        'minimum_temperature':  10000.*u.K,
        'safety_advection': 1.0,
        'safety_atomic': 1.0,
        'safety_conduction': 1.0,
        'safety_radiation': 0.1,
        'safety_viscosity': 1.0,
        'timestep_increase_limit': 0.05,
        'zero_over_temperature_interval':  500.*u.K,
    }
}

The next step is to pass it to the ~pydrad.configure.Configure class which can parse it and print the needed configuration files,

c = Configure(config_dict)

We can preview some of the different configuration files that setup the HYDRAD simulation. This is often useful for debugging.

print(c.initial_conditions_header)
print(c.initial_conditions_cfg)
print(c.hydrad_header)
// ****
// *
// * #defines for configuring the hydrostatic model
// *
// * (c) Dr. Stephen J. Bradshaw
// *
// * Source code generated by pydrad on 2024-01-04_03.18.19 UTC
// *
// ****

// **** Output ****
// **** End of Output ****

// **** Physics ****
#include "../../Radiation_Model/source/config.h"





// **** Solver ****
#define EPSILON 0.01

// **** Grid ****
#define ADAPT
#define MIN_CELLS 160
#define MAX_CELLS 655360
#define MAX_REFINEMENT_LEVEL 12
#define INITIAL_REFINEMENT_LEVEL 10
#define MIN_DS 1.00000000e+00
#define MAX_VARIATION 1.1
Initial_Conditions/profiles/initial.amr

8.00000000e+09
0.0
5.00000000e+08

1.000000e+04

1.0000000e+12

4.50000000e+09
1.00000000e+300
-8.0
2.0
0.01
10000.0

Configuration file generated by pydrad on 2024-01-04_03.18.19 UTC
// ****
// *
// * #defines for configuring the hydrodynamic model
// *
// * (c) Dr. Stephen J. Bradshaw
// *
// * Source code generated by pydrad on 2024-01-04_03.18.19 UTC
// *
// ****

// **** Output ****
#define WRITE_FILE_PHYSICAL
#define WRITE_FILE_ION_POPULATIONS
#define WRITE_FILE_HSTATE
#define WRITE_FILE_SCALES
#define WRITE_FILE_TERMS
#define OUTPUT_EVERY_N_TIME_STEPS 1000
// **** End of Output ****

// **** Physics ****
#include "../../Heating_Model/source/config.h"
#include "../../Radiation_Model/source/config.h"
#define HEAT_FLUX_LIMITING_COEFFICIENT 0.167
#define TIME_STEP_LIMIT 1e-10

#include "collisions.h"


// **** End of Physics ****

// **** Solver ****

#define SAFETY_RADIATION 0.1
#define SAFETY_CONDUCTION 1.0
#define SAFETY_ADVECTION 1.0
#define SAFETY_VISCOSITY 1.0
#define TIME_STEP_INCREASE_LIMIT 1.05

#define MINIMUM_RADIATION_TEMPERATURE 20000.0
#define ZERO_OVER_TEMPERATURE_INTERVAL 500.0
#define MINIMUM_TEMPERATURE 10000.0

// **** End of Solver ****

// **** Grid ****
#define MAX_REFINEMENT_LEVEL 12
#define INITIAL_REFINEMENT_LEVEL 10
#define ADAPT
#define ADAPT_EVERY_N_TIME_STEPS 1000
#define REFINE_ON_DENSITY
#define REFINE_ON_ELECTRON_ENERGY
#define REFINE_ON_HYDROGEN_ENERGY
#define MIN_FRAC_DIFF 0.05
#define MAX_FRAC_DIFF 0.1
#define LINEAR_RESTRICTION
#define ENFORCE_CONSERVATION
// **** End of Grid ****

To actually setup a simulation, you’ll first need to obtain a copy of HYDRAD. You can use a copy you already have locally or use the following convenience function to grab the most recent version from GitHub

tmpdir = pathlib.Path(tempfile.mkdtemp())  # Change this to wherever you want to save your clean HYDRAD copy
hydrad_clean = tmpdir / 'hydrad-clean'
get_clean_hydrad(hydrad_clean, from_github=True)

The way HYDRAD works, a complete copy of the source code is required for every simulation run. When setting up a simulation, we pass both the path to our “clean” copy (which will remain unchanged) and the path to our new simulation. This function will write all of the needed aforementioned configuration files and run the hydrostatic solver which will provide the initial conditions for the actual simulation.

c.setup_simulation(tmpdir / 'test-run', hydrad_clean)
WARNING: ../source/misc.cpp: In function ‘void GetConfigurationParameters(PARAMETERS*)’:
../source/misc.cpp:31:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   31 | fscanf( pFile, "%s", pParams->szOutputFilename );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenRangesFile(char*)’:
../../Radiation_Model/source/element.cpp:63:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   63 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:66:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   66 | fscanf( pFile, "%i", &NumTemp );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:67:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   67 | fscanf( pFile, "%i", &NumDen );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:76:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   76 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:85:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   85 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenAbundanceFile(char*)’:
../../Radiation_Model/source/element.cpp:105:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  105 | fscanf( pFile, "%i", &buffer );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:121:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  121 |     fscanf( pFile, "%i", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenEmissivityFile(char*)’:
../../Radiation_Model/source/element.cpp:152:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  152 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:154:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  154 | fscanf( pFile, "%i", &NumIons );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:162:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  162 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:166:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  166 |     fscanf( pFile, "%i", &pSpecNum[i] );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:184:15: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  184 |         fscanf( pFile, "%c", &buffer );
      |         ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenRatesFile(char*)’:
../../Radiation_Model/source/element.cpp:237:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  237 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:251:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  251 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp: In member function ‘void CRadiation::Initialise(char*)’:
../../Radiation_Model/source/radiation.cpp:92:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   92 | fscanf( pFile, "%s", buffer1 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:96:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   96 | fscanf( pFile, "%s", buffer2 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:99:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   99 | fscanf( pFile, "%s", buffer3 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:103:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  103 | fscanf( pFile, "%s", buffer4 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:106:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  106 | fscanf( pFile, "%i", &NumElements );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:117:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  117 |     fscanf( pFile, "%s", buffer1 );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:120:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  120 |     fscanf( pFile, "%i", &(pZ[i]) );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp: In member function ‘void CRadiation::OpenRangesFile(char*)’:
../../Radiation_Model/source/radiation.cpp:156:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  156 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:159:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  159 | fscanf( pFile, "%i", &NumTemp );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:160:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  160 | fscanf( pFile, "%i", &NumDen );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:169:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  169 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:178:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  178 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp: In member function ‘void CPieceWiseFit::OpenPieceWiseFit(char*)’:
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:49:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   49 |                 fscanf( pInputFile, "%i", &iPolyOrder );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:51:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   51 |                 fscanf( pInputFile, "%i", &inumSD );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp: In member function ‘void CPieceWiseFit::GeneratePieceWiseFit(char*, char*)’:
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:92:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   92 |                 fscanf( pInputFile, "%i", &iPolyOrder );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:99:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   99 |                 fscanf( pInputFile, "%i", &inumSD );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:106:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  106 |                 fscanf( pInputFile, "%i", &inumPoints );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/source/file.cpp: In function ‘void ReadDouble(void*, double*)’:
../../Resources/source/file.cpp:24:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   24 | fscanf( pFile, "%s", buffer );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
 [pydrad.configure.util]
INFO:

Calculating initial hydrostatic conditions...

Peak heating range = 2.8184e-03 -> 2.8840e-03 erg cm^-3 s^-1

Optimum peak heating rate = 2.8837e-03 erg cm^-3 s^-1

Writing initial conditions file...

Done!

 [pydrad.configure.util]
WARNING: ../source/mesh.cpp: In member function ‘void CAdaptiveMesh::CreateInitialMesh()’:
../source/mesh.cpp:84:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   84 | fscanf( pFile, "%i", &iFileNumber );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../source/mesh.cpp:88:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   88 | fscanf( pFile, "%i", &Params.iNumberOfCells );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../source/mesh.cpp:112:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  112 |     fscanf( pFile, "%i", &(CellProperties.iRefinementLevel) );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../source/mesh.cpp:114:15: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  114 |         fscanf( pFile, "%i", &(CellProperties.iUniqueID[j]) );
      |         ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../source/eqns.cpp: In member function ‘void CEquations::Initialise()’:
../source/eqns.cpp:131:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  131 |                 fscanf( pFile, "%s", Params.Profiles );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../source/eqns.cpp:133:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  133 |                 fscanf( pFile, "%s", Params.GravityFilename );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../source/eqns.cpp:147:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  147 |                 fscanf( pFile, "%i", &iTemp );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Heating_Model/source/heat.cpp: In member function ‘void CHeat::GetHeatingData()’:
../../Heating_Model/source/heat.cpp:104:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  104 | fscanf( pConfigFile, "%i", &NumActivatedEvents );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp: In member function ‘void CIonFrac::Initialise(CIonFrac*, char*, PRADIATION)’:
../../Radiation_Model/source/ionfrac.cpp:49:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   49 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp:52:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   52 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp:55:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   55 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp:58:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   58 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp:61:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   61 |     fscanf( pFile, "%i", &NumElements );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp:74:15: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   74 |         fscanf( pFile, "%s", buffer );
      |         ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp:77:15: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   77 |         fscanf( pFile, "%i", &(pZ[i]) );
      |         ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp: In member function ‘void CIonFrac::ReadAllIonFracFromFile(void*)’:
../../Radiation_Model/source/ionfrac.cpp:199:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  199 |     fscanf( (FILE*)pFile, "%i", &(pZ[i]) );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/ionfrac.cpp: In member function ‘void CIonFrac::ReadIonFracFromFile(void*, int)’:
../../Radiation_Model/source/ionfrac.cpp:216:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  216 | fscanf( (FILE*)pFile, "%i", &(pZ[i]) );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenRangesFile(char*)’:
../../Radiation_Model/source/element.cpp:63:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   63 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:66:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   66 | fscanf( pFile, "%i", &NumTemp );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:67:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   67 | fscanf( pFile, "%i", &NumDen );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:76:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   76 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:85:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   85 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenAbundanceFile(char*)’:
../../Radiation_Model/source/element.cpp:105:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  105 | fscanf( pFile, "%i", &buffer );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:121:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  121 |     fscanf( pFile, "%i", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenEmissivityFile(char*)’:
../../Radiation_Model/source/element.cpp:152:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  152 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:154:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  154 | fscanf( pFile, "%i", &NumIons );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:162:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  162 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:166:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  166 |     fscanf( pFile, "%i", &pSpecNum[i] );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:184:15: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  184 |         fscanf( pFile, "%c", &buffer );
      |         ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp: In member function ‘void CElement::OpenRatesFile(char*)’:
../../Radiation_Model/source/element.cpp:237:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  237 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/element.cpp:251:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  251 |     fscanf( pFile, "%s", buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp: In member function ‘void CRadiation::Initialise(char*)’:
../../Radiation_Model/source/radiation.cpp:92:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   92 | fscanf( pFile, "%s", buffer1 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:96:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   96 | fscanf( pFile, "%s", buffer2 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:99:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   99 | fscanf( pFile, "%s", buffer3 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:103:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  103 | fscanf( pFile, "%s", buffer4 );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:106:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  106 | fscanf( pFile, "%i", &NumElements );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:117:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  117 |     fscanf( pFile, "%s", buffer1 );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:120:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  120 |     fscanf( pFile, "%i", &(pZ[i]) );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp: In member function ‘void CRadiation::OpenRangesFile(char*)’:
../../Radiation_Model/source/radiation.cpp:156:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  156 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:159:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  159 | fscanf( pFile, "%i", &NumTemp );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:160:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  160 | fscanf( pFile, "%i", &NumDen );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:169:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  169 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Radiation_Model/source/radiation.cpp:178:11: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  178 |     fscanf( pFile, "%c", &buffer );
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp: In member function ‘void CPieceWiseFit::OpenPieceWiseFit(char*)’:
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:49:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   49 |                 fscanf( pInputFile, "%i", &iPolyOrder );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:51:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   51 |                 fscanf( pInputFile, "%i", &inumSD );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp: In member function ‘void CPieceWiseFit::GeneratePieceWiseFit(char*, char*)’:
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:92:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   92 |                 fscanf( pInputFile, "%i", &iPolyOrder );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:99:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   99 |                 fscanf( pInputFile, "%i", &inumSD );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/Utils/generatePieceWiseFit/source/piecewisefit.cpp:106:23: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  106 |                 fscanf( pInputFile, "%i", &inumPoints );
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../Resources/source/file.cpp: In function ‘void ReadDouble(void*, double*)’:
../../Resources/source/file.cpp:24:7: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   24 | fscanf( pFile, "%s", buffer );
      | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
 [pydrad.configure.util]
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)

To avoid having to repeatedly setup the configuration dictionary, the simulation setup can be serialized to an ASDF file, a human-readable, structured plain text file in the YAML format. These ASDF files are structured just like the config directory and can be easily read and written.

To save the configuration to disk and then load it back into a dict,

asdf_config = tmpdir / 'test_config.asdf'
c.save_config(asdf_config)
config_from_disk = Configure.load_config(asdf_config)
print(config_from_disk)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pydrad/envs/latest/lib/python3.11/site-packages/astropy/units/format/utils.py:219: UnitsWarning: The unit 'erg' has been deprecated in the VOUnit standard. Suggested: cm**2.g.s**-2.
  warnings.warn(message, UnitsWarning)
{'asdf_library': {'author': 'The ASDF Developers', 'homepage': 'http://github.com/asdf-format/asdf', 'name': 'asdf', 'version': '3.0.1'}, 'history': {'extensions': [{'extension_class': 'asdf.extension._manifest.ManifestExtension', 'extension_uri': 'asdf://asdf-format.org/core/extensions/core-1.5.0', 'software': {'name': 'asdf', 'version': '3.0.1'}}, {'extension_class': 'asdf_astropy._manifest.CompoundManifestExtension', 'extension_uri': 'asdf://astropy.org/core/extensions/core-1.5.0', 'software': {'name': 'asdf-astropy', 'version': '0.5.0'}}]}, 'general': {'footpoint_height': <Quantity 5. Mm>, 'force_single_fluid': False, 'heat_flux_limiting_coefficient': 0.167, 'heat_flux_timestep_limit': <Quantity 1.e-10 s>, 'logging_frequency': 1000, 'loop_inclination': <Quantity 0. deg>, 'loop_length': <Quantity 80. Mm>, 'minimum_collisional_coupling_timescale': <Quantity 0.01 s>, 'output_interval': <Quantity 10. s>, 'total_time': <Quantity 5000. s>, 'use_kinetic_model': False, 'write_file_equation_terms': True, 'write_file_hydrogen_level_populations': True, 'write_file_ion_populations': True, 'write_file_physical': True, 'write_file_timescales': True}, 'grid': {'adapt': True, 'adapt_every_n_time_steps': 1000, 'enforce_conservation': True, 'initial_refinement_level': 10, 'linear_restriction': True, 'maximum_cell_width': <Quantity 0.5 Mm>, 'maximum_fractional_difference': 0.1, 'maximum_refinement_level': 12, 'maximum_variation': 0.1, 'minimum_delta_s': <Quantity 1. cm>, 'minimum_fractional_difference': 0.05, 'refine_on_density': True, 'refine_on_electron_energy': True, 'refine_on_hydrogen_energy': True}, 'heating': {'alfven_wave': False, 'background': {'use_initial_conditions': True}, 'beam': False, 'electron_heating': 1.0, 'events': [{'decay_duration': <Quantity 100. s>, 'location': <Quantity 40. Mm>, 'rate': <Quantity 0.1 erg / (s cm3)>, 'rise_duration': <Quantity 100. s>, 'scale_height': <Quantity 1.e+300 cm>, 'time_start': <Quantity 0. s>, 'total_duration': <Quantity 200. s>}]}, 'initial_conditions': {'footpoint_density': <Quantity 1.e+12 1 / cm3>, 'footpoint_temperature': <Quantity 10000. K>, 'heating_location': <Quantity 45. Mm>, 'heating_range_fine_tuning': 10000.0, 'heating_range_lower_bound': <Quantity 1.e-08 erg / (s cm3)>, 'heating_range_step_size': 0.01, 'heating_range_upper_bound': <Quantity 100. erg / (s cm3)>, 'heating_scale_height': <Quantity 1.e+300 cm>, 'isothermal': False, 'use_poly_fit_gravity': False, 'use_poly_fit_magnetic_field': False}, 'radiation': {'abundance_dataset': 'asplund', 'decouple_ionization_state_solver': False, 'density_dependent_rates': False, 'elements_equilibrium': [], 'elements_nonequilibrium': [], 'emissivity_dataset': 'chianti_v7', 'nlte_chromosphere': False, 'optically_thick_radiation': False, 'ranges_dataset': 'ranges', 'rates_dataset': 'chianti_v7', 'use_power_law_radiative_losses': True}, 'solver': {'cutoff_ion_fraction': 1e-15, 'epsilon': 0.01, 'epsilon_d': 0.1, 'epsilon_r': 1.8649415311920072, 'maximum_optically_thin_density': <Quantity 1.e+12 1 / cm3>, 'minimum_radiation_temperature': <Quantity 20000. K>, 'minimum_temperature': <Quantity 10000. K>, 'safety_advection': 1.0, 'safety_atomic': 1.0, 'safety_conduction': 1.0, 'safety_radiation': 0.1, 'safety_viscosity': 1.0, 'timestep_increase_limit': 0.05, 'zero_over_temperature_interval': <Quantity 500. K>}}

Additionally, ~pydrad also includes a default set of configuration parameters. These are often a useful starting point when creating your own configuration.

config_default = get_defaults()
print(config_default)
{'asdf_library': {'author': 'Space Telescope Science Institute', 'homepage': 'http://github.com/spacetelescope/asdf', 'name': 'asdf', 'version': '2.7.1'}, 'history': {'extensions': [{'extension_class': 'astropy.io.misc.asdf.extension.AstropyAsdfExtension', 'software': {'name': 'astropy', 'version': '4.0.1.post1'}}, {'extension_class': 'asdf.extension.BuiltinExtension', 'software': {'name': 'asdf', 'version': '2.7.1'}}]}, 'general': {'footpoint_height': <Quantity 5.e+08 cm>, 'force_single_fluid': False, 'heat_flux_limiting_coefficient': 0.167, 'heat_flux_timestep_limit': <Quantity 1.e-10 s>, 'logging_frequency': 1000, 'loop_inclination': <Quantity 0. deg>, 'loop_length': <Quantity 90. Mm>, 'minimum_collisional_coupling_timescale': <Quantity 0.01 s>, 'output_interval': <Quantity 1. s>, 'total_time': <Quantity 3. h>, 'use_kinetic_model': False, 'write_file_equation_terms': True, 'write_file_hydrogen_level_populations': True, 'write_file_ion_populations': True, 'write_file_physical': True, 'write_file_timescales': True}, 'grid': {'adapt': True, 'adapt_every_n_time_steps': 1000, 'enforce_conservation': True, 'initial_refinement_level': 10, 'linear_restriction': True, 'maximum_cell_width': <Quantity 0.5 Mm>, 'maximum_fractional_difference': 0.2, 'maximum_refinement_level': 12, 'maximum_variation': 0.1, 'minimum_delta_s': <Quantity 1. cm>, 'minimum_fractional_difference': 0.1, 'refine_on_density': True, 'refine_on_electron_energy': True, 'refine_on_hydrogen_energy': True}, 'heating': {'alfven_wave': False, 'background': {'use_initial_conditions': True}, 'beam': False, 'electron_heating': 1.0, 'events': []}, 'initial_conditions': {'footpoint_density': <Quantity 1.e+11 1 / cm3>, 'footpoint_temperature': <Quantity 20000. K>, 'heating_location': <Quantity 45. Mm>, 'heating_range_fine_tuning': 10000.0, 'heating_range_lower_bound': <Quantity 1.e-08 erg / (s cm3)>, 'heating_range_step_size': 0.001, 'heating_range_upper_bound': <Quantity 100. erg / (s cm3)>, 'heating_scale_height': <Quantity 1.e+300 cm>, 'isothermal': False, 'use_poly_fit_gravity': False, 'use_poly_fit_magnetic_field': False}, 'radiation': {'abundance_dataset': 'asplund', 'decouple_ionization_state_solver': False, 'density_dependent_rates': False, 'elements_equilibrium': [], 'elements_nonequilibrium': [], 'emissivity_dataset': 'chianti_v7', 'nlte_chromosphere': False, 'optically_thick_radiation': False, 'ranges_dataset': 'ranges', 'rates_dataset': 'chianti_v7', 'use_power_law_radiative_losses': True}, 'solver': {'cutoff_ion_fraction': 1e-15, 'epsilon': 0.01, 'epsilon_d': 0.1, 'epsilon_r': 1.8649415311920072, 'maximum_optically_thin_density': <Quantity 1.e+12 1 / cm3>, 'minimum_radiation_temperature': <Quantity 20000. K>, 'minimum_temperature': <Quantity 10000. K>, 'safety_advection': 1.0, 'safety_atomic': 1.0, 'safety_conduction': 1.0, 'safety_radiation': 0.1, 'safety_viscosity': 1.0, 'timestep_increase_limit': 0.05, 'zero_over_temperature_interval': <Quantity 500. K>}}

If you make local modifications to the HYDRAD code, you may need configuration options not in the included templates. To use custom configuration options, you can inject your own modified templates of the configuration files which take advantage of any custom options.

To see the available templates,

print(c.templates)
['build_script.bat', 'coefficients.cfg', 'collisions.h', 'heating.beam.cfg', 'heating.cfg', 'heating.config.h', 'hydrad.cfg', 'hydrad.config.h', 'initial_conditions.cfg', 'initial_conditions.config.h', 'radiation.config.h', 'radiation.elements.cfg']

Say we want to add an option, MY_NEW_PARAM to the collisions.h file. To get the current unrendered template,

print(c.get_raw_template('collisions.h'))
// ****
// *
// * #defines for configuring the shortest collisional coupling timescale
// *
// * (c) Dr. Stephen J. Bradshaw
// *
// * Source code generated by pydrad on {{ date }}
// *
// ****

// **** Physics ****
#define MINIMUM_COLLISIONAL_COUPLING_TIME_SCALE {{ general.minimum_collisional_coupling_timescale | units_filter('s') }}
{% if general.force_single_fluid -%}#define FORCE_SINGLE_FLUID{%- endif %}
// **** End of Physics ****

We can then create a new template with our new value,

new_collisions = """// ****
// *
// * #defines for configuring the shortest collisional coupling timescale
// *
// * (c) Dr. Stephen J. Bradshaw
// *
// * Source code generated by pydrad on {{ date }}
// *
// ****

// **** Physics ****
#define MINIMUM_COLLISIONAL_COUPLING_TIME_SCALE {{ general.minimum_collisional_coupling_timescale | units_filter('s') }}
{% if general.force_single_fluid -%}#define FORCE_SINGLE_FLUID{%- endif %}
// **** End of Physics ****
#define MY_NEW_PARAM {{ general.my_new_param }}"""

add our new parameter to the configuration directory, and then pass the template to the Configure object,

config_dict['general']['my_new_param'] = 100
c_custom = Configure(config_dict, templates={'collisions.h': new_collisions})
print(c_custom.collisions_header)
// ****
// *
// * #defines for configuring the shortest collisional coupling timescale
// *
// * (c) Dr. Stephen J. Bradshaw
// *
// * Source code generated by pydrad on 2024-01-04_03.18.29 UTC
// *
// ****

// **** Physics ****
#define MINIMUM_COLLISIONAL_COUPLING_TIME_SCALE 0.01

// **** End of Physics ****
#define MY_NEW_PARAM 100

Total running time of the script: (0 minutes 10.137 seconds)

Gallery generated by Sphinx-Gallery