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 PATH variable is mismanaged.

Note

EXPERT USERS ONLY An empty dict indicates 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 otool is installed in macOS systems or ldd in 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:

Configuration object 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.16 output 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.16 output 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:

DataFrame whose 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), where n_threads is -1 for pure MPI runs. If no parallelization info is found, returns None.