4. Programmatic Interface
Bfrescox is a Python package that builds an internal, barebones Frescox binary during installation. It also provides an interface for configuring and running Frescox simulations using the internal binary as well as to access results.
4.1. Infrastructure
- bfrescox.test(verbosity: int = 1) bool
Run the full set of tests in the package with results presented to caller using a simple text interface.
This is included so that users can test their actual installation directly or record test results in Jupyter notebook output for reproducibility via:
bfrescox.test()
- Args:
- verbosity:
verbosity level to pass to
unittest.TextTestRunner
- Returns:
True if all tests in package passed; False, otherwise.
- bfrescox.information()
All code that would like to use the Frescox executable built for this package should use this information to obtain the absolute path to the executable to avoid the situation of simply calling Frescox with no path and inadvertently using a different executable if, for example, the
PATHvariable is mismanaged.Note
EXPERT USERS ONLY An empty
dictindicates a hollow Bfrescox installation- Returns
- dict: contains information regarding the Frescox executable
used by the package.
- bfrescox.print_information()
Print information about the Frescox executable used internally by the package.
If
otoolis installed in macOS systems orlddin unix-based systems, then Frescox external dependences are listed.
4.2. Simulation Configuration
- class bfrescox.Configuration(filename: str | PathLike)
Class representing a Frescox input configuration.
- Args:
- filename (Union[str, PathLike]): Path to Frescox Fortran namelist
input file
- Raises:
TypeError: If filename is not a str or Path ValueError: If filename does not exist or is not a file
- classmethod from_NML(filename: str | PathLike) Configuration
- Args:
- filename (Union[str, PathLike]): Path to Frescox Fortran
namelist input file
- Returns:
- Configuration: constructed from contents of given Frescox
Fortran namelist input file
- classmethod from_template(template_path: str | PathLike, output_path: str | PathLike, parameters: dict, overwrite: bool = False) Configuration
Read in a template nml file, replace ‘@key@’ placeholders with corresponding values from parameters, and write result to output_path. The set of possible keys in the template file must exactly match the keys in parameters, or a ValueError will be raised.
For example, if one has a Frescox template file with a line like this defining a potential:
` &POT kp=1 type=1 p1=@V@ p2=@r@ p3=@a@ p4=@W@ p5=@rw@ p6=@aw@ / &POT kp=1 type=2 p1=@Vs@ p2=@rw@ p3=@aw@ p4=@Ws@ p5=@rw@ p6=@aw@ / `Then the parameters dict should have the keys V, r, a, W, rw, aw, Vs and Ws. Notice that rw and aw are used in multiple places in the template file. The corresponding values in parameters will be substituted into each location where the placeholder appears.
- Args:
- template_path (Union[str, PathLike]): Path to the template
NML file.
- output_path (Union[str, PathLike]): Path to write the
modified NML file.
- parameters (dict): Dictionary of parameters to replace in
the template. Keys should match placeholders in the template, but should not include the @ characters. Corresponding values are the desired replacements in the output file.
- overwrite (bool): Whether to overwrite output_path if it
already exists.
- classmethod from_json(filename: str | PathLike) Configuration
- Args:
- filename (Union[str, PathLike]): Path to Bfrescox format
JSON file
- Returns:
- Configurationconstructed from contents of given
Bfrescox format JSON file
- write_to_nml(filename: str | PathLike, overwrite: bool = False) None
Write configuration to Frescox Fortran namelist input file.
- Args:
- filename (Union[str, PathLike]): Path to write Frescox Fortran
namelist input file
- overwrite (bool): Whether to overwrite filename if it
already exists.
- Raises:
TypeError: If filename is not a str or Path RuntimeError: If filename already exists and overwrite is False
4.3. Template Generation
- bfrescox.generate_elastic_template(output_path: str | PathLike, reaction_name: str, target_mass_amu: float, target_atomic_number: int, target_spin: Fraction | str | int | float, projectile_mass_amu: float, projectile_atomic_number: int, projectile_spin: Fraction | str | int | float, E_lab_MeV: float, J_tot_min: Fraction | str | int | float, J_tot_max: Fraction | str | int | float, E_0_MeV: float, R_match_fm: float, step_size_fm: float, overwrite: bool = False)
Generate an elastic scattering input template for Frescox.
Todo
This has hardcoded formatting for writing values to file. This package should not pretend to know what precision is needed by all applications. Rather, it should write all values in full precision.
Seems like we should be doing explicit type checking of actual arguments. Better yet if writing to full precision and type checking can be done by one single routine in the package’s private interface that this just calls.
Ideally the text placeholders in the template would include units in the name so that when mapping arguments to placeholders below we have something like
"RMATCH_FM": R_match_fm.
- Args:
- output_path:
Path to save the generated template file
- reaction_name:
Name of the reaction for file naming
- target_mass_amu:
Mass of the target nucleus
- target_atomic_number:
Charge of the target nucleus
- target_spin:
Spin of the target nucleus (integer or half-integer)
- projectile_mass_amu:
Mass of the projectile nucleus
- projectile_atomic_number:
Charge of the projectile nucleus
- projectile_spin:
Spin of the projectile nucleus (integer or half-integer). Must be convertible to Fraction.
- E_lab_MeV:
Laboratory energy of the projectile in MeV
- J_tot_min:
Minimum total angular momentum (integer or half-integer). Must be convertible to Fraction.
- J_tot_max:
Maximum total angular momentum (integer or half-integer). Must be convertible to Fraction.
- E_0_MeV:
Ground state energy of the target nucleus in MeV (usually 0, larger for isomeric or excited final state)
- R_match_fm:
Matching radius in fm
- step_size_fm:
Step size for the radial mesh in fm
- overwrite:
Whether to overwrite the output file if it already exists
- bfrescox.generate_inelastic_template(output_path: str | PathLike, target_mass_amu: float, target_atomic_number: float, projectile_mass_amu: float, projectile_atomic_number: float, projectile_spin: Fraction | str | int | float, E_lab_MeV: float, J_tot_min: Fraction | str | int | float, J_tot_max: Fraction | str | int | float, reaction_name: str, target_state_spins: List[Fraction | str | int | float], target_state_parities: List[bool], target_state_energies_MeV: List[float], multipoles: ndarray, R_match_fm: float, step_size_fm: float, overwrite: bool = False)
Generate an inelastic scattering input template for Frescox.
Todo
This has hardcoded formatting for writing values to file. This package should not pretend to know what precision is needed by all applications. Rather, it should write all values in full precision.
Seems like we should be doing explicit type checking of actual arguments. Better yet if writing to full precision and type checking can be done by one single routine in the package’s private interface that this just calls.
Ideally the text placeholders in the template would include units in the name so that when mapping arguments to placeholders below we have something like
"RMATCH_FM": R_match_fm.Code checks if multipoles is None. However, neither the documentation nor the type hints indicate that None is an acceptable argument. The meaning of a None argument is not explained.
- Args:
- output_path:
Path to save the generated template file
- target_mass_amu:
Mass of the target nucleus
- target_atomic_number:
Charge of the target nucleus
- projectile_mass_amu:
Mass of the projectile nucleus
- projectile_atomic_number:
Charge of the projectile nucleus
- projectile_spin:
Spin of the projectile nucleus (integer or half-integer). Must be convertible to Fraction.
- E_lab_MeV:
Laboratory energy of the projectile in MeV
- J_tot_min:
Minimum total angular momentum (integer or half-integer). Must be convertible to Fraction.
- J_tot_max:
Maximum total angular momentum (integer or half-integer). Must be convertible to Fraction.
- reaction_name:
Name of the reaction for file naming
- target_state_spins:
List of spin states of the target nucleus (integers or half-integers). List elements must be convertible to Fraction.
- target_state_parities:
List of parities for the target states (True for positive, False for negative)
- target_state_energies_MeV:
List of excitation energies of the target states in MeV
- multipoles:
numpy array of multipole transition orders (e.g., [2, 3] for quadrupole and octupole).
- R_match_fm:
Matching radius in fm
- step_size_fm:
Step size for the radial mesh in fm
- overwrite:
Whether to overwrite the output file if it already exists
4.4. Execution & Results
- bfrescox.run_simulation(configuration: Configuration, filename: str | PathLike, overwrite: dict | None = False, external: dict | None = None, cwd: str | PathLike | None = None)
Run a Frescox simulation based on the given simulation configuration object. Standard output and error are written to a file with the given output filename. Other outputs are written to disk based on the Frescox output settings. The Frescox Fortran namelist configuration file generated from the configuration object for the simulation is written alongside the output file.
- Args:
- configuration:
Configurationobject that specifies the simulation to run.- filename:
Filename including path of file to write Frescox stdout/stderr logging to
- overwrite:
If False, then an error is raised if either of the simulation input or output files exist
- external: (Bfrescox only)
EXPERT USERS ONLY
- cwd:
Pre-existing directory to run the simulation in. If None, the current working directory is used.
- bfrescox.parse_fort16(filename: str | PathLike) dict[str, DataFrame]
Parse out angular distributions from the given Frescox
fort.16output file. Each ‘@sN … &’ block becomes one entry labeled ‘channel_N’, with all numeric columns and proper names (‘Theta’, ‘sigma’, ‘iT11’, etc.).Todo
Convert asserts to error messages where we might be surprised by different formatting.
Parse out (Partition, Excit, near/far) information for each data block for testing. Consider using that so that we can return a single DataFrame with a MultiIndex. If not, should the index of the DataFrames be the angle Theta?
- Args:
- filename:
Path to the Frescox
fort.16output file
- Returns:
Dictionary with keys ‘channel_1’, ‘channel_2’, etc., each containing a DataFrame of the corresponding data. If no valid data blocks are found, returns an empty dictionary.
- bfrescox.parse_performance_results(filename: str | PathLike) DataFrame
Parse Frescox performance results from Frescox logging written to standard output.
Note
This code is a prototype, is not under test, and has not been reviewed.
Todo
Some timing lines aren’t printed on their own line. Put in NaNs? Is this due to an issue in Frescox logging to file or is it correct logging? If correct, is NaN the appropriate value or is this us currently throwing up our hands?
- Args:
- filename:
Path to the file containing the Frescox standard output log data
- Returns:
DataFramewhose rows are indexed by MPI rank.
- bfrescox.parse_parallelization_setup(filename: str | PathLike) tuple[int, int] | None
Parse Frescox parallelization setup from Frescox logging written to standard output.
Note
This code is a prototype, is not under test, and has not been reviewed.
Todo
If omp_n_found == 1 and mpi_n_found == 0, then should we confirm that omp_n_procs has a certain value? For example, should omp_n_procs == 1 always be true?
- Args:
- filename:
Path to the file containing the Frescox standard output log data
- Returns:
If parallelization info is found, returns a tuple
(n_mpi_procs, n_threads), wheren_threadsis -1 for pure MPI runs. If no parallelization info is found, returns None.