mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Merge branch 'develop' of github.com:myerspat/openmc into otimize-photon-calcxs
This commit is contained in:
commit
8eb21c0af2
78 changed files with 2191 additions and 459 deletions
|
|
@ -455,9 +455,10 @@ target_compile_options(openmc PRIVATE ${cxxflags})
|
|||
target_include_directories(openmc PRIVATE ${CMAKE_BINARY_DIR}/include)
|
||||
target_link_libraries(openmc libopenmc)
|
||||
|
||||
# Ensure C++14 standard is used
|
||||
# Ensure C++14 standard is used and turn off GNU extensions
|
||||
target_compile_features(openmc PUBLIC cxx_std_14)
|
||||
target_compile_features(libopenmc PUBLIC cxx_std_14)
|
||||
set_target_properties(openmc libopenmc PROPERTIES CXX_EXTENSIONS OFF)
|
||||
|
||||
#===============================================================================
|
||||
# Python package
|
||||
|
|
|
|||
|
|
@ -490,9 +490,10 @@ attributes/sub-elements:
|
|||
independent distributions of r-, phi-, and z-coordinates where phi is the
|
||||
azimuthal angle and the origin for the cylindrical coordinate system is
|
||||
specified by origin. A "spherical" spatial distribution specifies
|
||||
independent distributions of r-, theta-, and phi-coordinates where theta
|
||||
is the angle with respect to the z-axis, phi is the azimuthal angle, and
|
||||
the sphere is centered on the coordinate (x0,y0,z0).
|
||||
independent distributions of r-, cos_theta-, and phi-coordinates where
|
||||
cos_theta is the cosine of the angle with respect to the z-axis, phi is
|
||||
the azimuthal angle, and the sphere is centered on the coordinate
|
||||
(x0,y0,z0).
|
||||
|
||||
*Default*: None
|
||||
|
||||
|
|
|
|||
|
|
@ -4,18 +4,34 @@
|
|||
Track File Format
|
||||
=================
|
||||
|
||||
The current revision of the particle track file format is 2.0.
|
||||
The current revision of the particle track file format is 3.0.
|
||||
|
||||
**/**
|
||||
|
||||
:Attributes: - **filetype** (*char[]*) -- String indicating the type of file.
|
||||
- **version** (*int[2]*) -- Major and minor version of the track
|
||||
file format.
|
||||
- **n_particles** (*int*) -- Number of particles for which tracks
|
||||
are recorded.
|
||||
- **n_coords** (*int[]*) -- Number of coordinates for each
|
||||
particle.
|
||||
|
||||
:Datasets:
|
||||
- **coordinates_<i>** (*double[][3]*) -- (x,y,z) coordinates for the
|
||||
*i*-th particle.
|
||||
- **track_<b>_<g>_<p>** (Compound type) -- Particle track information
|
||||
for source particle in batch *b*, generation *g*, and particle
|
||||
number *p*. particle. The compound type has fields ``r``, ``u``,
|
||||
``E``, ``time``, ``wgt``, ``cell_id``, ``cell_instance``, and
|
||||
``material_id``, which represent the position (each coordinate in
|
||||
[cm]), direction, energy in [eV], time in [s], weight, cell ID,
|
||||
cell instance, and material ID, respectively. When the particle is
|
||||
present in a cell with no material assigned, the material ID is
|
||||
given as -1. Note that this array contains information for one or
|
||||
more primary/secondary particles originating. The starting index
|
||||
for each primary/secondary particle is given by the ``offsets``
|
||||
attribute.
|
||||
|
||||
:Attributes: - **n_particles** (*int*) -- Number of
|
||||
primary/secondary particles for the source history.
|
||||
- **offsets** (*int[]*) Offset (starting index) into
|
||||
the array for each primary/secondary particle. The
|
||||
last offset should match the total size of the
|
||||
array.
|
||||
- **particles** (*int[]*) -- Particle type for each
|
||||
primary/secondary particle (0=neutron, 1=photon,
|
||||
2=electron, 3=positron).
|
||||
|
|
|
|||
|
|
@ -185,8 +185,11 @@ Post-processing
|
|||
:template: myclass.rst
|
||||
|
||||
openmc.Particle
|
||||
openmc.ParticleTrack
|
||||
openmc.StatePoint
|
||||
openmc.Summary
|
||||
openmc.Track
|
||||
openmc.Tracks
|
||||
|
||||
The following classes and functions are used for functional expansion reconstruction.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,39 +8,56 @@ This quick install guide outlines the basic steps needed to install OpenMC on
|
|||
your computer. For more detailed instructions on configuring and installing
|
||||
OpenMC, see :ref:`usersguide_install` in the User's Manual.
|
||||
|
||||
----------------------------------------
|
||||
Installing on Linux/Mac with conda-forge
|
||||
----------------------------------------
|
||||
--------------------------------------------------
|
||||
Installing on Linux/Mac with Mamba and conda-forge
|
||||
--------------------------------------------------
|
||||
|
||||
`Conda <https://conda.io/en/latest/>`_ is an open source package management
|
||||
system and environment management system for installing multiple versions of
|
||||
software packages and their dependencies and switching easily between them. If
|
||||
you have `conda` installed on your system, OpenMC can be installed via the
|
||||
`conda-forge` channel. First, add the `conda-forge` channel with:
|
||||
system and environments management system for installing multiple versions of
|
||||
software packages and their dependencies and switching easily between them.
|
||||
`Mamba <https://mamba.readthedocs.io/en/latest/>`_ is a cross-platform package
|
||||
manager and is compatible with `conda` packages.
|
||||
OpenMC can be installed in a `conda` environment with `mamba`.
|
||||
First, `conda` should be installed with one of the following installers:
|
||||
`Miniconda <https://docs.conda.io/en/latest/miniconda.html>`_,
|
||||
`Anaconda <https://www.anaconda.com/>`_, or `Miniforge <https://github.com/conda-forge/miniforge>`_.
|
||||
Once you have `conda` installed on your system, OpenMC can be installed via the
|
||||
`conda-forge` channel with `mamba`.
|
||||
|
||||
First, add the `conda-forge` channel with:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda config --add channels conda-forge
|
||||
|
||||
Then create and activate a new conda enviroment called `openmc-env` in
|
||||
which to install OpenMC.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda create -n openmc-env
|
||||
conda activate openmc-env
|
||||
|
||||
Then install `mamba`, which will be used to install OpenMC.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda install mamba
|
||||
|
||||
To list the versions of OpenMC that are available on the `conda-forge` channel,
|
||||
in your terminal window or an Anaconda Prompt run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda search openmc
|
||||
mamba search openmc
|
||||
|
||||
OpenMC can then be installed with:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda create -n openmc-env openmc
|
||||
mamba install openmc
|
||||
|
||||
This will install OpenMC in a conda environment called `openmc-env`. To activate
|
||||
the environment, run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda activate openmc-env
|
||||
You are now in a conda environment called `openmc-env` that has OpenMC installed.
|
||||
|
||||
-------------------------------------------
|
||||
Installing on Linux/Mac/Windows with Docker
|
||||
|
|
|
|||
|
|
@ -8,39 +8,56 @@ Installation and Configuration
|
|||
|
||||
.. _install_conda:
|
||||
|
||||
----------------------------------------
|
||||
Installing on Linux/Mac with conda-forge
|
||||
----------------------------------------
|
||||
--------------------------------------------------
|
||||
Installing on Linux/Mac with Mamba and conda-forge
|
||||
--------------------------------------------------
|
||||
|
||||
Conda_ is an open source package management system and environment management
|
||||
system for installing multiple versions of software packages and their
|
||||
dependencies and switching easily between them. If you have `conda` installed on
|
||||
your system, OpenMC can be installed via the `conda-forge` channel. First, add
|
||||
the `conda-forge` channel with:
|
||||
`Conda <https://conda.io/en/latest/>`_ is an open source package management
|
||||
systems and environments management system for installing multiple versions of
|
||||
software packages and their dependencies and switching easily between them.
|
||||
`Mamba <https://mamba.readthedocs.io/en/latest/>`_ is a cross-platform package
|
||||
manager and is compatible with `conda` packages.
|
||||
OpenMC can be installed in a `conda` environment with `mamba`.
|
||||
First, `conda` should be installed with one of the following installers:
|
||||
`Miniconda <https://docs.conda.io/en/latest/miniconda.html>`_,
|
||||
`Anaconda <https://www.anaconda.com/>`_, or `Miniforge <https://github.com/conda-forge/miniforge>`_.
|
||||
Once you have `conda` installed on your system, OpenMC can be installed via the
|
||||
`conda-forge` channel with `mamba`.
|
||||
|
||||
First, add the `conda-forge` channel with:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda config --add channels conda-forge
|
||||
|
||||
Then create and activate a new conda enviroment called `openmc-env` in
|
||||
which to install OpenMC.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda create -n openmc-env
|
||||
conda activate openmc-env
|
||||
|
||||
Then install `mamba`, which will be used to install OpenMC.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda install mamba
|
||||
|
||||
To list the versions of OpenMC that are available on the `conda-forge` channel,
|
||||
in your terminal window or an Anaconda Prompt run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda search openmc
|
||||
mamba search openmc
|
||||
|
||||
OpenMC can then be installed with:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda create -n openmc-env openmc
|
||||
mamba install openmc
|
||||
|
||||
This will install OpenMC in a conda environment called `openmc-env`. To activate
|
||||
the environment, run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
conda activate openmc-env
|
||||
You are now in a conda environment called `openmc-env` that has OpenMC installed.
|
||||
|
||||
-------------------------------------------
|
||||
Installing on Linux/Mac/Windows with Docker
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ flags:
|
|||
-r, --restart file Restart a previous run from a state point or a particle
|
||||
restart file
|
||||
-s, --threads N Run with *N* OpenMP threads
|
||||
-t, --track Write tracks for all particles
|
||||
-t, --track Write tracks for all particles (up to max_tracks)
|
||||
-v, --version Show version information
|
||||
-h, --help Show help message
|
||||
|
||||
|
|
@ -112,6 +112,19 @@ otherwise.
|
|||
tallies. The path to the statepoint file can be provided as an optional arugment
|
||||
(if omitted, a file dialog will be presented).
|
||||
|
||||
.. _scripts_track_combine:
|
||||
|
||||
------------------------
|
||||
``openmc-track-combine``
|
||||
------------------------
|
||||
|
||||
This script combines multiple HDF5 :ref:`particle track files
|
||||
<usersguide_track>` into a single HDF5 particle track file. The filenames of the
|
||||
particle track files should be given as posititional arguments. The output
|
||||
filename can also be changed with the ``-o`` flag:
|
||||
|
||||
-o OUT, --out OUT Output HDF5 particle track file
|
||||
|
||||
.. _scripts_track:
|
||||
|
||||
-----------------------
|
||||
|
|
|
|||
|
|
@ -514,4 +514,108 @@ As an example, to write a statepoint file every five batches::
|
|||
settings.batches = n
|
||||
settings.statepoint = {'batches': range(5, n + 5, 5)}
|
||||
|
||||
.. _NIST ESTAR database: https://physics.nist.gov/PhysRefData/Star/Text/ESTAR.html
|
||||
Particle Track Files
|
||||
--------------------
|
||||
|
||||
OpenMC can generate a particle track file that contains track information
|
||||
(position, direction, energy, time, weight, cell ID, and material ID) for each
|
||||
state along a particle's history. There are two ways to indicate which particles
|
||||
and/or how many particles should have their tracks written. First, you can
|
||||
identify specific source particles by their batch, generation, and particle ID
|
||||
numbers::
|
||||
|
||||
settings.tracks = [
|
||||
(1, 1, 50),
|
||||
(2, 1, 30),
|
||||
(5, 1, 75)
|
||||
]
|
||||
|
||||
In this example, track information would be written for the 50th particle in the
|
||||
1st generation of batch 1, the 30th particle in the first generation of batch 2,
|
||||
and the 75th particle in the 1st generation of batch 5. Unless you are using
|
||||
more than one generation per batch (see :ref:`usersguide_particles`), the
|
||||
generation number should be 1. Alternatively, you can run OpenMC in a mode where
|
||||
track information is written for *all* particles, up to a user-specified limit::
|
||||
|
||||
openmc.run(tracks=True)
|
||||
|
||||
In this case, you can control the maximum number of source particles for which
|
||||
tracks will be written as follows::
|
||||
|
||||
settings.max_tracks = 1000
|
||||
|
||||
Particle track information is written to the ``tracks.h5`` file, which can be
|
||||
analyzed using the :class:`~openmc.Tracks` class::
|
||||
|
||||
>>> tracks = openmc.Tracks('tracks.h5')
|
||||
>>> tracks
|
||||
[<Track (1, 1, 50): 151 particles>,
|
||||
<Track (2, 1, 30): 191 particles>,
|
||||
<Track (5, 1, 75): 81 particles>]
|
||||
|
||||
Each :class:`~openmc.Track` object stores a list of track information for every
|
||||
primary/secondary particle. In the above example, the first source particle
|
||||
produced 150 secondary particles for a total of 151 particles. Information for
|
||||
each primary/secondary particle can be accessed using the
|
||||
:attr:`~openmc.Track.particle_tracks` attribute::
|
||||
|
||||
>>> first_track = tracks[0]
|
||||
>>> first_track.particle_tracks
|
||||
[<ParticleTrack: neutron, 120 states>,
|
||||
<ParticleTrack: photon, 6 states>,
|
||||
<ParticleTrack: electron, 2 states>,
|
||||
<ParticleTrack: electron, 2 states>,
|
||||
<ParticleTrack: electron, 2 states>,
|
||||
...
|
||||
<ParticleTrack: electron, 2 states>,
|
||||
<ParticleTrack: electron, 2 states>]
|
||||
>>> photon = first_track.particle_tracks[1]
|
||||
|
||||
The :class:`~openmc.ParticleTrack` class is a named tuple indicating the
|
||||
particle type and then a NumPy array of the "states". The states array is a
|
||||
compound type with a field for each physical quantity (position, direction,
|
||||
energy, time, weight, cell ID, and material ID). For example, to get the
|
||||
position for the above particle track::
|
||||
|
||||
>>> photon.states['r']
|
||||
array([(-11.92987939, -12.28467295, 0.67837495),
|
||||
(-11.95213726, -12.2682 , 0.68783964),
|
||||
(-12.2682 , -12.03428339, 0.82223855),
|
||||
(-12.5913778 , -11.79510096, 0.95966298),
|
||||
(-12.6622572 , -11.74264344, 0.98980293),
|
||||
(-12.6907775 , -11.7215357 , 1.00193058)],
|
||||
dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')])
|
||||
|
||||
The full list of fields is as follows:
|
||||
|
||||
:r: Position (each direction in [cm])
|
||||
:u: Direction
|
||||
:E: Energy in [eV]
|
||||
:time: Time in [s]
|
||||
:wgt: Weight
|
||||
:cell_id: Cell ID
|
||||
:cell_instance: Cell instance
|
||||
:material_id: Material ID
|
||||
|
||||
Both the :class:`~openmc.Tracks` and :class:`~openmc.Track` classes have a
|
||||
``filter`` method that allows you to get a subset of tracks that meet a given
|
||||
criteria. For example, to get all tracks that involved a photon::
|
||||
|
||||
>>> tracks.filter(particle='photon')
|
||||
[<Track (1, 1, 50): 151 particles>,
|
||||
<Track (2, 1, 30): 191 particles>,
|
||||
<Track (5, 1, 75): 81 particles>]
|
||||
|
||||
The :meth:`openmc.Tracks.filter` method returns a new :class:`~openmc.Tracks`
|
||||
instance, whereas the :meth:`openmc.Track.filter` method returns a new
|
||||
:class:`~openmc.Track` instance.
|
||||
|
||||
.. note:: If you are using an MPI-enabled install of OpenMC and run a simulation
|
||||
with more than one process, a separate track file will be written for
|
||||
each MPI process with the filename ``tracks_p#.h5`` where # is the
|
||||
rank of the corresponding process. Multiple track files can be
|
||||
combined with the :ref:`scripts_track_combine` script:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
openmc-track-combine tracks_p*.h5 --out tracks.h5
|
||||
|
|
|
|||
|
|
@ -300,5 +300,8 @@ struct CellInstanceHash {
|
|||
|
||||
void read_cells(pugi::xml_node node);
|
||||
|
||||
//! Add cells to universes
|
||||
void populate_universes();
|
||||
|
||||
} // namespace openmc
|
||||
#endif // OPENMC_CELL_H
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ constexpr int HDF5_VERSION[] {3, 0};
|
|||
// Version numbers for binary files
|
||||
constexpr array<int, 2> VERSION_STATEPOINT {17, 0};
|
||||
constexpr array<int, 2> VERSION_PARTICLE_RESTART {2, 0};
|
||||
constexpr array<int, 2> VERSION_TRACK {2, 0};
|
||||
constexpr array<int, 2> VERSION_TRACK {3, 0};
|
||||
constexpr array<int, 2> VERSION_SUMMARY {6, 0};
|
||||
constexpr array<int, 2> VERSION_VOLUME {1, 0};
|
||||
constexpr array<int, 2> VERSION_VOXEL {2, 0};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ void check_dagmc_root_univ();
|
|||
#ifdef DAGMC
|
||||
|
||||
#include "DagMC.hpp"
|
||||
#include "dagmcmetadata.hpp"
|
||||
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/particle.h"
|
||||
|
|
@ -87,6 +88,11 @@ public:
|
|||
explicit DAGUniverse(const std::string& filename, bool auto_geom_ids = false,
|
||||
bool auto_mat_ids = false);
|
||||
|
||||
//! Alternative DAGMC universe constructor for external DAGMC instance
|
||||
explicit DAGUniverse(std::shared_ptr<moab::DagMC> external_dagmc_ptr,
|
||||
const std::string& filename = "", bool auto_geom_ids = false,
|
||||
bool auto_mat_ids = false);
|
||||
|
||||
//! Initialize the DAGMC accel. data structures, indices, material
|
||||
//! assignments, etc.
|
||||
void initialize();
|
||||
|
|
@ -139,10 +145,16 @@ public:
|
|||
bool has_graveyard() const { return has_graveyard_; }
|
||||
|
||||
private:
|
||||
void set_id(); //!< Deduce the universe id from model::universes
|
||||
void init_dagmc(); //!< Create and initialise DAGMC pointer
|
||||
void init_metadata(); //!< Create and initialise dagmcMetaData pointer
|
||||
void init_geometry(); //!< Create cells and surfaces from DAGMC entities
|
||||
|
||||
std::string
|
||||
filename_; //!< Name of the DAGMC file used to create this universe
|
||||
std::shared_ptr<UWUW>
|
||||
uwuw_; //!< Pointer to the UWUW instance for this universe
|
||||
uwuw_; //!< Pointer to the UWUW instance for this universe
|
||||
std::unique_ptr<dagmcMetaData> dmd_ptr; //! Pointer to DAGMC metadata object
|
||||
bool adjust_geometry_ids_; //!< Indicates whether or not to automatically
|
||||
//!< generate new cell and surface IDs for the
|
||||
//!< universe
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ private:
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Distribution of points specified by spherical coordinates r,theta,phi
|
||||
//! Distribution of points specified by spherical coordinates r,cos_theta,phi
|
||||
//==============================================================================
|
||||
|
||||
class SphericalIndependent : public SpatialDistribution {
|
||||
|
|
@ -83,15 +83,15 @@ public:
|
|||
Position sample(uint64_t* seed) const;
|
||||
|
||||
Distribution* r() const { return r_.get(); }
|
||||
Distribution* theta() const { return theta_.get(); }
|
||||
Distribution* cos_theta() const { return cos_theta_.get(); }
|
||||
Distribution* phi() const { return phi_.get(); }
|
||||
Position origin() const { return origin_; }
|
||||
|
||||
private:
|
||||
UPtrDist r_; //!< Distribution of r coordinates
|
||||
UPtrDist theta_; //!< Distribution of theta coordinates
|
||||
UPtrDist phi_; //!< Distribution of phi coordinates
|
||||
Position origin_; //!< Cartesian coordinates of the sphere center
|
||||
UPtrDist r_; //!< Distribution of r coordinates
|
||||
UPtrDist cos_theta_; //!< Distribution of cos_theta coordinates
|
||||
UPtrDist phi_; //!< Distribution of phi coordinates
|
||||
Position origin_; //!< Cartesian coordinates of the sphere center
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -113,6 +113,9 @@ public:
|
|||
//! \param[in] units Units of density
|
||||
void set_density(double density, gsl::cstring_span units);
|
||||
|
||||
//! Set temperature of the material
|
||||
void set_temperature(double temperature) { temperature_ = temperature; };
|
||||
|
||||
//! Get nuclides in material
|
||||
//! \return Indices into the global nuclides vector
|
||||
gsl::span<const int> nuclides() const
|
||||
|
|
|
|||
|
|
@ -56,6 +56,24 @@ struct SourceSite {
|
|||
int64_t progeny_id;
|
||||
};
|
||||
|
||||
//! State of a particle used for particle track files
|
||||
struct TrackState {
|
||||
Position r; //!< Position in [cm]
|
||||
Direction u; //!< Direction
|
||||
double E; //!< Energy in [eV]
|
||||
double time {0.0}; //!< Time in [s]
|
||||
double wgt {1.0}; //!< Weight
|
||||
int cell_id; //!< Cell ID
|
||||
int cell_instance; //!< Cell instance
|
||||
int material_id {-1}; //!< Material ID (default value indicates void)
|
||||
};
|
||||
|
||||
//! Full history of a single particle's track states
|
||||
struct TrackStateHistory {
|
||||
ParticleType particle;
|
||||
std::vector<TrackState> states;
|
||||
};
|
||||
|
||||
//! Saved ("banked") state of a particle, for nu-fission tallying
|
||||
struct NuBank {
|
||||
double E; //!< particle energy
|
||||
|
|
@ -290,7 +308,7 @@ private:
|
|||
|
||||
vector<FilterMatch> filter_matches_; // tally filter matches
|
||||
|
||||
vector<vector<Position>> tracks_; // tracks for outputting to file
|
||||
vector<TrackStateHistory> tracks_; // tracks for outputting to file
|
||||
|
||||
vector<NuBank> nu_bank_; // bank of most recently fissioned particles
|
||||
|
||||
|
|
@ -342,6 +360,9 @@ public:
|
|||
const LocalCoord& coord(int i) const { return coord_[i]; }
|
||||
const vector<LocalCoord>& coord() const { return coord_; }
|
||||
|
||||
LocalCoord& lowest_coord() { return coord_[n_coord_ - 1]; }
|
||||
const LocalCoord& lowest_coord() const { return coord_[n_coord_ - 1]; }
|
||||
|
||||
int& n_coord_last() { return n_coord_last_; }
|
||||
const int& n_coord_last() const { return n_coord_last_; }
|
||||
int& cell_last(int i) { return cell_last_[i]; }
|
||||
|
|
@ -357,6 +378,7 @@ public:
|
|||
const int& g_last() const { return g_last_; }
|
||||
|
||||
double& wgt() { return wgt_; }
|
||||
double wgt() const { return wgt_; }
|
||||
double& mu() { return mu_; }
|
||||
const double& mu() const { return mu_; }
|
||||
double& time() { return time_; }
|
||||
|
|
@ -479,6 +501,9 @@ public:
|
|||
n_coord_ = 1;
|
||||
}
|
||||
|
||||
//! Get track information based on particle's current state
|
||||
TrackState get_track_state() const;
|
||||
|
||||
void zero_delayed_bank()
|
||||
{
|
||||
for (int& n : n_delayed_bank_) {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ extern int max_order; //!< Maximum Legendre order for multigroup data
|
|||
extern int n_log_bins; //!< number of bins for logarithmic energy grid
|
||||
extern int n_batches; //!< number of (inactive+active) batches
|
||||
extern int n_max_batches; //!< Maximum number of batches
|
||||
extern int max_tracks; //!< Maximum number of particle tracks written to file
|
||||
extern ResScatMethod res_scat_method; //!< resonance upscattering method
|
||||
extern double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering
|
||||
extern double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering
|
||||
|
|
|
|||
|
|
@ -9,8 +9,31 @@ namespace openmc {
|
|||
// Non-member functions
|
||||
//==============================================================================
|
||||
|
||||
//! Open HDF5 track file for writing and create track datatype
|
||||
void open_track_file();
|
||||
|
||||
//! Close HDF5 resources for track file
|
||||
void close_track_file();
|
||||
|
||||
//! Determine whether a given particle should collect/write track information
|
||||
//
|
||||
//! \param[in] p Current particle
|
||||
//! \return Whether to collect/write track information
|
||||
bool check_track_criteria(const Particle& p);
|
||||
|
||||
//! Create a new track state history for a primary/secondary particle
|
||||
//
|
||||
//! \param[in] p Current particle
|
||||
void add_particle_track(Particle& p);
|
||||
|
||||
//! Store particle's current state
|
||||
//
|
||||
//! \param[in] p Current particle
|
||||
void write_particle_track(Particle& p);
|
||||
|
||||
//! Write full particle state history to HDF5 track file
|
||||
//
|
||||
//! \param[in] p Current particle
|
||||
void finalize_particle_track(Particle& p);
|
||||
|
||||
} // namespace openmc
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Restart a previous run from a state point or a particle restart file named
|
|||
Use \fIN\fP OpenMP threads.
|
||||
.TP
|
||||
.B "\-t\fR, \fP\-\-track"
|
||||
Write tracks for all particles.
|
||||
Write tracks for all particles (up to max_tracks).
|
||||
.TP
|
||||
.B "\-v\fR, \fP\-\-version"
|
||||
Show version information.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ from openmc.mixin import *
|
|||
from openmc.plotter import *
|
||||
from openmc.search import *
|
||||
from openmc.polynomial import *
|
||||
from openmc.tracks import *
|
||||
from . import examples
|
||||
|
||||
# Import a few names from the model module
|
||||
|
|
|
|||
|
|
@ -690,7 +690,10 @@ class Cell(IDManagerMixin):
|
|||
for key in ('temperature', 'rotation', 'translation'):
|
||||
value = get_text(elem, key)
|
||||
if value is not None:
|
||||
setattr(c, key, [float(x) for x in value.split()])
|
||||
values = [float(x) for x in value.split()]
|
||||
if key == 'rotation' and len(values) == 9:
|
||||
values = np.array(values).reshape(3, 3)
|
||||
setattr(c, key, values)
|
||||
|
||||
# Add this cell to appropriate universe
|
||||
univ_id = int(get_text(elem, 'universe', 0))
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ class Material(IDManagerMixin):
|
|||
|
||||
To create a material, one should create an instance of this class, add
|
||||
nuclides or elements with :meth:`Material.add_nuclide` or
|
||||
`Material.add_element`, respectively, and set the total material density
|
||||
with `Material.set_density()`. The material can then be assigned to a cell
|
||||
using the :attr:`Cell.fill` attribute.
|
||||
:meth:`Material.add_element`, respectively, and set the total material
|
||||
density with :meth:`Material.set_density()`. The material can then be
|
||||
assigned to a cell using the :attr:`Cell.fill` attribute.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
|
|||
135
openmc/mesh.py
135
openmc/mesh.py
|
|
@ -1,4 +1,4 @@
|
|||
from abc import ABC
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Iterable
|
||||
from math import pi
|
||||
from numbers import Real, Integral
|
||||
|
|
@ -60,7 +60,7 @@ class MeshBase(IDManagerMixin, ABC):
|
|||
return string
|
||||
|
||||
def _volume_dim_check(self):
|
||||
if len(self.dimension) != 3 or \
|
||||
if self.n_dimension != 3 or \
|
||||
any([d == 0 for d in self.dimension]):
|
||||
raise RuntimeError(f'Mesh {self.id} is not 3D. '
|
||||
'Volumes cannot be provided.')
|
||||
|
|
@ -126,7 +126,75 @@ class MeshBase(IDManagerMixin, ABC):
|
|||
raise ValueError(f'Unrecognized mesh type "{mesh_type}" found.')
|
||||
|
||||
|
||||
class RegularMesh(MeshBase):
|
||||
class StructuredMesh(MeshBase):
|
||||
"""A base class for structured mesh functionality
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_id : int
|
||||
Unique identifier for the mesh
|
||||
name : str
|
||||
Name of the mesh
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id : int
|
||||
Unique identifier for the mesh
|
||||
name : str
|
||||
Name of the mesh
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def dimension(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def n_dimension(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def _grids(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def vertices(self):
|
||||
"""Return coordinates of mesh vertices.
|
||||
|
||||
Returns
|
||||
-------
|
||||
vertices : numpy.ndarray
|
||||
Returns a numpy.ndarray representing the coordinates of the mesh
|
||||
vertices with a shape equal to (dim1 + 1, ..., dimn + 1, ndim).
|
||||
|
||||
"""
|
||||
return np.stack(np.meshgrid(*self._grids, indexing='ij'), axis=-1)
|
||||
|
||||
@property
|
||||
def centroids(self):
|
||||
"""Return coordinates of mesh element centroids.
|
||||
|
||||
Returns
|
||||
-------
|
||||
centroids : numpy.ndarray
|
||||
Returns a numpy.ndarray representing the mesh element centroid
|
||||
coordinates with a shape equal to (dim1, ..., dimn, ndim).
|
||||
|
||||
"""
|
||||
ndim = self.n_dimension
|
||||
vertices = self.vertices
|
||||
s0 = (slice(0, -1),)*ndim + (slice(None),)
|
||||
s1 = (slice(1, None),)*ndim + (slice(None),)
|
||||
return (vertices[s0] + vertices[s1]) / 2
|
||||
|
||||
|
||||
class RegularMesh(StructuredMesh):
|
||||
"""A regular Cartesian mesh in one, two, or three dimensions
|
||||
|
||||
Parameters
|
||||
|
|
@ -244,6 +312,30 @@ class RegularMesh(MeshBase):
|
|||
nx, = self.dimension
|
||||
return ((x,) for x in range(1, nx + 1))
|
||||
|
||||
@property
|
||||
def _grids(self):
|
||||
ndim = len(self._dimension)
|
||||
if ndim == 3:
|
||||
x0, y0, z0 = self.lower_left
|
||||
x1, y1, z1 = self.upper_right
|
||||
nx, ny, nz = self.dimension
|
||||
xarr = np.linspace(x0, x1, nx + 1)
|
||||
yarr = np.linspace(y0, y1, ny + 1)
|
||||
zarr = np.linspace(z0, z1, nz + 1)
|
||||
return (xarr, yarr, zarr)
|
||||
elif ndim == 2:
|
||||
x0, y0 = self.lower_left
|
||||
x1, y1 = self.upper_right
|
||||
nx, ny = self.dimension
|
||||
xarr = np.linspace(x0, x1, nx + 1)
|
||||
yarr = np.linspace(y0, y1, ny + 1)
|
||||
return (xarr, yarr)
|
||||
else:
|
||||
nx, = self.dimension
|
||||
x0, = self.lower_left
|
||||
x1, = self.upper_right
|
||||
return (np.linspace(x0, x1, nx + 1),)
|
||||
|
||||
@dimension.setter
|
||||
def dimension(self, dimension):
|
||||
cv.check_type('mesh dimension', dimension, Iterable, Integral)
|
||||
|
|
@ -440,7 +532,7 @@ class RegularMesh(MeshBase):
|
|||
for entry in bc:
|
||||
cv.check_value('bc', entry, _BOUNDARY_TYPES)
|
||||
|
||||
n_dim = len(self.dimension)
|
||||
n_dim = self.n_dimension
|
||||
|
||||
# Build the cell which will contain the lattice
|
||||
xplanes = [openmc.XPlane(self.lower_left[0], boundary_type=bc[0]),
|
||||
|
|
@ -537,7 +629,7 @@ def Mesh(*args, **kwargs):
|
|||
return RegularMesh(*args, **kwargs)
|
||||
|
||||
|
||||
class RectilinearMesh(MeshBase):
|
||||
class RectilinearMesh(StructuredMesh):
|
||||
"""A 3D rectilinear Cartesian mesh
|
||||
|
||||
Parameters
|
||||
|
|
@ -598,6 +690,10 @@ class RectilinearMesh(MeshBase):
|
|||
def z_grid(self):
|
||||
return self._z_grid
|
||||
|
||||
@property
|
||||
def _grids(self):
|
||||
return (self.x_grid, self.y_grid, self.z_grid)
|
||||
|
||||
@property
|
||||
def volumes(self):
|
||||
"""Return Volumes for every mesh cell
|
||||
|
|
@ -726,7 +822,7 @@ class RectilinearMesh(MeshBase):
|
|||
return element
|
||||
|
||||
|
||||
class CylindricalMesh(MeshBase):
|
||||
class CylindricalMesh(StructuredMesh):
|
||||
"""A 3D cylindrical mesh
|
||||
|
||||
Parameters
|
||||
|
|
@ -789,6 +885,10 @@ class CylindricalMesh(MeshBase):
|
|||
def z_grid(self):
|
||||
return self._z_grid
|
||||
|
||||
@property
|
||||
def _grids(self):
|
||||
return (self.r_grid, self.phi_grid, self.z_grid)
|
||||
|
||||
@property
|
||||
def indices(self):
|
||||
nr, np, nz = self.dimension
|
||||
|
|
@ -913,7 +1013,7 @@ class CylindricalMesh(MeshBase):
|
|||
return np.multiply.outer(np.outer(V_r, V_p), V_z)
|
||||
|
||||
|
||||
class SphericalMesh(MeshBase):
|
||||
class SphericalMesh(StructuredMesh):
|
||||
"""A 3D spherical mesh
|
||||
|
||||
Parameters
|
||||
|
|
@ -977,6 +1077,10 @@ class SphericalMesh(MeshBase):
|
|||
def phi_grid(self):
|
||||
return self._phi_grid
|
||||
|
||||
@property
|
||||
def _grids(self):
|
||||
return (self.r_grid, self.theta_grid, self.phi_grid)
|
||||
|
||||
@property
|
||||
def indices(self):
|
||||
nr, nt, np = self.dimension
|
||||
|
|
@ -1146,7 +1250,7 @@ class UnstructuredMesh(MeshBase):
|
|||
(1.0, 1.0, 1.0), ...]
|
||||
"""
|
||||
def __init__(self, filename, library, mesh_id=None, name='',
|
||||
length_multiplier=1.0):
|
||||
length_multiplier=1.0):
|
||||
super().__init__(mesh_id, name)
|
||||
self.filename = filename
|
||||
self._volumes = None
|
||||
|
|
@ -1241,6 +1345,19 @@ class UnstructuredMesh(MeshBase):
|
|||
Real)
|
||||
self._length_multiplier = length_multiplier
|
||||
|
||||
@property
|
||||
def dimension(self):
|
||||
return self.n_elements
|
||||
|
||||
@property
|
||||
def n_dimension(self):
|
||||
return 3
|
||||
|
||||
@property
|
||||
def vertices(self):
|
||||
raise NotImplementedError("Vertices for UnstructuredMesh objects are "
|
||||
"not yet available")
|
||||
|
||||
def __repr__(self):
|
||||
string = super().__repr__()
|
||||
string += '{: <16}=\t{}\n'.format('\tFilename', self.filename)
|
||||
|
|
@ -1371,7 +1488,7 @@ class UnstructuredMesh(MeshBase):
|
|||
subelement.text = self.filename
|
||||
|
||||
if self._length_multiplier != 1.0:
|
||||
element.set("length_multiplier", str(self.length_multiplier))
|
||||
element.set("length_multiplier", str(self.length_multiplier))
|
||||
|
||||
return element
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ class CylinderSector(CompositeSurface):
|
|||
|
||||
|
||||
class IsogonalOctagon(CompositeSurface):
|
||||
"""Infinite isogonal octagon composite surface
|
||||
r"""Infinite isogonal octagon composite surface
|
||||
|
||||
An isogonal octagon is composed of eight planar surfaces. The prism is
|
||||
parallel to the x, y, or z axis. The remaining two axes (y and z, z and x,
|
||||
|
|
|
|||
|
|
@ -213,8 +213,8 @@ class Plot(IDManagerMixin):
|
|||
The basis directions for the plot
|
||||
background : Iterable of int or str
|
||||
Color of the background
|
||||
mask_components : Iterable of openmc.Cell or openmc.Material
|
||||
The cells or materials to plot
|
||||
mask_components : Iterable of openmc.Cell or openmc.Material or int
|
||||
The cells or materials (or corresponding IDs) to mask
|
||||
mask_background : Iterable of int or str
|
||||
Color to apply to all cells/materials not listed in mask_components
|
||||
show_overlaps : bool
|
||||
|
|
@ -222,8 +222,10 @@ class Plot(IDManagerMixin):
|
|||
overlap_color : Iterable of int or str
|
||||
Color to apply to overlapping regions
|
||||
colors : dict
|
||||
Dictionary indicating that certain cells/materials (keys) should be
|
||||
displayed with a particular color.
|
||||
Dictionary indicating that certain cells/materials should be
|
||||
displayed with a particular color. The keys can be of type
|
||||
:class:`~openmc.Cell`, :class:`~openmc.Material`, or int (ID for a
|
||||
cell/material).
|
||||
level : int
|
||||
Universe depth to plot at
|
||||
meshlines : dict
|
||||
|
|
@ -373,14 +375,15 @@ class Plot(IDManagerMixin):
|
|||
def colors(self, colors):
|
||||
cv.check_type('plot colors', colors, Mapping)
|
||||
for key, value in colors.items():
|
||||
cv.check_type('plot color key', key, (openmc.Cell, openmc.Material))
|
||||
cv.check_type('plot color key', key,
|
||||
(openmc.Cell, openmc.Material, Integral))
|
||||
self._check_color('plot color value', value)
|
||||
self._colors = colors
|
||||
|
||||
@mask_components.setter
|
||||
def mask_components(self, mask_components):
|
||||
cv.check_type('plot mask components', mask_components, Iterable,
|
||||
(openmc.Cell, openmc.Material))
|
||||
(openmc.Cell, openmc.Material, Integral))
|
||||
self._mask_components = mask_components
|
||||
|
||||
@mask_background.setter
|
||||
|
|
@ -634,11 +637,16 @@ class Plot(IDManagerMixin):
|
|||
color = _SVG_COLORS[color.lower()]
|
||||
subelement.text = ' '.join(str(x) for x in color)
|
||||
|
||||
# Helper function that returns the domain ID given either a
|
||||
# Cell/Material object or the domain ID itself
|
||||
def get_id(domain):
|
||||
return domain if isinstance(domain, Integral) else domain.id
|
||||
|
||||
if self._colors:
|
||||
for domain, color in sorted(self._colors.items(),
|
||||
key=lambda x: x[0].id):
|
||||
key=lambda x: get_id(x[0])):
|
||||
subelement = ET.SubElement(element, "color")
|
||||
subelement.set("id", str(domain.id))
|
||||
subelement.set("id", str(get_id(domain)))
|
||||
if isinstance(color, str):
|
||||
color = _SVG_COLORS[color.lower()]
|
||||
subelement.set("rgb", ' '.join(str(x) for x in color))
|
||||
|
|
@ -646,7 +654,7 @@ class Plot(IDManagerMixin):
|
|||
if self._mask_components is not None:
|
||||
subelement = ET.SubElement(element, "mask")
|
||||
subelement.set("components", ' '.join(
|
||||
str(d.id) for d in self._mask_components))
|
||||
str(get_id(d)) for d in self._mask_components))
|
||||
color = self._mask_background
|
||||
if color is not None:
|
||||
if isinstance(color, str):
|
||||
|
|
@ -720,15 +728,14 @@ class Plot(IDManagerMixin):
|
|||
# Set plot colors
|
||||
colors = {}
|
||||
for color_elem in elem.findall("color"):
|
||||
uid = color_elem.get("id")
|
||||
uid = int(color_elem.get("id"))
|
||||
colors[uid] = tuple([int(x) for x in color_elem.get("rgb").split()])
|
||||
# TODO: set colors (needs geometry information)
|
||||
plot.colors = colors
|
||||
|
||||
# Set masking information
|
||||
mask_elem = elem.find("mask")
|
||||
if mask_elem is not None:
|
||||
mask_components = [int(x) for x in mask_elem.get("components").split()]
|
||||
# TODO: set mask components (needs geometry information)
|
||||
plot.mask_components = [int(x) for x in mask_elem.get("components").split()]
|
||||
background = mask_elem.get("background")
|
||||
if background is not None:
|
||||
plot.mask_background = tuple([int(x) for x in background.split()])
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import os
|
|||
import typing # imported separately as py3.8 requires typing.Iterable
|
||||
from collections.abc import Iterable, Mapping, MutableSequence
|
||||
from enum import Enum
|
||||
import itertools
|
||||
from math import ceil
|
||||
from numbers import Integral, Real
|
||||
from pathlib import Path
|
||||
|
|
@ -104,6 +105,10 @@ class Settings:
|
|||
Maximum number of times a particle can split during a history
|
||||
|
||||
.. versionadded:: 0.13
|
||||
max_tracks : int
|
||||
Maximum number of tracks written to a track file (per MPI process).
|
||||
|
||||
.. versionadded:: 0.13.1
|
||||
no_reduce : bool
|
||||
Indicate that all user-defined and global tallies should not be reduced
|
||||
across processes in a parallel calculation.
|
||||
|
|
@ -187,7 +192,7 @@ class Settings:
|
|||
integers: the batch number, generation number, and particle number
|
||||
track : tuple or list
|
||||
Specify particles for which track files should be written. Each particle
|
||||
is identified by a triplet with the batch number, generation number, and
|
||||
is identified by a tuple with the batch number, generation number, and
|
||||
particle number.
|
||||
trigger_active : bool
|
||||
Indicate whether tally triggers are used
|
||||
|
|
@ -290,6 +295,7 @@ class Settings:
|
|||
self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows')
|
||||
self._weight_windows_on = None
|
||||
self._max_splits = None
|
||||
self._max_tracks = None
|
||||
|
||||
@property
|
||||
def run_mode(self):
|
||||
|
|
@ -475,6 +481,10 @@ class Settings:
|
|||
def max_splits(self):
|
||||
return self._max_splits
|
||||
|
||||
@property
|
||||
def max_tracks(self):
|
||||
return self._max_tracks
|
||||
|
||||
@run_mode.setter
|
||||
def run_mode(self, run_mode: str):
|
||||
cv.check_value('run mode', run_mode, {x.value for x in RunMode})
|
||||
|
|
@ -776,16 +786,18 @@ class Settings:
|
|||
self._trace = trace
|
||||
|
||||
@track.setter
|
||||
def track(self, track: typing.Iterable[int]):
|
||||
cv.check_type('track', track, Iterable, Integral)
|
||||
if len(track) % 3 != 0:
|
||||
msg = f'Unable to set the track to "{track}" since its length is ' \
|
||||
'not a multiple of 3'
|
||||
raise ValueError(msg)
|
||||
for t in zip(track[::3], track[1::3], track[2::3]):
|
||||
def track(self, track: typing.Iterable[typing.Iterable[int]]):
|
||||
cv.check_type('track', track, Iterable)
|
||||
for t in track:
|
||||
if len(t) != 3:
|
||||
msg = f'Unable to set the track to "{t}" since its length is not 3'
|
||||
raise ValueError(msg)
|
||||
cv.check_greater_than('track batch', t[0], 0)
|
||||
cv.check_greater_than('track generation', t[0], 0)
|
||||
cv.check_greater_than('track particle', t[0], 0)
|
||||
cv.check_greater_than('track generation', t[1], 0)
|
||||
cv.check_greater_than('track particle', t[2], 0)
|
||||
cv.check_type('track batch', t[0], Integral)
|
||||
cv.check_type('track generation', t[1], Integral)
|
||||
cv.check_type('track particle', t[2], Integral)
|
||||
self._track = track
|
||||
|
||||
@ufs_mesh.setter
|
||||
|
|
@ -881,9 +893,15 @@ class Settings:
|
|||
@max_splits.setter
|
||||
def max_splits(self, value: int):
|
||||
cv.check_type('maximum particle splits', value, Integral)
|
||||
cv.check_greater_than('max particles in flight', value, 0)
|
||||
cv.check_greater_than('max particle splits', value, 0)
|
||||
self._max_splits = value
|
||||
|
||||
@max_tracks.setter
|
||||
def max_tracks(self, value: int):
|
||||
cv.check_type('maximum particle tracks', value, Integral)
|
||||
cv.check_greater_than('maximum particle tracks', value, 0, True)
|
||||
self._max_tracks = value
|
||||
|
||||
def _create_run_mode_subelement(self, root):
|
||||
elem = ET.SubElement(root, "run_mode")
|
||||
elem.text = self._run_mode.value
|
||||
|
|
@ -1110,7 +1128,7 @@ class Settings:
|
|||
def _create_track_subelement(self, root):
|
||||
if self._track is not None:
|
||||
element = ET.SubElement(root, "track")
|
||||
element.text = ' '.join(map(str, self._track))
|
||||
element.text = ' '.join(map(str, itertools.chain(*self._track)))
|
||||
|
||||
def _create_ufs_mesh_subelement(self, root):
|
||||
if self.ufs_mesh is not None:
|
||||
|
|
@ -1196,6 +1214,11 @@ class Settings:
|
|||
elem = ET.SubElement(root, "max_splits")
|
||||
elem.text = str(self._max_splits)
|
||||
|
||||
def _create_max_tracks_subelement(self, root):
|
||||
if self._max_tracks is not None:
|
||||
elem = ET.SubElement(root, "max_tracks")
|
||||
elem.text = str(self._max_tracks)
|
||||
|
||||
def _eigenvalue_from_xml_element(self, root):
|
||||
elem = root.find('eigenvalue')
|
||||
if elem is not None:
|
||||
|
|
@ -1424,7 +1447,8 @@ class Settings:
|
|||
def _track_from_xml_element(self, root):
|
||||
text = get_text(root, 'track')
|
||||
if text is not None:
|
||||
self.track = [int(x) for x in text.split()]
|
||||
values = [int(x) for x in text.split()]
|
||||
self.track = list(zip(values[::3], values[1::3], values[2::3]))
|
||||
|
||||
def _ufs_mesh_from_xml_element(self, root):
|
||||
text = get_text(root, 'ufs_mesh')
|
||||
|
|
@ -1498,6 +1522,11 @@ class Settings:
|
|||
if text is not None:
|
||||
self.max_splits = int(text)
|
||||
|
||||
def _max_tracks_from_xml_element(self, root):
|
||||
text = get_text(root, 'max_tracks')
|
||||
if text is not None:
|
||||
self.max_tracks = int(text)
|
||||
|
||||
def export_to_xml(self, path: Union[str, os.PathLike] = 'settings.xml'):
|
||||
"""Export simulation settings to an XML file.
|
||||
|
||||
|
|
@ -1554,6 +1583,7 @@ class Settings:
|
|||
self._create_write_initial_source_subelement(root_element)
|
||||
self._create_weight_windows_subelement(root_element)
|
||||
self._create_max_splits_subelement(root_element)
|
||||
self._create_max_tracks_subelement(root_element)
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
clean_indentation(root_element)
|
||||
|
|
@ -1633,6 +1663,7 @@ class Settings:
|
|||
settings._write_initial_source_from_xml_element(root)
|
||||
settings._weight_windows_from_xml_element(root)
|
||||
settings._max_splits_from_xml_element(root)
|
||||
settings._max_tracks_from_xml_element(root)
|
||||
|
||||
# TODO: Get volume calculations
|
||||
|
||||
|
|
|
|||
|
|
@ -298,6 +298,10 @@ class SourceParticle:
|
|||
self.surf_id = surf_id
|
||||
self.particle = particle
|
||||
|
||||
def __repr__(self):
|
||||
name = self.particle.name.lower()
|
||||
return f'<SourceParticle: {name} at E={self.E:.6e} eV>'
|
||||
|
||||
def to_tuple(self):
|
||||
"""Return source particle attributes as a tuple
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Iterable
|
||||
from math import pi
|
||||
from math import pi, cos
|
||||
from numbers import Real
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ import numpy as np
|
|||
|
||||
import openmc.checkvalue as cv
|
||||
from .._xml import get_text
|
||||
from .univariate import Univariate, Uniform
|
||||
from .univariate import Univariate, Uniform, PowerLaw
|
||||
|
||||
|
||||
class UnitSphere(ABC):
|
||||
|
|
@ -208,7 +208,6 @@ class Monodirectional(UnitSphere):
|
|||
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, reference_uvw=[1., 0., 0.]):
|
||||
super().__init__(reference_uvw)
|
||||
|
||||
|
|
@ -375,8 +374,8 @@ class SphericalIndependent(Spatial):
|
|||
r"""Spatial distribution represented in spherical coordinates.
|
||||
|
||||
This distribution allows one to specify coordinates whose :math:`r`,
|
||||
:math:`\theta`, and :math:`\phi` components are sampled independently from
|
||||
one another and centered on the coordinates (x0, y0, z0).
|
||||
:math:`\theta`, and :math:`\phi` components are sampled independently
|
||||
from one another and centered on the coordinates (x0, y0, z0).
|
||||
|
||||
.. versionadded: 0.12
|
||||
|
||||
|
|
@ -385,9 +384,9 @@ class SphericalIndependent(Spatial):
|
|||
r : openmc.stats.Univariate
|
||||
Distribution of r-coordinates in a reference frame specified by
|
||||
the origin parameter
|
||||
theta : openmc.stats.Univariate
|
||||
Distribution of theta-coordinates (angle relative to the z-axis) in a
|
||||
reference frame specified by the origin parameter
|
||||
cos_theta : openmc.stats.Univariate
|
||||
Distribution of the cosine of the theta-coordinates (angle relative to
|
||||
the z-axis) in a reference frame specified by the origin parameter
|
||||
phi : openmc.stats.Univariate
|
||||
Distribution of phi-coordinates (azimuthal angle) in a reference frame
|
||||
specified by the origin parameter
|
||||
|
|
@ -399,9 +398,9 @@ class SphericalIndependent(Spatial):
|
|||
----------
|
||||
r : openmc.stats.Univariate
|
||||
Distribution of r-coordinates in the local reference frame
|
||||
theta : openmc.stats.Univariate
|
||||
Distribution of theta-coordinates (angle relative to the z-axis) in the
|
||||
local reference frame
|
||||
cos_theta : openmc.stats.Univariate
|
||||
Distribution of the cosine of the theta-coordinates (angle relative to
|
||||
the z-axis) in the local reference frame
|
||||
phi : openmc.stats.Univariate
|
||||
Distribution of phi-coordinates (azimuthal angle) in the local
|
||||
reference frame
|
||||
|
|
@ -411,9 +410,9 @@ class SphericalIndependent(Spatial):
|
|||
|
||||
"""
|
||||
|
||||
def __init__(self, r, theta, phi, origin=(0.0, 0.0, 0.0)):
|
||||
def __init__(self, r, cos_theta, phi, origin=(0.0, 0.0, 0.0)):
|
||||
self.r = r
|
||||
self.theta = theta
|
||||
self.cos_theta = cos_theta
|
||||
self.phi = phi
|
||||
self.origin = origin
|
||||
|
||||
|
|
@ -422,8 +421,8 @@ class SphericalIndependent(Spatial):
|
|||
return self._r
|
||||
|
||||
@property
|
||||
def theta(self):
|
||||
return self._theta
|
||||
def cos_theta(self):
|
||||
return self._cos_theta
|
||||
|
||||
@property
|
||||
def phi(self):
|
||||
|
|
@ -438,10 +437,10 @@ class SphericalIndependent(Spatial):
|
|||
cv.check_type('r coordinate', r, Univariate)
|
||||
self._r = r
|
||||
|
||||
@theta.setter
|
||||
def theta(self, theta):
|
||||
cv.check_type('theta coordinate', theta, Univariate)
|
||||
self._theta = theta
|
||||
@cos_theta.setter
|
||||
def cos_theta(self, cos_theta):
|
||||
cv.check_type('cos_theta coordinate', cos_theta, Univariate)
|
||||
self._cos_theta = cos_theta
|
||||
|
||||
@phi.setter
|
||||
def phi(self, phi):
|
||||
|
|
@ -466,7 +465,7 @@ class SphericalIndependent(Spatial):
|
|||
element = ET.Element('space')
|
||||
element.set('type', 'spherical')
|
||||
element.append(self.r.to_xml_element('r'))
|
||||
element.append(self.theta.to_xml_element('theta'))
|
||||
element.append(self.cos_theta.to_xml_element('cos_theta'))
|
||||
element.append(self.phi.to_xml_element('phi'))
|
||||
element.set("origin", ' '.join(map(str, self.origin)))
|
||||
return element
|
||||
|
|
@ -487,10 +486,10 @@ class SphericalIndependent(Spatial):
|
|||
|
||||
"""
|
||||
r = Univariate.from_xml_element(elem.find('r'))
|
||||
theta = Univariate.from_xml_element(elem.find('theta'))
|
||||
cos_theta = Univariate.from_xml_element(elem.find('cos_theta'))
|
||||
phi = Univariate.from_xml_element(elem.find('phi'))
|
||||
origin = [float(x) for x in elem.get('origin').split()]
|
||||
return cls(r, theta, phi, origin=origin)
|
||||
return cls(r, cos_theta, phi, origin=origin)
|
||||
|
||||
|
||||
class CylindricalIndependent(Spatial):
|
||||
|
|
@ -640,7 +639,6 @@ class Box(Spatial):
|
|||
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, lower_left, upper_right, only_fissionable=False):
|
||||
self.lower_left = lower_left
|
||||
self.upper_right = upper_right
|
||||
|
|
@ -779,3 +777,42 @@ class Point(Spatial):
|
|||
"""
|
||||
xyz = [float(x) for x in get_text(elem, 'parameters').split()]
|
||||
return cls(xyz)
|
||||
|
||||
|
||||
def spherical_uniform(r_outer, r_inner=0.0, thetas=(0., pi), phis=(0., 2*pi),
|
||||
origin=(0., 0., 0.)):
|
||||
"""Return a uniform spatial distribution over a spherical shell.
|
||||
|
||||
This function provides a uniform spatial distribution over a spherical
|
||||
shell between `r_inner` and `r_outer`. Optionally, the range of angles
|
||||
can be restricted by the `thetas` and `phis` arguments.
|
||||
|
||||
.. versionadded: 0.13.1
|
||||
|
||||
Parameters
|
||||
----------
|
||||
r_outer : float
|
||||
Outer radius of the spherical shell in [cm]
|
||||
r_inner : float, optional
|
||||
Inner radius of the spherical shell in [cm]
|
||||
thetas : iterable of float, optional
|
||||
Starting and ending theta coordinates (angle relative to
|
||||
the z-axis) in radius in a reference frame centered at `origin`
|
||||
phis : iterable of float, optional
|
||||
Starting and ending phi coordinates (azimuthal angle) in
|
||||
radians in a reference frame centered at `origin`
|
||||
origin: iterable of float, optional
|
||||
Coordinates (x0, y0, z0) of the center of the spherical
|
||||
reference frame for the distribution.
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.stats.SphericalIndependent
|
||||
Uniform distribution over the spherical shell
|
||||
"""
|
||||
|
||||
r_dist = PowerLaw(r_inner, r_outer, 2)
|
||||
cos_thetas_dist = Uniform(cos(thetas[1]), cos(thetas[0]))
|
||||
phis_dist = Uniform(phis[0], phis[1])
|
||||
|
||||
return SphericalIndependent(r_dist, cos_thetas_dist, phis_dist, origin)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from collections import defaultdict
|
||||
from collections.abc import Iterable
|
||||
from numbers import Real
|
||||
from xml.etree import ElementTree as ET
|
||||
|
|
@ -156,6 +157,38 @@ class Discrete(Univariate):
|
|||
p = params[len(params)//2:]
|
||||
return cls(x, p)
|
||||
|
||||
@classmethod
|
||||
def merge(cls, dists, probs):
|
||||
"""Merge multiple discrete distributions into a single distribution
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dists : iterable of openmc.stats.Discrete
|
||||
Discrete distributions to combine
|
||||
probs : iterable of float
|
||||
Probability of each distribution
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.stats.Discrete
|
||||
Combined discrete distribution
|
||||
|
||||
"""
|
||||
if len(dists) != len(probs):
|
||||
raise ValueError("Number of distributions and probabilities must match.")
|
||||
|
||||
# Combine distributions accounting for duplicate x values
|
||||
x_merged = set()
|
||||
p_merged = defaultdict(float)
|
||||
for dist, p_dist in zip(dists, probs):
|
||||
for x, p in zip(dist.x, dist.p):
|
||||
x_merged.add(x)
|
||||
p_merged[x] += p*p_dist
|
||||
|
||||
# Create values and probabilities as arrays
|
||||
x_arr = np.array(sorted(x_merged))
|
||||
p_arr = np.array([p_merged[x] for x in x_arr])
|
||||
return cls(x_arr, p_arr)
|
||||
|
||||
class Uniform(Univariate):
|
||||
"""Distribution with constant probability over a finite interval [a,b]
|
||||
|
|
|
|||
|
|
@ -760,7 +760,7 @@ class XPlane(PlaneMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
Location of the plane. Defaults to 0.
|
||||
Location of the plane in [cm]. Defaults to 0.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface. Defaults to transmissive boundary condition where particles
|
||||
|
|
@ -775,7 +775,7 @@ class XPlane(PlaneMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
Location of the plane
|
||||
Location of the plane in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -819,7 +819,7 @@ class YPlane(PlaneMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
y0 : float, optional
|
||||
Location of the plane
|
||||
Location of the plane in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface. Defaults to transmissive boundary condition where particles
|
||||
|
|
@ -834,7 +834,7 @@ class YPlane(PlaneMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
y0 : float
|
||||
Location of the plane
|
||||
Location of the plane in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -878,7 +878,7 @@ class ZPlane(PlaneMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
z0 : float, optional
|
||||
Location of the plane. Defaults to 0.
|
||||
Location of the plane in [cm]. Defaults to 0.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}, optional
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface. Defaults to transmissive boundary condition where particles
|
||||
|
|
@ -893,7 +893,7 @@ class ZPlane(PlaneMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
z0 : float
|
||||
Location of the plane
|
||||
Location of the plane in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'periodic', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -991,8 +991,8 @@ class QuadricMixin:
|
|||
Parameters
|
||||
----------
|
||||
point : 3-tuple of float
|
||||
The Cartesian coordinates, :math:`(x',y',z')`, at which the surface
|
||||
equation should be evaluated.
|
||||
The Cartesian coordinates, :math:`(x',y',z')`, in [cm] at which the
|
||||
surface equation should be evaluated.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -1106,13 +1106,13 @@ class Cylinder(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
x-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
y0 : float, optional
|
||||
y-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
y-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
z0 : float, optional
|
||||
z-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
z-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
r : float, optional
|
||||
Radius of the cylinder. Defaults to 1.
|
||||
Radius of the cylinder in [cm]. Defaults to 1.
|
||||
dx : float, optional
|
||||
x-component of the vector representing the axis of the cylinder.
|
||||
Defaults to 0.
|
||||
|
|
@ -1136,13 +1136,13 @@ class Cylinder(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate for the origin of the Cylinder
|
||||
x-coordinate for the origin of the Cylinder in [cm]
|
||||
y0 : float
|
||||
y-coordinate for the origin of the Cylinder
|
||||
y-coordinate for the origin of the Cylinder in [cm]
|
||||
z0 : float
|
||||
z-coordinate for the origin of the Cylinder
|
||||
z-coordinate for the origin of the Cylinder in [cm]
|
||||
r : float
|
||||
Radius of the cylinder
|
||||
Radius of the cylinder in [cm]
|
||||
dx : float
|
||||
x-component of the vector representing the axis of the cylinder
|
||||
dy : float
|
||||
|
|
@ -1243,7 +1243,7 @@ class Cylinder(QuadricMixin, Surface):
|
|||
p1, p2 : 3-tuples
|
||||
Points that pass through the plane, p1 will be used as (x0, y0, z0)
|
||||
r : float, optional
|
||||
Radius of the cylinder. Defaults to 1.
|
||||
Radius of the cylinder in [cm]. Defaults to 1.
|
||||
kwargs : dict
|
||||
Keyword arguments passed to the :class:`Cylinder` constructor
|
||||
|
||||
|
|
@ -1288,11 +1288,11 @@ class XCylinder(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
y0 : float, optional
|
||||
y-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
y-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
z0 : float, optional
|
||||
z-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
z-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
r : float, optional
|
||||
Radius of the cylinder. Defaults to 1.
|
||||
Radius of the cylinder in [cm]. Defaults to 1.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface. Defaults to transmissive boundary condition where particles
|
||||
|
|
@ -1307,11 +1307,11 @@ class XCylinder(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
y0 : float
|
||||
y-coordinate for the origin of the Cylinder
|
||||
y-coordinate for the origin of the Cylinder in [cm]
|
||||
z0 : float
|
||||
z-coordinate for the origin of the Cylinder
|
||||
z-coordinate for the origin of the Cylinder in [cm]
|
||||
r : float
|
||||
Radius of the cylinder
|
||||
Radius of the cylinder in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -1379,11 +1379,11 @@ class YCylinder(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
x-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
z0 : float, optional
|
||||
z-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
z-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
r : float, optional
|
||||
Radius of the cylinder. Defaults to 1.
|
||||
Radius of the cylinder in [cm]. Defaults to 1.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface. Defaults to transmissive boundary condition where particles
|
||||
|
|
@ -1398,11 +1398,11 @@ class YCylinder(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate for the origin of the Cylinder
|
||||
x-coordinate for the origin of the Cylinder in [cm]
|
||||
z0 : float
|
||||
z-coordinate for the origin of the Cylinder
|
||||
z-coordinate for the origin of the Cylinder in [cm]
|
||||
r : float
|
||||
Radius of the cylinder
|
||||
Radius of the cylinder in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -1470,11 +1470,11 @@ class ZCylinder(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
x-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
y0 : float, optional
|
||||
y-coordinate for the origin of the Cylinder. Defaults to 0
|
||||
y-coordinate for the origin of the Cylinder in [cm]. Defaults to 0
|
||||
r : float, optional
|
||||
Radius of the cylinder. Defaults to 1.
|
||||
Radius of the cylinder in [cm]. Defaults to 1.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface. Defaults to transmissive boundary condition where particles
|
||||
|
|
@ -1489,11 +1489,11 @@ class ZCylinder(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate for the origin of the Cylinder
|
||||
x-coordinate for the origin of the Cylinder in [cm]
|
||||
y0 : float
|
||||
y-coordinate for the origin of the Cylinder
|
||||
y-coordinate for the origin of the Cylinder in [cm]
|
||||
r : float
|
||||
Radius of the cylinder
|
||||
Radius of the cylinder in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -1560,13 +1560,13 @@ class Sphere(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate of the center of the sphere. Defaults to 0.
|
||||
x-coordinate of the center of the sphere in [cm]. Defaults to 0.
|
||||
y0 : float, optional
|
||||
y-coordinate of the center of the sphere. Defaults to 0.
|
||||
y-coordinate of the center of the sphere in [cm]. Defaults to 0.
|
||||
z0 : float, optional
|
||||
z-coordinate of the center of the sphere. Defaults to 0.
|
||||
z-coordinate of the center of the sphere in [cm]. Defaults to 0.
|
||||
r : float, optional
|
||||
Radius of the sphere. Defaults to 1.
|
||||
Radius of the sphere in [cm]. Defaults to 1.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface. Defaults to transmissive boundary condition where particles
|
||||
|
|
@ -1580,13 +1580,13 @@ class Sphere(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the center of the sphere
|
||||
x-coordinate of the center of the sphere in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the center of the sphere
|
||||
y-coordinate of the center of the sphere in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the center of the sphere
|
||||
z-coordinate of the center of the sphere in [cm]
|
||||
r : float
|
||||
Radius of the sphere
|
||||
Radius of the sphere in [cm]
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -1653,11 +1653,11 @@ class Cone(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate of the apex. Defaults to 0.
|
||||
x-coordinate of the apex in [cm]. Defaults to 0.
|
||||
y0 : float, optional
|
||||
y-coordinate of the apex. Defaults to 0.
|
||||
y-coordinate of the apex in [cm]. Defaults to 0.
|
||||
z0 : float, optional
|
||||
z-coordinate of the apex. Defaults to 0.
|
||||
z-coordinate of the apex in [cm]. Defaults to 0.
|
||||
r2 : float, optional
|
||||
Parameter related to the aperature. Defaults to 1.
|
||||
dx : float, optional
|
||||
|
|
@ -1682,11 +1682,11 @@ class Cone(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the apex
|
||||
x-coordinate of the apex in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the apex
|
||||
y-coordinate of the apex in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the apex
|
||||
z-coordinate of the apex in [cm]
|
||||
r2 : float
|
||||
Parameter related to the aperature
|
||||
dx : float
|
||||
|
|
@ -1796,11 +1796,11 @@ class XCone(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate of the apex. Defaults to 0.
|
||||
x-coordinate of the apex in [cm]. Defaults to 0.
|
||||
y0 : float, optional
|
||||
y-coordinate of the apex. Defaults to 0.
|
||||
y-coordinate of the apex in [cm]. Defaults to 0.
|
||||
z0 : float, optional
|
||||
z-coordinate of the apex. Defaults to 0.
|
||||
z-coordinate of the apex in [cm]. Defaults to 0.
|
||||
r2 : float, optional
|
||||
Parameter related to the aperature. Defaults to 1.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional
|
||||
|
|
@ -1816,11 +1816,11 @@ class XCone(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the apex
|
||||
x-coordinate of the apex in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the apex
|
||||
y-coordinate of the apex in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the apex
|
||||
z-coordinate of the apex in [cm]
|
||||
r2 : float
|
||||
Parameter related to the aperature
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
|
|
@ -1885,11 +1885,11 @@ class YCone(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate of the apex. Defaults to 0.
|
||||
x-coordinate of the apex in [cm]. Defaults to 0.
|
||||
y0 : float, optional
|
||||
y-coordinate of the apex. Defaults to 0.
|
||||
y-coordinate of the apex in [cm]. Defaults to 0.
|
||||
z0 : float, optional
|
||||
z-coordinate of the apex. Defaults to 0.
|
||||
z-coordinate of the apex in [cm]. Defaults to 0.
|
||||
r2 : float, optional
|
||||
Parameter related to the aperature. Defaults to 1.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional
|
||||
|
|
@ -1905,11 +1905,11 @@ class YCone(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the apex
|
||||
x-coordinate of the apex in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the apex
|
||||
y-coordinate of the apex in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the apex
|
||||
z-coordinate of the apex in [cm]
|
||||
r2 : float
|
||||
Parameter related to the aperature
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
|
|
@ -1974,11 +1974,11 @@ class ZCone(QuadricMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float, optional
|
||||
x-coordinate of the apex. Defaults to 0.
|
||||
x-coordinate of the apex in [cm]. Defaults to 0.
|
||||
y0 : float, optional
|
||||
y-coordinate of the apex. Defaults to 0.
|
||||
y-coordinate of the apex in [cm]. Defaults to 0.
|
||||
z0 : float, optional
|
||||
z-coordinate of the apex. Defaults to 0.
|
||||
z-coordinate of the apex in [cm]. Defaults to 0.
|
||||
r2 : float, optional
|
||||
Parameter related to the aperature. Defaults to 1.
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}, optional
|
||||
|
|
@ -1994,11 +1994,11 @@ class ZCone(QuadricMixin, Surface):
|
|||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the apex
|
||||
x-coordinate of the apex in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the apex
|
||||
y-coordinate of the apex in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the apex
|
||||
z-coordinate of the apex in [cm]
|
||||
r2 : float
|
||||
Parameter related to the aperature
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
|
|
@ -2198,34 +2198,34 @@ class XTorus(TorusMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the center of the axis of revolution
|
||||
x-coordinate of the center of the axis of revolution in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the center of the axis of revolution
|
||||
y-coordinate of the center of the axis of revolution in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the center of the axis of revolution
|
||||
z-coordinate of the center of the axis of revolution in [cm]
|
||||
a : float
|
||||
Major radius of the torus
|
||||
Major radius of the torus in [cm]
|
||||
b : float
|
||||
Minor radius of the torus (parallel to axis of revolution)
|
||||
Minor radius of the torus in [cm] (parallel to axis of revolution)
|
||||
c : float
|
||||
Minor radius of the torus (perpendicular to axis of revolution)
|
||||
Minor radius of the torus in [cm] (perpendicular to axis of revolution)
|
||||
kwargs : dict
|
||||
Keyword arguments passed to the :class:`Surface` constructor
|
||||
|
||||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the center of the axis of revolution
|
||||
x-coordinate of the center of the axis of revolution in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the center of the axis of revolution
|
||||
y-coordinate of the center of the axis of revolution in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the center of the axis of revolution
|
||||
z-coordinate of the center of the axis of revolution in [cm]
|
||||
a : float
|
||||
Major radius of the torus
|
||||
Major radius of the torus in [cm]
|
||||
b : float
|
||||
Minor radius of the torus (parallel to axis of revolution)
|
||||
Minor radius of the torus in [cm] (parallel to axis of revolution)
|
||||
c : float
|
||||
Minor radius of the torus (perpendicular to axis of revolution)
|
||||
Minor radius of the torus in [cm] (perpendicular to axis of revolution)
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
@ -2269,32 +2269,32 @@ class YTorus(TorusMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the center of the axis of revolution
|
||||
x-coordinate of the center of the axis of revolution in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the center of the axis of revolution
|
||||
y-coordinate of the center of the axis of revolution in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the center of the axis of revolution
|
||||
z-coordinate of the center of the axis of revolution in [cm]
|
||||
a : float
|
||||
Major radius of the torus
|
||||
Major radius of the torus in [cm]
|
||||
b : float
|
||||
Minor radius of the torus (parallel to axis of revolution)
|
||||
Minor radius of the torus in [cm] (parallel to axis of revolution)
|
||||
c : float
|
||||
Minor radius of the torus (perpendicular to axis of revolution)
|
||||
Minor radius of the torus in [cm] (perpendicular to axis of revolution)
|
||||
kwargs : dict
|
||||
Keyword arguments passed to the :class:`Surface` constructor
|
||||
|
||||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the center of the axis of revolution
|
||||
x-coordinate of the center of the axis of revolution in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the center of the axis of revolution
|
||||
y-coordinate of the center of the axis of revolution in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the center of the axis of revolution
|
||||
z-coordinate of the center of the axis of revolution in [cm]
|
||||
a : float
|
||||
Major radius of the torus
|
||||
Major radius of the torus in [cm]
|
||||
b : float
|
||||
Minor radius of the torus (parallel to axis of revolution)
|
||||
Minor radius of the torus in [cm] (parallel to axis of revolution)
|
||||
c : float
|
||||
Minor radius of the torus (perpendicular to axis of revolution)
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
|
|
@ -2340,34 +2340,34 @@ class ZTorus(TorusMixin, Surface):
|
|||
Parameters
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the center of the axis of revolution
|
||||
x-coordinate of the center of the axis of revolution in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the center of the axis of revolution
|
||||
y-coordinate of the center of the axis of revolution in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the center of the axis of revolution
|
||||
z-coordinate of the center of the axis of revolution in [cm]
|
||||
a : float
|
||||
Major radius of the torus
|
||||
Major radius of the torus in [cm]
|
||||
b : float
|
||||
Minor radius of the torus (parallel to axis of revolution)
|
||||
Minor radius of the torus in [cm] (parallel to axis of revolution)
|
||||
c : float
|
||||
Minor radius of the torus (perpendicular to axis of revolution)
|
||||
Minor radius of the torus in [cm] (perpendicular to axis of revolution)
|
||||
kwargs : dict
|
||||
Keyword arguments passed to the :class:`Surface` constructor
|
||||
|
||||
Attributes
|
||||
----------
|
||||
x0 : float
|
||||
x-coordinate of the center of the axis of revolution
|
||||
x-coordinate of the center of the axis of revolution in [cm]
|
||||
y0 : float
|
||||
y-coordinate of the center of the axis of revolution
|
||||
y-coordinate of the center of the axis of revolution in [cm]
|
||||
z0 : float
|
||||
z-coordinate of the center of the axis of revolution
|
||||
z-coordinate of the center of the axis of revolution in [cm]
|
||||
a : float
|
||||
Major radius of the torus
|
||||
Major radius of the torus in [cm]
|
||||
b : float
|
||||
Minor radius of the torus (parallel to axis of revolution)
|
||||
Minor radius of the torus in [cm] (parallel to axis of revolution)
|
||||
c : float
|
||||
Minor radius of the torus (perpendicular to axis of revolution)
|
||||
Minor radius of the torus in [cm] (perpendicular to axis of revolution)
|
||||
boundary_type : {'transmission, 'vacuum', 'reflective', 'white'}
|
||||
Boundary condition that defines the behavior for particles hitting the
|
||||
surface.
|
||||
|
|
|
|||
291
openmc/tracks.py
Normal file
291
openmc/tracks.py
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
from collections import namedtuple
|
||||
from collections.abc import Sequence
|
||||
|
||||
import h5py
|
||||
|
||||
from .checkvalue import check_filetype_version
|
||||
from .source import SourceParticle, ParticleType
|
||||
|
||||
|
||||
ParticleTrack = namedtuple('ParticleTrack', ['particle', 'states'])
|
||||
ParticleTrack.__doc__ = """\
|
||||
Particle track information
|
||||
|
||||
Parameters
|
||||
----------
|
||||
particle : openmc.ParticleType
|
||||
Type of the particle
|
||||
states : numpy.ndarray
|
||||
Structured array containing each state of the particle. The structured array
|
||||
contains the following fields: ``r`` (position; each direction in [cm]),
|
||||
``u`` (direction), ``E`` (energy in [eV]), ``time`` (time in [s]), ``wgt``
|
||||
(weight), ``cell_id`` (cell ID) , ``cell_instance`` (cell instance), and
|
||||
``material_id`` (material ID).
|
||||
|
||||
"""
|
||||
def _particle_track_repr(self):
|
||||
name = self.particle.name.lower()
|
||||
return f"<ParticleTrack: {name}, {len(self.states)} states>"
|
||||
ParticleTrack.__repr__ = _particle_track_repr
|
||||
|
||||
|
||||
_VERSION_TRACK = 3
|
||||
|
||||
|
||||
def _identifier(dset_name):
|
||||
"""Return (batch, gen, particle) tuple given dataset name"""
|
||||
_, batch, gen, particle = dset_name.split('_')
|
||||
return (int(batch), int(gen), int(particle))
|
||||
|
||||
|
||||
class Track(Sequence):
|
||||
"""Tracks resulting from a single source particle
|
||||
|
||||
This class stores information for all tracks resulting from a primary source
|
||||
particle and any secondary particles that it created. The track for each
|
||||
primary/secondary particle is stored in the :attr:`particle_tracks`
|
||||
attribute.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dset : h5py.Dataset
|
||||
Dataset to read track data from
|
||||
|
||||
Attributes
|
||||
----------
|
||||
identifier : tuple
|
||||
Tuple of (batch, generation, particle number)
|
||||
particle_tracks : list
|
||||
List of tuples containing (particle type, array of track states)
|
||||
sources : list
|
||||
List of :class:`SourceParticle` representing each primary/secondary
|
||||
particle
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, dset):
|
||||
tracks = dset[()]
|
||||
offsets = dset.attrs['offsets']
|
||||
particles = dset.attrs['particles']
|
||||
self.identifier = _identifier(dset.name)
|
||||
|
||||
# Construct list of track histories
|
||||
tracks_list = []
|
||||
for particle, start, end in zip(particles, offsets[:-1], offsets[1:]):
|
||||
ptype = ParticleType(particle)
|
||||
tracks_list.append(ParticleTrack(ptype, tracks[start:end]))
|
||||
self.particle_tracks = tracks_list
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Track {self.identifier}: {len(self.particle_tracks)} particles>'
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.particle_tracks[index]
|
||||
|
||||
def __len__(self):
|
||||
return len(self.particle_tracks)
|
||||
|
||||
def filter(self, particle=None, state_filter=None):
|
||||
"""Filter particle tracks by given criteria
|
||||
|
||||
Parameters
|
||||
----------
|
||||
particle : {'neutron', 'photon', 'electron', 'positron'}
|
||||
Matching particle type
|
||||
state_filter : function
|
||||
Function that takes a state (structured datatype) and returns a bool
|
||||
depending on some criteria.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Track
|
||||
New instance with only matching :class:`openmc.ParticleTrack` objects
|
||||
|
||||
Examples
|
||||
--------
|
||||
Get all particle tracks for photons:
|
||||
|
||||
>>> track.filter(particle='photon')
|
||||
|
||||
Get all particle tracks that entered cell with ID=15:
|
||||
|
||||
>>> track.filter(state_filter=lambda s: s['cell_id'] == 15)
|
||||
|
||||
Get all particle tracks in entered material with ID=2:
|
||||
|
||||
>>> track.filter(state_filter=lambda s: s['material_id'] == 2)
|
||||
|
||||
See Also
|
||||
--------
|
||||
openmc.ParticleTrack
|
||||
|
||||
"""
|
||||
matching = []
|
||||
for t in self:
|
||||
# Check for matching particle
|
||||
if particle is not None:
|
||||
if t.particle.name.lower() != particle:
|
||||
continue
|
||||
|
||||
# Apply arbitrary state filter
|
||||
match = True
|
||||
if state_filter is not None:
|
||||
for state in t.states:
|
||||
if state_filter(state):
|
||||
break
|
||||
else:
|
||||
match = False
|
||||
|
||||
if match:
|
||||
matching.append(t)
|
||||
|
||||
# Return new Track instance with only matching particle tracks
|
||||
track = type(self).__new__(type(self))
|
||||
track.identifier = self.identifier
|
||||
track.particle_tracks = matching
|
||||
return track
|
||||
|
||||
def plot(self, axes=None):
|
||||
"""Produce a 3D plot of particle tracks
|
||||
|
||||
Parameters
|
||||
----------
|
||||
axes : matplotlib.axes.Axes, optional
|
||||
Axes for plot
|
||||
|
||||
Returns
|
||||
-------
|
||||
axes : matplotlib.axes.Axes
|
||||
Axes for plot
|
||||
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# Setup axes is one wasn't passed
|
||||
if axes is None:
|
||||
fig = plt.figure()
|
||||
ax = plt.axes(projection='3d')
|
||||
ax.set_xlabel('x [cm]')
|
||||
ax.set_ylabel('y [cm]')
|
||||
ax.set_zlabel('z [cm]')
|
||||
else:
|
||||
ax = axes
|
||||
|
||||
# Plot each particle track
|
||||
for _, states in self:
|
||||
r = states['r']
|
||||
ax.plot3D(r['x'], r['y'], r['z'])
|
||||
|
||||
return ax
|
||||
|
||||
@property
|
||||
def sources(self):
|
||||
sources = []
|
||||
for particle_track in self:
|
||||
particle_type = ParticleType(particle_track.particle)
|
||||
state = particle_track.states[0]
|
||||
sources.append(
|
||||
SourceParticle(
|
||||
r=state['r'], u=state['u'], E=state['E'],
|
||||
time=state['time'], wgt=state['wgt'],
|
||||
particle=particle_type
|
||||
)
|
||||
)
|
||||
return sources
|
||||
|
||||
|
||||
class Tracks(list):
|
||||
"""Collection of particle tracks
|
||||
|
||||
This class behaves like a list and can be indexed using the normal subscript
|
||||
notation. Each element in the list is a :class:`openmc.Track` object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filepath : str or pathlib.Path
|
||||
Path of file to load
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, filepath='tracks.h5'):
|
||||
# Read data from track file
|
||||
with h5py.File(filepath, 'r') as fh:
|
||||
# Check filetype and version
|
||||
check_filetype_version(fh, 'track', _VERSION_TRACK)
|
||||
|
||||
for dset_name in sorted(fh, key=_identifier):
|
||||
dset = fh[dset_name]
|
||||
self.append(Track(dset))
|
||||
|
||||
def filter(self, particle=None, state_filter=None):
|
||||
"""Filter tracks by given criteria
|
||||
|
||||
Parameters
|
||||
----------
|
||||
particle : {'neutron', 'photon', 'electron', 'positron'}
|
||||
Matching particle type
|
||||
state_filter : function
|
||||
Function that takes a state (structured datatype) and returns a bool
|
||||
depending on some criteria.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Tracks
|
||||
List of :class:`openmc.Track` objects
|
||||
|
||||
See Also
|
||||
--------
|
||||
openmc.Track.filter
|
||||
|
||||
"""
|
||||
# Create a new Tracks instance but avoid call to __init__
|
||||
matching = type(self).__new__(type(self))
|
||||
|
||||
# Append matching Track objects
|
||||
for track in self:
|
||||
if track.filter(particle, state_filter):
|
||||
matching.append(track)
|
||||
return matching
|
||||
|
||||
def plot(self):
|
||||
"""Produce a 3D plot of particle tracks
|
||||
|
||||
Returns
|
||||
-------
|
||||
matplotlib.axes.Axes
|
||||
Axes for plot
|
||||
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
fig = plt.figure()
|
||||
ax = plt.axes(projection='3d')
|
||||
ax.set_xlabel('x [cm]')
|
||||
ax.set_ylabel('y [cm]')
|
||||
ax.set_zlabel('z [cm]')
|
||||
for track in self:
|
||||
track.plot(ax)
|
||||
return ax
|
||||
|
||||
@staticmethod
|
||||
def combine(track_files, path='tracks.h5'):
|
||||
"""Combine multiple track files into a single track file
|
||||
|
||||
Parameters
|
||||
----------
|
||||
track_files : list of path-like
|
||||
Paths to track files to combine
|
||||
path : path-like
|
||||
Path of combined track file to create
|
||||
|
||||
"""
|
||||
with h5py.File(path, 'w') as h5_out:
|
||||
for i, fname in enumerate(track_files):
|
||||
with h5py.File(fname, 'r') as h5_in:
|
||||
# Copy file attributes for first file
|
||||
if i == 0:
|
||||
h5_out.attrs['filetype'] = h5_in.attrs['filetype']
|
||||
h5_out.attrs['version'] = h5_in.attrs['version']
|
||||
|
||||
# Copy each 'track_*' dataset from input file
|
||||
for dset in h5_in:
|
||||
h5_in.copy(dset, h5_out)
|
||||
24
scripts/openmc-track-combine
Executable file
24
scripts/openmc-track-combine
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""Combine multiple HDF5 particle track files."""
|
||||
|
||||
import argparse
|
||||
|
||||
import openmc
|
||||
|
||||
|
||||
def main():
|
||||
# Parse command-line arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Combine particle track files into a single .h5 file.')
|
||||
parser.add_argument('input', metavar='IN', nargs='+',
|
||||
help='Input HDF5 particle track filename(s).')
|
||||
parser.add_argument('-o', '--out', metavar='OUT', default='tracks.h5',
|
||||
help='Output HDF5 particle track file.')
|
||||
|
||||
args = parser.parse_args()
|
||||
openmc.Tracks.combine(args.input, args.out)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -4,18 +4,16 @@
|
|||
|
||||
"""
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import struct
|
||||
|
||||
import h5py
|
||||
import openmc
|
||||
import vtk
|
||||
|
||||
|
||||
def _parse_args():
|
||||
# Create argument parser.
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Convert particle track file to a .pvtp file.')
|
||||
description='Convert particle track file(s) to a .pvtp file.')
|
||||
parser.add_argument('input', metavar='IN', type=str, nargs='+',
|
||||
help='Input particle track data filename(s).')
|
||||
parser.add_argument('-o', '--out', metavar='OUT', type=str, dest='out',
|
||||
|
|
@ -41,25 +39,22 @@ def main():
|
|||
point_offset = 0
|
||||
for fname in args.input:
|
||||
# Write coordinate values to points array.
|
||||
track = h5py.File(fname)
|
||||
n_particles = track.attrs['n_particles']
|
||||
n_coords = track.attrs['n_coords']
|
||||
coords = []
|
||||
for i in range(n_particles):
|
||||
coords.append(track['coordinates_' + str(i + 1)][()])
|
||||
for j in range(n_coords[i]):
|
||||
points.InsertNextPoint(coords[i][j,:])
|
||||
track_file = openmc.Tracks(fname)
|
||||
for track in track_file:
|
||||
for particle in track:
|
||||
for state in particle.states:
|
||||
points.InsertNextPoint(state['r'])
|
||||
|
||||
for i in range(n_particles):
|
||||
# Create VTK line and assign points to line.
|
||||
line = vtk.vtkPolyLine()
|
||||
line.GetPointIds().SetNumberOfIds(n_coords[i])
|
||||
for j in range(n_coords[i]):
|
||||
line.GetPointIds().SetId(j, point_offset + j)
|
||||
# Create VTK line and assign points to line.
|
||||
n = particle.states.size
|
||||
line = vtk.vtkPolyLine()
|
||||
line.GetPointIds().SetNumberOfIds(n)
|
||||
for i in range(n):
|
||||
line.GetPointIds().SetId(i, point_offset + i)
|
||||
point_offset += n
|
||||
|
||||
# Add line to cell array
|
||||
cells.InsertNextCell(line)
|
||||
point_offset += n_coords[i]
|
||||
# Add line to cell array
|
||||
cells.InsertNextCell(line)
|
||||
|
||||
data = vtk.vtkPolyData()
|
||||
data.SetPoints(points)
|
||||
|
|
|
|||
23
src/cell.cpp
23
src/cell.cpp
|
|
@ -846,6 +846,20 @@ void read_cells(pugi::xml_node node)
|
|||
|
||||
read_dagmc_universes(node);
|
||||
|
||||
populate_universes();
|
||||
|
||||
// Allocate the cell overlap count if necessary.
|
||||
if (settings::check_overlaps) {
|
||||
model::overlap_check_count.resize(model::cells.size(), 0);
|
||||
}
|
||||
|
||||
if (model::cells.size() == 0) {
|
||||
fatal_error("No cells were found in the geometry.xml file");
|
||||
}
|
||||
}
|
||||
|
||||
void populate_universes()
|
||||
{
|
||||
// Populate the Universe vector and map.
|
||||
for (int i = 0; i < model::cells.size(); i++) {
|
||||
int32_t uid = model::cells[i]->universe_;
|
||||
|
|
@ -860,15 +874,6 @@ void read_cells(pugi::xml_node node)
|
|||
}
|
||||
}
|
||||
model::universes.shrink_to_fit();
|
||||
|
||||
// Allocate the cell overlap count if necessary.
|
||||
if (settings::check_overlaps) {
|
||||
model::overlap_check_count.resize(model::cells.size(), 0);
|
||||
}
|
||||
|
||||
if (model::cells.size() == 0) {
|
||||
fatal_error("No cells were found in the geometry.xml file");
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
137
src/dagmc.cpp
137
src/dagmc.cpp
|
|
@ -12,7 +12,6 @@
|
|||
#include "openmc/string_utils.h"
|
||||
|
||||
#ifdef DAGMC
|
||||
#include "dagmcmetadata.hpp"
|
||||
#include "uwuw.hpp"
|
||||
#endif
|
||||
#include <fmt/core.h>
|
||||
|
|
@ -50,6 +49,9 @@ DAGUniverse::DAGUniverse(pugi::xml_node node)
|
|||
|
||||
if (check_for_node(node, "filename")) {
|
||||
filename_ = get_node_value(node, "filename");
|
||||
if (!file_exists(filename_)) {
|
||||
fatal_error(fmt::format("DAGMC file '{}' could not be found", filename_));
|
||||
}
|
||||
} else {
|
||||
fatal_error("Must specify a file for the DAGMC universe");
|
||||
}
|
||||
|
|
@ -71,6 +73,23 @@ DAGUniverse::DAGUniverse(
|
|||
const std::string& filename, bool auto_geom_ids, bool auto_mat_ids)
|
||||
: filename_(filename), adjust_geometry_ids_(auto_geom_ids),
|
||||
adjust_material_ids_(auto_mat_ids)
|
||||
{
|
||||
set_id();
|
||||
initialize();
|
||||
}
|
||||
|
||||
DAGUniverse::DAGUniverse(std::shared_ptr<moab::DagMC> dagmc_ptr,
|
||||
const std::string& filename, bool auto_geom_ids, bool auto_mat_ids)
|
||||
: dagmc_instance_(dagmc_ptr), filename_(filename),
|
||||
adjust_geometry_ids_(auto_geom_ids), adjust_material_ids_(auto_mat_ids)
|
||||
{
|
||||
set_id();
|
||||
init_metadata();
|
||||
read_uwuw_materials();
|
||||
init_geometry();
|
||||
}
|
||||
|
||||
void DAGUniverse::set_id()
|
||||
{
|
||||
// determine the next universe id
|
||||
int32_t next_univ_id = 0;
|
||||
|
|
@ -82,48 +101,27 @@ DAGUniverse::DAGUniverse(
|
|||
|
||||
// set the universe id
|
||||
id_ = next_univ_id;
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
||||
void DAGUniverse::initialize()
|
||||
{
|
||||
geom_type() = GeometryType::DAG;
|
||||
|
||||
// determine the next cell id
|
||||
int32_t next_cell_id = 0;
|
||||
for (const auto& c : model::cells) {
|
||||
if (c->id_ > next_cell_id)
|
||||
next_cell_id = c->id_;
|
||||
}
|
||||
cell_idx_offset_ = model::cells.size();
|
||||
next_cell_id++;
|
||||
init_dagmc();
|
||||
|
||||
// determine the next surface id
|
||||
int32_t next_surf_id = 0;
|
||||
for (const auto& s : model::surfaces) {
|
||||
if (s->id_ > next_surf_id)
|
||||
next_surf_id = s->id_;
|
||||
}
|
||||
surf_idx_offset_ = model::surfaces.size();
|
||||
next_surf_id++;
|
||||
init_metadata();
|
||||
|
||||
read_uwuw_materials();
|
||||
|
||||
init_geometry();
|
||||
}
|
||||
|
||||
void DAGUniverse::init_dagmc()
|
||||
{
|
||||
|
||||
// create a new DAGMC instance
|
||||
dagmc_instance_ = std::make_shared<moab::DagMC>();
|
||||
|
||||
// --- Materials ---
|
||||
|
||||
// read any UWUW materials from the file
|
||||
read_uwuw_materials();
|
||||
|
||||
// check for uwuw material definitions
|
||||
bool using_uwuw = uses_uwuw();
|
||||
|
||||
// notify user if UWUW materials are going to be used
|
||||
if (using_uwuw) {
|
||||
write_message("Found UWUW Materials in the DAGMC geometry file.", 6);
|
||||
}
|
||||
|
||||
// load the DAGMC geometry
|
||||
filename_ = settings::path_input + filename_;
|
||||
if (!file_exists(filename_)) {
|
||||
|
|
@ -135,18 +133,35 @@ void DAGUniverse::initialize()
|
|||
// initialize acceleration data structures
|
||||
rval = dagmc_instance_->init_OBBTree();
|
||||
MB_CHK_ERR_CONT(rval);
|
||||
}
|
||||
|
||||
void DAGUniverse::init_metadata()
|
||||
{
|
||||
// parse model metadata
|
||||
dagmcMetaData DMD(dagmc_instance_.get(), false, false);
|
||||
DMD.load_property_data();
|
||||
dmd_ptr =
|
||||
std::make_unique<dagmcMetaData>(dagmc_instance_.get(), false, false);
|
||||
dmd_ptr->load_property_data();
|
||||
|
||||
std::vector<std::string> keywords {"temp"};
|
||||
std::map<std::string, std::string> dum;
|
||||
std::string delimiters = ":/";
|
||||
moab::ErrorCode rval;
|
||||
rval = dagmc_instance_->parse_properties(keywords, dum, delimiters.c_str());
|
||||
MB_CHK_ERR_CONT(rval);
|
||||
}
|
||||
|
||||
// --- Cells (Volumes) ---
|
||||
void DAGUniverse::init_geometry()
|
||||
{
|
||||
moab::ErrorCode rval;
|
||||
|
||||
// determine the next cell id
|
||||
int32_t next_cell_id = 0;
|
||||
for (const auto& c : model::cells) {
|
||||
if (c->id_ > next_cell_id)
|
||||
next_cell_id = c->id_;
|
||||
}
|
||||
cell_idx_offset_ = model::cells.size();
|
||||
next_cell_id++;
|
||||
|
||||
// initialize cell objects
|
||||
int n_cells = dagmc_instance_->num_entities(3);
|
||||
|
|
@ -175,7 +190,7 @@ void DAGUniverse::initialize()
|
|||
// --- Materials ---
|
||||
|
||||
// determine volume material assignment
|
||||
std::string mat_str = DMD.get_volume_property("material", vol_handle);
|
||||
std::string mat_str = dmd_ptr->get_volume_property("material", vol_handle);
|
||||
|
||||
if (mat_str.empty()) {
|
||||
fatal_error(fmt::format("Volume {} has no material assignment.", c->id_));
|
||||
|
|
@ -191,9 +206,10 @@ void DAGUniverse::initialize()
|
|||
if (mat_str == "void" || mat_str == "vacuum" || mat_str == "graveyard") {
|
||||
c->material_.push_back(MATERIAL_VOID);
|
||||
} else {
|
||||
if (using_uwuw) {
|
||||
if (uses_uwuw()) {
|
||||
// lookup material in uwuw if present
|
||||
std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle];
|
||||
std::string uwuw_mat =
|
||||
dmd_ptr->volume_material_property_data_eh[vol_handle];
|
||||
if (uwuw_->material_library.count(uwuw_mat) != 0) {
|
||||
// Note: material numbers are set by UWUW
|
||||
int mat_number = uwuw_->material_library.get_material(uwuw_mat)
|
||||
|
|
@ -243,7 +259,14 @@ void DAGUniverse::initialize()
|
|||
|
||||
has_graveyard_ = graveyard;
|
||||
|
||||
// --- Surfaces ---
|
||||
// determine the next surface id
|
||||
int32_t next_surf_id = 0;
|
||||
for (const auto& s : model::surfaces) {
|
||||
if (s->id_ > next_surf_id)
|
||||
next_surf_id = s->id_;
|
||||
}
|
||||
surf_idx_offset_ = model::surfaces.size();
|
||||
next_surf_id++;
|
||||
|
||||
// initialize surface objects
|
||||
int n_surfaces = dagmc_instance_->num_entities(2);
|
||||
|
|
@ -256,7 +279,8 @@ void DAGUniverse::initialize()
|
|||
: dagmc_instance_->id_by_index(2, i + 1);
|
||||
|
||||
// set BCs
|
||||
std::string bc_value = DMD.get_surface_property("boundary", surf_handle);
|
||||
std::string bc_value =
|
||||
dmd_ptr->get_surface_property("boundary", surf_handle);
|
||||
to_lower(bc_value);
|
||||
if (bc_value.empty() || bc_value == "transmit" ||
|
||||
bc_value == "transmission") {
|
||||
|
|
@ -395,7 +419,7 @@ void DAGUniverse::to_hdf5(hid_t universes_group) const
|
|||
|
||||
bool DAGUniverse::uses_uwuw() const
|
||||
{
|
||||
return !uwuw_->material_library.empty();
|
||||
return uwuw_ && !uwuw_->material_library.empty();
|
||||
}
|
||||
|
||||
std::string DAGUniverse::get_uwuw_materials_xml() const
|
||||
|
|
@ -484,33 +508,32 @@ void DAGUniverse::legacy_assign_material(
|
|||
|
||||
void DAGUniverse::read_uwuw_materials()
|
||||
{
|
||||
|
||||
int32_t next_material_id = 0;
|
||||
for (const auto& m : model::materials) {
|
||||
next_material_id = std::max(m->id_, next_material_id);
|
||||
}
|
||||
next_material_id++;
|
||||
// If no filename was provided, don't read UWUW materials
|
||||
if (filename_ == "")
|
||||
return;
|
||||
|
||||
uwuw_ = std::make_shared<UWUW>(filename_.c_str());
|
||||
const auto& mat_lib = uwuw_->material_library;
|
||||
if (mat_lib.size() == 0)
|
||||
|
||||
if (!uses_uwuw())
|
||||
return;
|
||||
|
||||
// Notify user if UWUW materials are going to be used
|
||||
write_message("Found UWUW Materials in the DAGMC geometry file.", 6);
|
||||
|
||||
// if we're using automatic IDs, update the UWUW material metadata
|
||||
if (adjust_material_ids_) {
|
||||
int32_t next_material_id = 0;
|
||||
for (const auto& m : model::materials) {
|
||||
next_material_id = std::max(m->id_, next_material_id);
|
||||
}
|
||||
next_material_id++;
|
||||
|
||||
for (auto& mat : uwuw_->material_library) {
|
||||
mat.second->metadata["mat_number"] = next_material_id++;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "<?xml version=\"1.0\"?>\n";
|
||||
ss << "<materials>\n";
|
||||
for (auto mat : mat_lib) {
|
||||
ss << mat.second->openmc("atom");
|
||||
}
|
||||
ss << "</materials>";
|
||||
std::string mat_xml_string = ss.str();
|
||||
std::string mat_xml_string = get_uwuw_materials_xml();
|
||||
|
||||
// create a pugi XML document from this string
|
||||
pugi::xml_document doc;
|
||||
|
|
|
|||
|
|
@ -132,15 +132,15 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node)
|
|||
r_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read distribution for theta-coordinate
|
||||
if (check_for_node(node, "theta")) {
|
||||
pugi::xml_node node_dist = node.child("theta");
|
||||
theta_ = distribution_from_xml(node_dist);
|
||||
// Read distribution for cos_theta-coordinate
|
||||
if (check_for_node(node, "cos_theta")) {
|
||||
pugi::xml_node node_dist = node.child("cos_theta");
|
||||
cos_theta_ = distribution_from_xml(node_dist);
|
||||
} else {
|
||||
// If no distribution was specified, default to a single point at theta=0
|
||||
// If no distribution was specified, default to a single point at cos_theta=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
theta_ = make_unique<Discrete>(x, p, 1);
|
||||
cos_theta_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read distribution for phi-coordinate
|
||||
|
|
@ -171,11 +171,12 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node)
|
|||
Position SphericalIndependent::sample(uint64_t* seed) const
|
||||
{
|
||||
double r = r_->sample(seed);
|
||||
double theta = theta_->sample(seed);
|
||||
double cos_theta = cos_theta_->sample(seed);
|
||||
double phi = phi_->sample(seed);
|
||||
double x = r * sin(theta) * cos(phi) + origin_.x;
|
||||
double y = r * sin(theta) * sin(phi) + origin_.y;
|
||||
double z = r * cos(theta) + origin_.z;
|
||||
// sin(theta) by sin**2 + cos**2 = 1
|
||||
double x = r * std::sqrt(1 - cos_theta * cos_theta) * cos(phi) + origin_.x;
|
||||
double y = r * std::sqrt(1 - cos_theta * cos_theta) * sin(phi) + origin_.y;
|
||||
double z = r * cos_theta + origin_.z;
|
||||
return {x, y, z};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ int openmc_finalize()
|
|||
settings::material_cell_offsets = true;
|
||||
settings::max_particles_in_flight = 100000;
|
||||
settings::max_splits = 1000;
|
||||
settings::max_tracks = 1000;
|
||||
settings::n_inactive = 0;
|
||||
settings::n_particles = -1;
|
||||
settings::output_summary = true;
|
||||
|
|
|
|||
|
|
@ -318,7 +318,8 @@ void print_usage()
|
|||
" -r, --restart Restart a previous run from a state point\n"
|
||||
" or a particle restart file\n"
|
||||
" -s, --threads Number of OpenMP threads\n"
|
||||
" -t, --track Write tracks for all particles\n"
|
||||
" -t, --track Write tracks for all particles (up to "
|
||||
"max_tracks)\n"
|
||||
" -e, --event Run using event-based parallelism\n"
|
||||
" -v, --version Show version information\n"
|
||||
" -h, --help Show this message\n");
|
||||
|
|
|
|||
|
|
@ -337,6 +337,11 @@ void Particle::event_revive_from_secondary()
|
|||
|
||||
// Check for secondary particles if this particle is dead
|
||||
if (!alive()) {
|
||||
// Write final position for this particle
|
||||
if (write_track()) {
|
||||
write_particle_track(*this);
|
||||
}
|
||||
|
||||
// If no secondary particles, break out of event loop
|
||||
if (secondary_bank().empty())
|
||||
return;
|
||||
|
|
@ -359,7 +364,6 @@ void Particle::event_death()
|
|||
|
||||
// Finish particle track output.
|
||||
if (write_track()) {
|
||||
write_particle_track(*this);
|
||||
finalize_particle_track(*this);
|
||||
}
|
||||
|
||||
|
|
@ -454,8 +458,7 @@ void Particle::cross_surface()
|
|||
// ==========================================================================
|
||||
// COULDN'T FIND PARTICLE IN NEIGHBORING CELLS, SEARCH ALL CELLS
|
||||
|
||||
// Remove lower coordinate levels and assignment of surface
|
||||
surface() = 0;
|
||||
// Remove lower coordinate levels
|
||||
n_coord() = 1;
|
||||
bool found = exhaustive_find_cell(*this);
|
||||
|
||||
|
|
@ -465,6 +468,7 @@ void Particle::cross_surface()
|
|||
// the particle is really traveling tangent to a surface, if we move it
|
||||
// forward a tiny bit it should fix the problem.
|
||||
|
||||
surface() = 0;
|
||||
n_coord() = 1;
|
||||
r() += TINY_BIT * u();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "openmc/particle_data.h"
|
||||
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/geometry.h"
|
||||
#include "openmc/material.h"
|
||||
#include "openmc/nuclide.h"
|
||||
#include "openmc/photon.h"
|
||||
#include "openmc/settings.h"
|
||||
|
|
@ -53,4 +55,20 @@ ParticleData::ParticleData()
|
|||
photon_xs_.resize(data::elements.size());
|
||||
}
|
||||
|
||||
TrackState ParticleData::get_track_state() const
|
||||
{
|
||||
TrackState state;
|
||||
state.r = this->r();
|
||||
state.u = this->u();
|
||||
state.E = this->E();
|
||||
state.time = this->time();
|
||||
state.wgt = this->wgt();
|
||||
state.cell_id = model::cells[this->lowest_coord().cell]->id_;
|
||||
state.cell_instance = this->cell_instance();
|
||||
if (this->material() != MATERIAL_VOID) {
|
||||
state.material_id = model::materials[material()]->id_;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ int n_log_bins {8000};
|
|||
int n_batches;
|
||||
int n_max_batches;
|
||||
int max_splits {1000};
|
||||
int max_tracks {1000};
|
||||
ResScatMethod res_scat_method {ResScatMethod::rvs};
|
||||
double res_scat_energy_min {0.01};
|
||||
double res_scat_energy_max {1000.0};
|
||||
|
|
@ -802,6 +803,12 @@ void read_settings_xml()
|
|||
}
|
||||
if (check_for_node(root, "temperature_multipole")) {
|
||||
temperature_multipole = get_node_value_bool(root, "temperature_multipole");
|
||||
|
||||
// Multipole currently doesn't work with photon transport
|
||||
if (temperature_multipole && photon_transport) {
|
||||
fatal_error("Multipole data cannot currently be used in conjunction with "
|
||||
"photon transport.");
|
||||
}
|
||||
}
|
||||
if (check_for_node(root, "temperature_range")) {
|
||||
auto range = get_node_array<double>(root, "temperature_range");
|
||||
|
|
@ -871,6 +878,10 @@ void read_settings_xml()
|
|||
if (check_for_node(root, "max_splits")) {
|
||||
settings::max_splits = std::stoi(get_node_value(root, "max_splits"));
|
||||
}
|
||||
|
||||
if (check_for_node(root, "max_tracks")) {
|
||||
settings::max_tracks = std::stoi(get_node_value(root, "max_tracks"));
|
||||
}
|
||||
}
|
||||
|
||||
void free_memory_settings()
|
||||
|
|
|
|||
|
|
@ -82,6 +82,11 @@ int openmc_simulation_init()
|
|||
// Allocate source, fission and surface source banks.
|
||||
allocate_banks();
|
||||
|
||||
// Create track file if needed
|
||||
if (!settings::track_identifiers.empty() || settings::write_all_tracks) {
|
||||
open_track_file();
|
||||
}
|
||||
|
||||
// If doing an event-based simulation, intialize the particle buffer
|
||||
// and event queues
|
||||
if (settings::event_based) {
|
||||
|
|
@ -152,6 +157,11 @@ int openmc_simulation_finalize()
|
|||
mat->mat_nuclide_index_.clear();
|
||||
}
|
||||
|
||||
// Close track file if open
|
||||
if (!settings::track_identifiers.empty() || settings::write_all_tracks) {
|
||||
close_track_file();
|
||||
}
|
||||
|
||||
// Increment total number of generations
|
||||
simulation::total_gen += simulation::current_batch * settings::gen_per_batch;
|
||||
|
||||
|
|
@ -507,18 +517,7 @@ void initialize_history(Particle& p, int64_t index_source)
|
|||
p.trace() = true;
|
||||
|
||||
// Set particle track.
|
||||
p.write_track() = false;
|
||||
if (settings::write_all_tracks) {
|
||||
p.write_track() = true;
|
||||
} else if (settings::track_identifiers.size() > 0) {
|
||||
for (const auto& t : settings::track_identifiers) {
|
||||
if (simulation::current_batch == t[0] &&
|
||||
simulation::current_gen == t[1] && p.id() == t[2]) {
|
||||
p.write_track() = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
p.write_track() = check_track_criteria(p);
|
||||
|
||||
// Display message if high verbosity or trace is on
|
||||
if (settings::verbosity >= 9 || p.trace()) {
|
||||
|
|
|
|||
|
|
@ -963,18 +963,23 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index,
|
|||
score = score_neutron_heating(
|
||||
p, tally, flux, HEATING, i_nuclide, atom_density);
|
||||
} else {
|
||||
// The energy deposited is the difference between the pre-collision and
|
||||
// post-collision energy...
|
||||
score = E - p.E();
|
||||
if (i_nuclide == -1 || i_nuclide == p.event_nuclide()) {
|
||||
// The energy deposited is the difference between the pre-collision
|
||||
// and post-collision energy...
|
||||
score = E - p.E();
|
||||
|
||||
// ...less the energy of any secondary particles since they will be
|
||||
// transported individually later
|
||||
const auto& bank = p.secondary_bank();
|
||||
for (auto it = bank.end() - p.n_bank_second(); it < bank.end(); ++it) {
|
||||
score -= it->E;
|
||||
// ...less the energy of any secondary particles since they will be
|
||||
// transported individually later
|
||||
const auto& bank = p.secondary_bank();
|
||||
for (auto it = bank.end() - p.n_bank_second(); it < bank.end();
|
||||
++it) {
|
||||
score -= it->E;
|
||||
}
|
||||
|
||||
score *= p.wgt_last();
|
||||
} else {
|
||||
score = 0.0;
|
||||
}
|
||||
|
||||
score *= p.wgt_last();
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/position.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/simulation.h"
|
||||
|
|
@ -9,6 +10,7 @@
|
|||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include <fmt/core.h>
|
||||
#include <hdf5.h>
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <string>
|
||||
|
|
@ -19,6 +21,10 @@ namespace openmc {
|
|||
// Global variables
|
||||
//==============================================================================
|
||||
|
||||
hid_t track_file; //! HDF5 identifier for track file
|
||||
hid_t track_dtype; //! HDF5 identifier for track datatype
|
||||
int n_tracks_written; //! Number of tracks written
|
||||
|
||||
//==============================================================================
|
||||
// Non-member functions
|
||||
//==============================================================================
|
||||
|
|
@ -26,45 +32,123 @@ namespace openmc {
|
|||
void add_particle_track(Particle& p)
|
||||
{
|
||||
p.tracks().emplace_back();
|
||||
p.tracks().back().particle = p.type();
|
||||
}
|
||||
|
||||
void write_particle_track(Particle& p)
|
||||
{
|
||||
p.tracks().back().push_back(p.r());
|
||||
p.tracks().back().states.push_back(p.get_track_state());
|
||||
}
|
||||
|
||||
void open_track_file()
|
||||
{
|
||||
// Open file and write filetype/version -- when MPI is enabled and there is
|
||||
// more than one rank, each rank writes its own file
|
||||
#ifdef OPENMC_MPI
|
||||
std::string filename;
|
||||
if (mpi::n_procs > 1) {
|
||||
filename = fmt::format("{}tracks_p{}.h5", settings::path_output, mpi::rank);
|
||||
} else {
|
||||
filename = fmt::format("{}tracks.h5", settings::path_output);
|
||||
}
|
||||
#else
|
||||
std::string filename = fmt::format("{}tracks.h5", settings::path_output);
|
||||
#endif
|
||||
track_file = file_open(filename, 'w');
|
||||
write_attribute(track_file, "filetype", "track");
|
||||
write_attribute(track_file, "version", VERSION_TRACK);
|
||||
|
||||
// Create compound type for Position
|
||||
hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(struct Position));
|
||||
H5Tinsert(postype, "x", HOFFSET(Position, x), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(postype, "y", HOFFSET(Position, y), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE);
|
||||
|
||||
// Create compound type for TrackState
|
||||
track_dtype = H5Tcreate(H5T_COMPOUND, sizeof(struct TrackState));
|
||||
H5Tinsert(track_dtype, "r", HOFFSET(TrackState, r), postype);
|
||||
H5Tinsert(track_dtype, "u", HOFFSET(TrackState, u), postype);
|
||||
H5Tinsert(track_dtype, "E", HOFFSET(TrackState, E), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(track_dtype, "time", HOFFSET(TrackState, time), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(track_dtype, "wgt", HOFFSET(TrackState, wgt), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(
|
||||
track_dtype, "cell_id", HOFFSET(TrackState, cell_id), H5T_NATIVE_INT);
|
||||
H5Tinsert(track_dtype, "cell_instance", HOFFSET(TrackState, cell_instance),
|
||||
H5T_NATIVE_INT);
|
||||
H5Tinsert(track_dtype, "material_id", HOFFSET(TrackState, material_id),
|
||||
H5T_NATIVE_INT);
|
||||
H5Tclose(postype);
|
||||
}
|
||||
|
||||
void close_track_file()
|
||||
{
|
||||
H5Tclose(track_dtype);
|
||||
file_close(track_file);
|
||||
|
||||
// Reset number of tracks written
|
||||
n_tracks_written = 0;
|
||||
}
|
||||
|
||||
bool check_track_criteria(const Particle& p)
|
||||
{
|
||||
if (settings::write_all_tracks) {
|
||||
// Increment number of tracks written and get previous value
|
||||
int n;
|
||||
#pragma omp atomic capture
|
||||
n = n_tracks_written++;
|
||||
|
||||
// Indicate that track should be written for this particle
|
||||
return n < settings::max_tracks;
|
||||
}
|
||||
|
||||
// Check for match from explicit track identifiers
|
||||
if (settings::track_identifiers.size() > 0) {
|
||||
for (const auto& t : settings::track_identifiers) {
|
||||
if (simulation::current_batch == t[0] &&
|
||||
simulation::current_gen == t[1] && p.id() == t[2]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void finalize_particle_track(Particle& p)
|
||||
{
|
||||
std::string filename =
|
||||
fmt::format("{}track_{}_{}_{}.h5", settings::path_output,
|
||||
simulation::current_batch, simulation::current_gen, p.id());
|
||||
|
||||
// Determine number of coordinates for each particle
|
||||
vector<int> n_coords;
|
||||
for (auto& coords : p.tracks()) {
|
||||
n_coords.push_back(coords.size());
|
||||
vector<int> offsets;
|
||||
vector<int> particles;
|
||||
vector<TrackState> tracks;
|
||||
int offset = 0;
|
||||
for (auto& track_i : p.tracks()) {
|
||||
offsets.push_back(offset);
|
||||
particles.push_back(static_cast<int>(track_i.particle));
|
||||
offset += track_i.states.size();
|
||||
tracks.insert(tracks.end(), track_i.states.begin(), track_i.states.end());
|
||||
}
|
||||
offsets.push_back(offset);
|
||||
|
||||
#pragma omp critical(FinalizeParticleTrack)
|
||||
{
|
||||
hid_t file_id = file_open(filename, 'w');
|
||||
write_attribute(file_id, "filetype", "track");
|
||||
write_attribute(file_id, "version", VERSION_TRACK);
|
||||
write_attribute(file_id, "n_particles", p.tracks().size());
|
||||
write_attribute(file_id, "n_coords", n_coords);
|
||||
for (auto i = 1; i <= p.tracks().size(); ++i) {
|
||||
const auto& t {p.tracks()[i - 1]};
|
||||
size_t n = t.size();
|
||||
xt::xtensor<double, 2> data({n, 3});
|
||||
for (int j = 0; j < n; ++j) {
|
||||
data(j, 0) = t[j].x;
|
||||
data(j, 1) = t[j].y;
|
||||
data(j, 2) = t[j].z;
|
||||
}
|
||||
std::string name = fmt::format("coordinates_{}", i);
|
||||
write_dataset(file_id, name.c_str(), data);
|
||||
}
|
||||
file_close(file_id);
|
||||
// Create name for dataset
|
||||
std::string dset_name = fmt::format("track_{}_{}_{}",
|
||||
simulation::current_batch, simulation::current_gen, p.id());
|
||||
|
||||
// Write array of TrackState to file
|
||||
hsize_t dims[] {static_cast<hsize_t>(tracks.size())};
|
||||
hid_t dspace = H5Screate_simple(1, dims, nullptr);
|
||||
hid_t dset = H5Dcreate(track_file, dset_name.c_str(), track_dtype, dspace,
|
||||
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
||||
H5Dwrite(dset, track_dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, tracks.data());
|
||||
|
||||
// Write attributes
|
||||
write_attribute(dset, "n_particles", p.tracks().size());
|
||||
write_attribute(dset, "offsets", offsets);
|
||||
write_attribute(dset, "particles", particles);
|
||||
|
||||
// Free resources
|
||||
H5Dclose(dset);
|
||||
H5Sclose(dspace);
|
||||
}
|
||||
|
||||
// Clear particle tracks
|
||||
|
|
|
|||
0
tests/regression_tests/dagmc/external/__init__.py
vendored
Normal file
0
tests/regression_tests/dagmc/external/__init__.py
vendored
Normal file
1
tests/regression_tests/dagmc/external/dagmc.h5m
vendored
Symbolic link
1
tests/regression_tests/dagmc/external/dagmc.h5m
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../legacy/dagmc.h5m
|
||||
40
tests/regression_tests/dagmc/external/inputs_true.dat
vendored
Normal file
40
tests/regression_tests/dagmc/external/inputs_true.dat
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<geometry>
|
||||
<dagmc_universe filename="dagmc.h5m" id="1" />
|
||||
</geometry>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<materials>
|
||||
<material depletable="true" id="40" name="no-void fuel">
|
||||
<density units="g/cc" value="11" />
|
||||
<nuclide ao="1.0" name="U235" />
|
||||
</material>
|
||||
<material id="41" name="water">
|
||||
<density units="g/cc" value="1.0" />
|
||||
<nuclide ao="2.0" name="H1" />
|
||||
<nuclide ao="1.0" name="O16" />
|
||||
<sab name="c_H_in_H2O" />
|
||||
</material>
|
||||
</materials>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<settings>
|
||||
<run_mode>eigenvalue</run_mode>
|
||||
<particles>100</particles>
|
||||
<batches>5</batches>
|
||||
<inactive>0</inactive>
|
||||
<source strength="1.0">
|
||||
<space type="box">
|
||||
<parameters>-4 -4 -4 4 4 4</parameters>
|
||||
</space>
|
||||
</source>
|
||||
<temperature_default>293</temperature_default>
|
||||
</settings>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<tallies>
|
||||
<filter id="1" type="cell">
|
||||
<bins>1</bins>
|
||||
</filter>
|
||||
<tally id="1">
|
||||
<filters>1</filters>
|
||||
<scores>total</scores>
|
||||
</tally>
|
||||
</tallies>
|
||||
94
tests/regression_tests/dagmc/external/main.cpp
vendored
Normal file
94
tests/regression_tests/dagmc/external/main.cpp
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#include "openmc/capi.h"
|
||||
#include "openmc/cross_sections.h"
|
||||
#include "openmc/dagmc.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/geometry.h"
|
||||
#include "openmc/geometry_aux.h"
|
||||
#include "openmc/material.h"
|
||||
#include "openmc/nuclide.h"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
using namespace openmc;
|
||||
int openmc_err;
|
||||
|
||||
// Initialise OpenMC
|
||||
openmc_err = openmc_init(argc, argv, nullptr);
|
||||
if (openmc_err == -1) {
|
||||
// This happens for the -h and -v flags
|
||||
return EXIT_SUCCESS;
|
||||
} else if (openmc_err) {
|
||||
fatal_error(openmc_err_msg);
|
||||
}
|
||||
|
||||
// Create DAGMC ptr
|
||||
std::string filename = "dagmc.h5m";
|
||||
std::shared_ptr<moab::DagMC> dag_ptr = std::make_shared<moab::DagMC>();
|
||||
moab::ErrorCode rval = dag_ptr->load_file(filename.c_str());
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
fatal_error("Failed to load file");
|
||||
}
|
||||
|
||||
// Initialize acceleration data structures
|
||||
rval = dag_ptr->init_OBBTree();
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
fatal_error("Failed to initialise OBB tree");
|
||||
}
|
||||
|
||||
// Get rid of existing geometry
|
||||
std::unordered_map<std::string, int> nuclide_map_copy =
|
||||
openmc::data::nuclide_map;
|
||||
openmc::data::nuclides.clear();
|
||||
openmc::data::nuclide_map = nuclide_map_copy;
|
||||
openmc::model::surfaces.clear();
|
||||
openmc::model::surface_map.clear();
|
||||
openmc::model::cells.clear();
|
||||
openmc::model::cell_map.clear();
|
||||
openmc::model::universes.clear();
|
||||
openmc::model::universe_map.clear();
|
||||
|
||||
// Update materials (emulate an external program)
|
||||
for (auto& mat_ptr : openmc::model::materials) {
|
||||
mat_ptr->set_temperature(300);
|
||||
}
|
||||
|
||||
// Create new DAGMC universe
|
||||
openmc::model::universes.push_back(
|
||||
std::make_unique<openmc::DAGUniverse>(dag_ptr));
|
||||
model::universe_map[model::universes.back()->id_] =
|
||||
model::universes.size() - 1;
|
||||
|
||||
// Add cells to universes
|
||||
openmc::populate_universes();
|
||||
|
||||
// Set root universe
|
||||
openmc::model::root_universe = openmc::find_root_universe();
|
||||
openmc::check_dagmc_root_univ();
|
||||
|
||||
// Final geometry setup and assign temperatures
|
||||
openmc::finalize_geometry();
|
||||
|
||||
// Finalize cross sections having assigned temperatures
|
||||
openmc::finalize_cross_sections();
|
||||
|
||||
// Check that we correctly assigned cell temperatures with non-void fill
|
||||
for (auto& cell_ptr : openmc::model::cells) {
|
||||
if (cell_ptr->material_.front() != openmc::C_NONE &&
|
||||
cell_ptr->temperature() != 300) {
|
||||
fatal_error("Failed to set cell temperature");
|
||||
}
|
||||
}
|
||||
|
||||
// Run OpenMC
|
||||
openmc_err = openmc_run();
|
||||
if (openmc_err)
|
||||
fatal_error(openmc_err_msg);
|
||||
|
||||
// Deallocate memory
|
||||
openmc_err = openmc_finalize();
|
||||
if (openmc_err)
|
||||
fatal_error(openmc_err_msg);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
5
tests/regression_tests/dagmc/external/results_true.dat
vendored
Normal file
5
tests/regression_tests/dagmc/external/results_true.dat
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
k-combined:
|
||||
8.426936E-01 5.715847E-02
|
||||
tally 1:
|
||||
8.093843E+00
|
||||
1.328829E+01
|
||||
128
tests/regression_tests/dagmc/external/test.py
vendored
Normal file
128
tests/regression_tests/dagmc/external/test.py
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
from pathlib import Path
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import textwrap
|
||||
|
||||
import openmc
|
||||
import openmc.lib
|
||||
import pytest
|
||||
|
||||
from tests.regression_tests import config
|
||||
from tests.testing_harness import PyAPITestHarness
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
not openmc.lib._dagmc_enabled(),
|
||||
reason="DAGMC is not enabled.")
|
||||
|
||||
# Test that an external DAGMC instance can be passed in through the C API
|
||||
|
||||
@pytest.fixture
|
||||
def cpp_driver(request):
|
||||
"""Compile the external source"""
|
||||
|
||||
# Get build directory and write CMakeLists.txt file
|
||||
openmc_dir = Path(str(request.config.rootdir)) / 'build'
|
||||
with open('CMakeLists.txt', 'w') as f:
|
||||
f.write(textwrap.dedent("""
|
||||
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
|
||||
project(openmc_cpp_driver CXX)
|
||||
add_executable(main main.cpp)
|
||||
find_package(OpenMC REQUIRED HINTS {})
|
||||
target_link_libraries(main OpenMC::libopenmc)
|
||||
target_compile_features(main PUBLIC cxx_std_14)
|
||||
set(CMAKE_CXX_FLAGS "-pedantic-errors")
|
||||
add_compile_definitions(DAGMC=1)
|
||||
""".format(openmc_dir)))
|
||||
|
||||
# Create temporary build directory and change to there
|
||||
local_builddir = Path('build')
|
||||
local_builddir.mkdir(exist_ok=True)
|
||||
os.chdir(local_builddir)
|
||||
|
||||
mpi_arg = "On" if config['mpi'] else "Off"
|
||||
|
||||
try:
|
||||
# Run cmake/make to build the shared libary
|
||||
subprocess.run(['cmake', os.path.pardir, f'-DOPENMC_USE_MPI={mpi_arg}'], check=True)
|
||||
subprocess.run(['make'], check=True)
|
||||
os.chdir(os.path.pardir)
|
||||
|
||||
yield "./build/main"
|
||||
|
||||
finally:
|
||||
# Remove local build directory when test is complete
|
||||
shutil.rmtree('build')
|
||||
os.remove('CMakeLists.txt')
|
||||
|
||||
@pytest.fixture
|
||||
def model():
|
||||
model = openmc.model.Model()
|
||||
|
||||
# Settings
|
||||
model.settings.batches = 5
|
||||
model.settings.inactive = 0
|
||||
model.settings.particles = 100
|
||||
source_box = openmc.stats.Box([-4, -4, -4],
|
||||
[ 4, 4, 4])
|
||||
source = openmc.Source(space=source_box)
|
||||
model.settings.source = source
|
||||
model.settings.temperature['default'] = 293
|
||||
|
||||
# Geometry
|
||||
dag_univ = openmc.DAGMCUniverse("dagmc.h5m")
|
||||
model.geometry = openmc.Geometry(dag_univ)
|
||||
|
||||
# Tallies
|
||||
tally = openmc.Tally()
|
||||
tally.scores = ['total']
|
||||
tally.filters = [openmc.CellFilter(1)]
|
||||
model.tallies = [tally]
|
||||
|
||||
# Materials
|
||||
u235 = openmc.Material(name="no-void fuel")
|
||||
u235.add_nuclide('U235', 1.0, 'ao')
|
||||
u235.set_density('g/cc', 11)
|
||||
u235.id = 40
|
||||
water = openmc.Material(name="water")
|
||||
water.add_nuclide('H1', 2.0, 'ao')
|
||||
water.add_nuclide('O16', 1.0, 'ao')
|
||||
water.set_density('g/cc', 1.0)
|
||||
water.add_s_alpha_beta('c_H_in_H2O')
|
||||
water.id = 41
|
||||
mats = openmc.Materials([u235, water])
|
||||
model.materials = mats
|
||||
|
||||
return model
|
||||
|
||||
class ExternalDAGMCTest(PyAPITestHarness):
|
||||
def __init__(self, executable, statepoint_name, model):
|
||||
super().__init__(statepoint_name, model)
|
||||
self.executable = executable
|
||||
|
||||
def _run_openmc(self):
|
||||
"""
|
||||
Just test if results generated with the external C++ API are
|
||||
self-consistent with the internal python API.
|
||||
We generate the "truth" results with the python API but
|
||||
the main test produces the results file by running the
|
||||
executable compiled from main.cpp. This future-proofs
|
||||
the test - we only care that the two routes are equivalent.
|
||||
"""
|
||||
if config['update']:
|
||||
# Generate the results file with internal python API
|
||||
openmc.run(openmc_exec=config['exe'], event_based=config['event'])
|
||||
elif config['mpi']:
|
||||
mpi_args = [config['mpiexec'], '-n', config['mpi_np']]
|
||||
# Run main cpp executable with MPI
|
||||
openmc.run(openmc_exec=self.executable,
|
||||
mpi_args=mpi_args,
|
||||
event_based=config['event'])
|
||||
else:
|
||||
# Run main cpp executable
|
||||
openmc.run(openmc_exec=self.executable,
|
||||
event_based=config['event'])
|
||||
|
||||
def test_external_dagmc(cpp_driver, model):
|
||||
harness = ExternalDAGMCTest(cpp_driver, 'statepoint.5.h5', model)
|
||||
harness.main()
|
||||
|
|
@ -67,8 +67,8 @@ tally 3:
|
|||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
1.764573E+05
|
||||
3.113718E+10
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
|
|
@ -79,8 +79,8 @@ tally 3:
|
|||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
7.691658E+03
|
||||
5.916160E+07
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@
|
|||
<source strength="0.1">
|
||||
<space origin="1.0 1.0 0.0" type="spherical">
|
||||
<r parameters="2.0 3.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.7853981633974483 1.5707963267948966 2.356194490192345 0.3 0.4 0.3</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3</parameters>
|
||||
</cos_theta>
|
||||
<phi parameters="0.0 6.283185307179586" type="uniform" />
|
||||
</space>
|
||||
<angle type="isotropic" />
|
||||
|
|
@ -102,9 +102,9 @@
|
|||
<source strength="0.1">
|
||||
<space origin="1.0 1.0 0.0" type="spherical">
|
||||
<r parameters="2.0 3.0 2.0" type="powerlaw" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.7853981633974483 1.5707963267948966 2.356194490192345 0.3 0.4 0.3</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>0.7071067811865476 0.0 -0.7071067811865475 0.3 0.4 0.3</parameters>
|
||||
</cos_theta>
|
||||
<phi parameters="0.0 6.283185307179586" type="uniform" />
|
||||
</space>
|
||||
<angle type="isotropic" />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from math import pi
|
||||
from math import pi, cos
|
||||
|
||||
import numpy as np
|
||||
import openmc
|
||||
|
|
@ -32,19 +32,19 @@ class SourceTestHarness(PyAPITestHarness):
|
|||
r_dist = openmc.stats.Uniform(2., 3.)
|
||||
r_dist1 = openmc.stats.PowerLaw(2., 3., 1.)
|
||||
r_dist2 = openmc.stats.PowerLaw(2., 3., 2.)
|
||||
theta_dist = openmc.stats.Discrete([pi/4, pi/2, 3*pi/4],
|
||||
[0.3, 0.4, 0.3])
|
||||
cos_theta_dist = openmc.stats.Discrete([cos(pi/4), 0.0, cos(3*pi/4)],
|
||||
[0.3, 0.4, 0.3])
|
||||
phi_dist = openmc.stats.Uniform(0.0, 2*pi)
|
||||
spatial1 = openmc.stats.CartesianIndependent(x_dist, y_dist, z_dist)
|
||||
spatial2 = openmc.stats.Box([-4., -4., -4.], [4., 4., 4.])
|
||||
spatial3 = openmc.stats.Point([1.2, -2.3, 0.781])
|
||||
spatial4 = openmc.stats.SphericalIndependent(r_dist, theta_dist,
|
||||
spatial4 = openmc.stats.SphericalIndependent(r_dist, cos_theta_dist,
|
||||
phi_dist,
|
||||
origin=(1., 1., 0.))
|
||||
spatial5 = openmc.stats.CylindricalIndependent(r_dist, phi_dist,
|
||||
z_dist,
|
||||
origin=(1., 1., 0.))
|
||||
spatial6 = openmc.stats.SphericalIndependent(r_dist2, theta_dist,
|
||||
spatial6 = openmc.stats.SphericalIndependent(r_dist2, cos_theta_dist,
|
||||
phi_dist,
|
||||
origin=(1., 1., 0.))
|
||||
spatial7 = openmc.stats.CylindricalIndependent(r_dist1, phi_dist,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,266 @@
|
|||
<?xml version="1.0"?>
|
||||
<VTKFile type="PPolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
|
||||
<PPolyData GhostLevel="0">
|
||||
<PPoints>
|
||||
<PDataArray type="Float32" Name="Points" NumberOfComponents="3"/>
|
||||
</PPoints>
|
||||
<Piece Source="poly_0.vtp"/>
|
||||
</PPolyData>
|
||||
</VTKFile>
|
||||
ParticleType.NEUTRON [((-9.663085e-01, -6.616522e-01, -9.863690e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 0.000000e+00, 1.000000e+00, 23, 2403, 1)
|
||||
((-1.281491e+00, -4.879529e-01, -7.708709e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.323629e-10, 1.000000e+00, 22, 2403, 3)
|
||||
((-1.368452e+00, -4.400285e-01, -7.114141e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 1.688824e-10, 1.000000e+00, 21, 2403, 2)
|
||||
((-2.150539e+00, -9.015151e-03, -1.766823e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 4.973246e-10, 1.000000e+00, 22, 2403, 3)
|
||||
((-2.237499e+00, 3.890922e-02, -1.172255e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 5.338441e-10, 1.000000e+00, 23, 2403, 1)
|
||||
((-2.453640e+00, 1.580257e-01, 3.055504e-02), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 6.246136e-10, 1.000000e+00, 23, 2402, 1)
|
||||
((-2.767485e+00, 3.309877e-01, 2.451383e-01), (-7.513921e-01, 4.140970e-01, 5.137447e-01), 5.293873e+06, 7.564146e-10, 1.000000e+00, 22, 2402, 3)
|
||||
((-2.825099e+00, 3.627392e-01, 2.845305e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 7.806100e-10, 1.000000e+00, 22, 2402, 3)
|
||||
((-3.274427e+00, 6.029890e-01, 6.987901e-01), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 9.878481e-10, 1.000000e+00, 23, 2402, 1)
|
||||
((-3.676327e+00, 8.178800e-01, 1.069324e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.173212e-09, 1.000000e+00, 23, 2416, 1)
|
||||
((-4.089400e+00, 1.038745e+00, 1.450158e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.363728e-09, 1.000000e+00, 23, 2415, 1)
|
||||
((-4.456639e+00, 1.235102e+00, 1.788735e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.533105e-09, 1.000000e+00, 22, 2415, 3)
|
||||
((-4.536974e+00, 1.278056e+00, 1.862800e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.570157e-09, 1.000000e+00, 21, 2415, 2)
|
||||
((-5.410401e+00, 1.745067e+00, 2.668060e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 1.972998e-09, 1.000000e+00, 22, 2415, 3)
|
||||
((-5.490736e+00, 1.788021e+00, 2.742125e+00), (-6.842434e-01, 3.658561e-01, 6.308409e-01), 5.292729e+06, 2.010050e-09, 1.000000e+00, 23, 2415, 1)
|
||||
((-5.576301e+00, 1.833771e+00, 2.821012e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.049514e-09, 1.000000e+00, 23, 2415, 1)
|
||||
((-5.725160e+00, 1.896661e+00, 2.330311e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.227030e-09, 1.000000e+00, 23, 2414, 1)
|
||||
((-6.116514e+00, 2.061999e+00, 1.040248e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 2.693724e-09, 1.000000e+00, 22, 2414, 3)
|
||||
((-6.534762e+00, 2.238699e+00, -3.384686e-01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.192489e-09, 1.000000e+00, 23, 2414, 1)
|
||||
((-7.043525e+00, 2.453640e+00, -2.015560e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 3.799195e-09, 1.000000e+00, 23, 2428, 1)
|
||||
((-7.360920e+00, 2.587732e+00, -3.061825e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 4.177692e-09, 1.000000e+00, 11, 1757, 1)
|
||||
((-8.996680e+00, 3.278803e+00, -8.453960e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.128354e-09, 1.000000e+00, 23, 2427, 1)
|
||||
((-9.220205e+00, 3.373238e+00, -9.190791e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.394910e-09, 1.000000e+00, 22, 2427, 3)
|
||||
((-9.320244e+00, 3.415502e+00, -9.520561e+00), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 6.514208e-09, 1.000000e+00, 21, 2427, 2)
|
||||
((-1.005591e+01, 3.726304e+00, -1.194562e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.391498e-09, 1.000000e+00, 22, 2427, 3)
|
||||
((-1.015595e+01, 3.768569e+00, -1.227539e+01), (-2.881377e-01, 1.217316e-01, -9.498200e-01), 4.458753e+06, 7.510796e-09, 1.000000e+00, 23, 2427, 1)
|
||||
((-1.062054e+01, 3.964848e+00, -1.380687e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.064826e-09, 1.000000e+00, 23, 2427, 1)
|
||||
((-1.063244e+01, 3.969501e+00, -1.382484e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.072756e-09, 1.000000e+00, 23, 2426, 1)
|
||||
((-1.093907e+01, 4.089400e+00, -1.428802e+01), (-5.395885e-01, 2.109921e-01, -8.150623e-01), 4.068754e+06, 8.277097e-09, 1.000000e+00, 23, 2437, 1)
|
||||
((-1.108410e+01, 4.146112e+00, -1.450710e+01), (4.855193e-01, 3.316053e-01, -8.088937e-01), 8.856868e+05, 8.373750e-09, 1.000000e+00, 23, 2437, 1)
|
||||
((-1.080173e+01, 4.338973e+00, -1.497755e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 8.820862e-09, 1.000000e+00, 23, 2437, 1)
|
||||
((-1.063244e+01, 4.371524e+00, -1.555290e+01), (2.818553e-01, 5.419536e-02, -9.579251e-01), 7.653670e+05, 9.317522e-09, 1.000000e+00, 23, 2438, 1)
|
||||
((-1.041266e+01, 4.413783e+00, -1.629984e+01), (2.686183e-01, -3.269476e-01, -9.060626e-01), 6.562001e+05, 9.962308e-09, 1.000000e+00, 23, 2438, 1)
|
||||
((-1.016754e+01, 4.115428e+00, -1.712667e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.077718e-08, 1.000000e+00, 23, 2438, 1)
|
||||
((-1.019064e+01, 4.089400e+00, -1.713747e+01), (-6.340850e-01, -7.142137e-01, -2.963697e-01), 7.155058e+04, 1.087569e-08, 1.000000e+00, 23, 2427, 1)
|
||||
((-1.024915e+01, 4.023496e+00, -1.716481e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.112511e-08, 1.000000e+00, 23, 2427, 1)
|
||||
((-1.018199e+01, 3.749638e+00, -1.740047e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.276389e-08, 1.000000e+00, 22, 2427, 3)
|
||||
((-1.015866e+01, 3.654498e+00, -1.748234e+01), (1.827568e-01, -7.452255e-01, -6.412791e-01), 2.628504e+04, 1.333321e-08, 1.000000e+00, 21, 2427, 2)
|
||||
((-1.009978e+01, 3.414404e+00, -1.768895e+01), (1.735861e-01, -9.678731e-01, 1.819053e-01), 2.620416e+04, 1.476994e-08, 1.000000e+00, 21, 2427, 2)
|
||||
((-9.994809e+00, 2.829099e+00, -1.757894e+01), (4.635724e-01, 5.558106e-01, 6.900545e-01), 2.214649e+04, 1.747088e-08, 1.000000e+00, 21, 2427, 2)
|
||||
((-9.553365e+00, 3.358379e+00, -1.692183e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.209726e-08, 1.000000e+00, 21, 2427, 2)
|
||||
((-1.011854e+01, 3.687059e+00, -1.760205e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.716243e-08, 1.000000e+00, 22, 2427, 3)
|
||||
((-1.020058e+01, 3.734765e+00, -1.770077e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 2.789760e-08, 1.000000e+00, 23, 2427, 1)
|
||||
((-1.063244e+01, 3.985917e+00, -1.822054e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.176800e-08, 1.000000e+00, 23, 2426, 1)
|
||||
((-1.081038e+01, 4.089400e+00, -1.843470e+01), (-5.990363e-01, 3.483710e-01, -7.209668e-01), 1.813617e+04, 3.336273e-08, 1.000000e+00, 23, 2437, 1)
|
||||
((-1.081564e+01, 4.092455e+00, -1.844103e+01), (-6.690877e-01, 6.718700e-01, -3.176671e-01), 1.355236e+04, 3.340982e-08, 1.000000e+00, 23, 2437, 1)
|
||||
((-1.096190e+01, 4.239327e+00, -1.851047e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.476743e-08, 1.000000e+00, 23, 2437, 1)
|
||||
((-1.109457e+01, 4.420404e+00, -1.850054e+01), (-5.904492e-01, 8.058629e-01, 4.421237e-02), 1.153343e+04, 3.628014e-08, 1.000000e+00, 22, 2437, 3)
|
||||
((-1.113484e+01, 4.475368e+00, -1.849752e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.673931e-08, 1.000000e+00, 22, 2437, 3)
|
||||
((-1.117187e+01, 4.372425e+00, -1.850142e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.748914e-08, 1.000000e+00, 23, 2437, 1)
|
||||
((-1.127367e+01, 4.089400e+00, -1.851213e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 3.955064e-08, 1.000000e+00, 23, 2426, 1)
|
||||
((-1.135375e+01, 3.866733e+00, -1.852056e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.117251e-08, 1.000000e+00, 22, 2426, 3)
|
||||
((-1.138419e+01, 3.782113e+00, -1.852377e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.178887e-08, 1.000000e+00, 21, 2426, 2)
|
||||
((-1.172456e+01, 2.835777e+00, -1.855959e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.868184e-08, 1.000000e+00, 22, 2426, 3)
|
||||
((-1.175499e+01, 2.751157e+00, -1.856280e+01), (-3.382310e-01, -9.403895e-01, -3.560132e-02), 1.114105e+04, 4.929820e-08, 1.000000e+00, 23, 2426, 1)
|
||||
((-1.179525e+01, 2.639224e+00, -1.856703e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.011351e-08, 1.000000e+00, 23, 2426, 1)
|
||||
((-1.190609e+01, 2.453640e+00, -1.847770e+01), (-4.738733e-01, -7.934600e-01, 3.819231e-01), 8.873828e+03, 5.190861e-08, 1.000000e+00, 23, 2411, 1)
|
||||
((-1.222017e+01, 1.927741e+00, -1.822457e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.699551e-08, 1.000000e+00, 23, 2411, 1)
|
||||
((-1.226820e+01, 1.951470e+00, -1.815983e+01), (-5.716267e-01, 2.823908e-01, 7.703884e-01), 1.028345e+03, 5.888995e-08, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.236181e+01, 1.997712e+00, -1.803368e+01), (1.748787e-01, 6.613493e-01, 7.294070e-01), 4.250133e+02, 6.258186e-08, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.234968e+01, 2.043587e+00, -1.798308e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 6.501444e-08, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.276513e+01, 2.146245e+00, -1.744506e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 8.979603e-08, 1.000000e+00, 22, 2100, 3)
|
||||
((-1.313233e+01, 2.236980e+00, -1.696953e+01), (-6.043263e-01, 1.493281e-01, 7.826180e-01), 4.022525e+02, 1.116994e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.318468e+01, 2.249916e+00, -1.690173e+01), (-8.862976e-01, -6.402442e-02, 4.586692e-01), 3.113244e+02, 1.148223e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.363685e+01, 2.217253e+00, -1.666773e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.357269e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.334593e+01, 2.453640e+00, -1.709033e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.617034e-07, 1.000000e+00, 23, 2101, 1)
|
||||
((-1.308145e+01, 2.668542e+00, -1.747452e+01), (5.149966e-01, 4.184610e-01, -7.481102e-01), 2.471907e+02, 1.853189e-07, 1.000000e+00, 22, 2101, 3)
|
||||
((-1.304150e+01, 2.701005e+00, -1.753256e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.888862e-07, 1.000000e+00, 22, 2101, 3)
|
||||
((-1.304665e+01, 2.669815e+00, -1.753058e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 1.903682e-07, 1.000000e+00, 23, 2101, 1)
|
||||
((-1.308231e+01, 2.453640e+00, -1.751686e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.006392e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.311790e+01, 2.237916e+00, -1.750317e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.108888e-07, 1.000000e+00, 22, 2100, 3)
|
||||
((-1.313266e+01, 2.148507e+00, -1.749750e+01), (-1.624676e-01, -9.847331e-01, 6.248920e-02), 2.387811e+02, 2.151369e-07, 1.000000e+00, 21, 2100, 2)
|
||||
((-1.320190e+01, 1.728791e+00, -1.747087e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.350787e-07, 1.000000e+00, 21, 2100, 2)
|
||||
((-1.309582e+01, 2.150526e+00, -1.834143e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.808996e-07, 1.000000e+00, 22, 2100, 3)
|
||||
((-1.307365e+01, 2.238628e+00, -1.852329e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 2.904717e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.301957e+01, 2.453640e+00, -1.896713e+01), (1.090151e-01, 4.333767e-01, -8.945950e-01), 2.357642e+02, 3.138324e-07, 1.000000e+00, 23, 2101, 1)
|
||||
((-1.297913e+01, 2.614390e+00, -1.929896e+01), (6.012134e-01, 7.985735e-01, -2.868317e-02), 4.041011e+01, 3.312976e-07, 1.000000e+00, 23, 2101, 1)
|
||||
((-1.295975e+01, 2.640133e+00, -1.929988e+01), (6.762805e-01, -5.875192e-01, 4.443713e-01), 3.527833e+01, 3.349640e-07, 1.000000e+00, 23, 2101, 1)
|
||||
((-1.282907e+01, 2.526604e+00, -1.921402e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.584852e-07, 1.000000e+00, 23, 2101, 1)
|
||||
((-1.284217e+01, 2.453640e+00, -1.921346e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 3.799102e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.288683e+01, 2.204886e+00, -1.921158e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.529534e-07, 1.000000e+00, 22, 2100, 3)
|
||||
((-1.290264e+01, 2.116831e+00, -1.921091e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 4.788097e-07, 1.000000e+00, 21, 2100, 2)
|
||||
((-1.308145e+01, 1.120923e+00, -1.920338e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.712448e-07, 1.000000e+00, 22, 2100, 3)
|
||||
((-1.309726e+01, 1.032868e+00, -1.920271e+01), (-1.767101e-01, -9.842348e-01, 7.448995e-03), 6.258032e+00, 7.971010e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.312690e+01, 8.677798e-01, -1.920146e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.455768e-07, 1.000000e+00, 23, 2100, 1)
|
||||
((-1.316626e+01, 8.178800e-01, -1.918559e+01), (-6.009065e-01, -7.617185e-01, 2.422732e-01), 3.971935e+00, 8.693415e-07, 1.000000e+00, 23, 2099, 1)
|
||||
((-1.324019e+01, 7.241633e-01, -1.915578e+01), (-9.367321e-01, -1.471894e-01, -3.175976e-01), 2.365289e+00, 9.139738e-07, 1.000000e+00, 23, 2099, 1)
|
||||
((-1.348497e+01, 6.857011e-01, -1.923877e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.036815e-06, 1.000000e+00, 23, 2099, 1)
|
||||
((-1.390396e+01, 7.859275e-01, -1.924890e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.269071e-06, 1.000000e+00, 23, 2114, 1)
|
||||
((-1.403754e+01, 8.178800e-01, -1.925212e+01), (-9.722929e-01, 2.325825e-01, -2.349230e-02), 1.799413e+00, 1.343115e-06, 1.000000e+00, 23, 2115, 1)
|
||||
((-1.504223e+01, 1.058212e+00, -1.927640e+01), (-4.085804e-01, -2.719942e-01, -8.712526e-01), 1.628266e+00, 1.900041e-06, 1.000000e+00, 23, 2115, 1)
|
||||
((-1.523744e+01, 9.282558e-01, -1.969268e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.170751e-06, 1.000000e+00, 23, 2115, 1)
|
||||
((-1.553972e+01, 1.106680e+00, -1.997974e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 2.636878e-06, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.585973e+01, 1.295571e+00, -2.028364e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.130348e-06, 1.000000e+00, 22, 2129, 3)
|
||||
((-1.593583e+01, 1.340489e+00, -2.035590e+01), (-6.666265e-01, 3.934879e-01, -6.330690e-01), 4.946445e-01, 3.247693e-06, 1.000000e+00, 21, 2129, 2)
|
||||
((-1.647184e+01, 1.656882e+00, -2.086494e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 4.074258e-06, 1.000000e+00, 21, 2129, 2)
|
||||
((-1.585080e+01, 1.545037e+00, -2.159072e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.061748e-06, 1.000000e+00, 22, 2129, 3)
|
||||
((-1.576406e+01, 1.529415e+00, -2.169209e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.199673e-06, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.553972e+01, 1.489015e+00, -2.195425e+01), (6.457458e-01, -1.162934e-01, -7.546444e-01), 4.958073e-01, 5.556377e-06, 1.000000e+00, 23, 2115, 1)
|
||||
((-1.546081e+01, 1.474803e+00, -2.204648e+01), (3.257038e-01, -9.420596e-01, -8.025439e-02), 3.076319e-01, 5.681852e-06, 1.000000e+00, 23, 2115, 1)
|
||||
((-1.543563e+01, 1.401988e+00, -2.205268e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 5.782605e-06, 1.000000e+00, 23, 2115, 1)
|
||||
((-1.553972e+01, 1.153338e+00, -2.213907e+01), (-3.677195e-01, -8.784218e-01, -3.052172e-01), 8.422973e-02, 6.487752e-06, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.565955e+01, 8.670807e-01, -2.223854e+01), (1.611814e-01, 2.692337e-01, -9.494913e-01), 8.559448e-02, 7.299552e-06, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.563263e+01, 9.120446e-01, -2.239711e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 7.712256e-06, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.592604e+01, 1.214620e+00, -2.249695e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.406031e-06, 1.000000e+00, 22, 2129, 3)
|
||||
((-1.598742e+01, 1.277922e+00, -2.251784e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 9.760391e-06, 1.000000e+00, 21, 2129, 2)
|
||||
((-1.670388e+01, 2.016770e+00, -2.276163e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.389636e-05, 1.000000e+00, 22, 2129, 3)
|
||||
((-1.676526e+01, 2.080073e+00, -2.278252e+01), (-6.773989e-01, 6.985688e-01, -2.305048e-01), 3.418159e-02, 1.425072e-05, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.681575e+01, 2.132139e+00, -2.279970e+01), (4.286076e-02, -9.409799e-01, -3.357375e-01), 1.813618e-02, 1.454218e-05, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.681374e+01, 2.087933e+00, -2.281547e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.479439e-05, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.682083e+01, 2.021795e+00, -2.287841e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.532970e-05, 1.000000e+00, 22, 2129, 3)
|
||||
((-1.684417e+01, 1.804084e+00, -2.308558e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.709182e-05, 1.000000e+00, 21, 2129, 2)
|
||||
((-1.686879e+01, 1.574384e+00, -2.330417e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 1.895097e-05, 1.000000e+00, 22, 2129, 3)
|
||||
((-1.689212e+01, 1.356673e+00, -2.351134e+01), (-7.741702e-02, -7.222450e-01, -6.872909e-01), 1.529603e-02, 2.071309e-05, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.689233e+01, 1.354754e+00, -2.351317e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.072862e-05, 1.000000e+00, 23, 2129, 1)
|
||||
((-1.689148e+01, 1.355453e+00, -2.351229e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.073958e-05, 1.000000e+00, 22, 2129, 3)
|
||||
((-1.682182e+01, 1.413107e+00, -2.343954e+01), (6.002458e-01, 4.967948e-01, 6.268172e-01), 8.602342e-03, 2.164421e-05, 1.000000e+00, 21, 2129, 2)
|
||||
((-1.636364e+01, 1.792326e+00, -2.296107e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 2.759442e-05, 1.000000e+00, 21, 2129, 2)
|
||||
((-1.598564e+01, 1.746738e+00, -2.286758e+01), (9.641593e-01, -1.162836e-01, 2.384846e-01), 7.837617e-03, 3.079609e-05, 0.000000e+00, 21, 2129, 2)]
|
||||
ParticleType.NEUTRON [((-9.469716e-01, -2.580266e-01, 1.414357e-01), (1.438873e-01, 2.365819e-01, 9.608983e-01), 9.724461e+05, 0.000000e+00, 1.000000e+00, 23, 2403, 1)
|
||||
((-9.064818e-01, -1.914524e-01, 4.118326e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 2.064696e-10, 1.000000e+00, 23, 2403, 1)
|
||||
((-8.178800e-01, -1.616918e-01, 4.336377e-01), (9.231638e-01, 3.100833e-01, 2.271937e-01), 1.746594e+05, 3.725262e-10, 1.000000e+00, 11, 1756, 1)
|
||||
((-3.834875e-01, -1.578285e-02, 5.405432e-01), (-5.547498e-01, -6.358598e-02, 8.295839e-01), 1.474011e+05, 1.186660e-09, 1.000000e+00, 11, 1756, 1)
|
||||
((-7.999329e-01, -6.351625e-02, 1.163304e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.600465e-09, 1.000000e+00, 11, 1756, 1)
|
||||
((-8.178800e-01, -6.341842e-02, 1.190721e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 2.662321e-09, 1.000000e+00, 23, 2403, 1)
|
||||
((-1.035984e+00, -6.222961e-02, 1.523906e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.414026e-09, 1.000000e+00, 22, 2403, 3)
|
||||
((-1.124618e+00, -6.174649e-02, 1.659308e+00), (-5.476898e-01, 2.985279e-03, 8.366761e-01), 1.467299e+05, 3.719509e-09, 1.000000e+00, 21, 2403, 2)
|
||||
((-1.705404e+00, -5.858082e-02, 2.546543e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 5.721217e-09, 1.000000e+00, 21, 2403, 2)
|
||||
((-1.851116e+00, -4.676544e-01, 2.685103e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.583734e-09, 1.000000e+00, 22, 2403, 3)
|
||||
((-1.880791e+00, -5.509662e-01, 2.713322e+00), (-3.196694e-01, -8.974451e-01, 3.039799e-01), 1.460188e+05, 6.759394e-09, 1.000000e+00, 23, 2403, 1)
|
||||
((-1.948026e+00, -7.397227e-01, 2.777257e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.157380e-09, 1.000000e+00, 23, 2403, 1)
|
||||
((-2.068870e+00, -8.178800e-01, 2.735799e+00), (-8.068708e-01, -5.218555e-01, -2.768147e-01), 6.012975e+04, 7.598974e-09, 1.000000e+00, 23, 2388, 1)
|
||||
((-2.111345e+00, -8.453511e-01, 2.721228e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 7.754188e-09, 1.000000e+00, 23, 2388, 1)
|
||||
((-2.453640e+00, -1.161216e+00, 3.335542e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.421339e-08, 1.000000e+00, 23, 2387, 1)
|
||||
((-2.715369e+00, -1.402736e+00, 3.805265e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 1.915229e-08, 1.000000e+00, 22, 2387, 3)
|
||||
((-2.785083e+00, -1.467067e+00, 3.930380e+00), (-4.440083e-01, -4.097242e-01, 7.968580e-01), 7.445994e+03, 2.046780e-08, 1.000000e+00, 21, 2387, 2)
|
||||
((-2.940196e+00, -1.610203e+00, 4.208760e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 2.339483e-08, 1.000000e+00, 21, 2387, 2)
|
||||
((-3.600602e+00, -1.239800e+00, 3.812386e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.112139e-08, 1.000000e+00, 22, 2387, 3)
|
||||
((-3.682067e+00, -1.194109e+00, 3.763490e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.207450e-08, 1.000000e+00, 23, 2387, 1)
|
||||
((-4.089400e+00, -9.656478e-01, 3.519009e+00), (-7.727102e-01, 4.333905e-01, -4.637797e-01), 6.395532e+03, 3.684019e-08, 1.000000e+00, 23, 2386, 1)
|
||||
((-4.185927e+00, -9.115084e-01, 3.461074e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 3.796953e-08, 1.000000e+00, 23, 2386, 1)
|
||||
((-4.089400e+00, -9.150200e-01, 3.260397e+00), (4.334152e-01, -1.576729e-02, -9.010564e-01), 2.532713e+01, 6.996444e-08, 1.000000e+00, 23, 2387, 1)
|
||||
((-3.920090e+00, -9.211794e-01, 2.908406e+00), (9.094673e-01, -3.659267e-01, -1.974002e-01), 9.547085e+00, 1.260840e-07, 1.000000e+00, 23, 2387, 1)
|
||||
((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 2387, 1)
|
||||
((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 2387, 1)]
|
||||
ParticleType.NEUTRON [((6.474155e+00, -5.192870e+00, 5.413003e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2367, 2)
|
||||
((6.467293e+00, -5.416535e+00, 5.441544e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450870e-05, 1.000000e+00, 22, 2367, 3)
|
||||
((6.464574e+00, -5.505149e+00, 5.452851e+00), (-3.042035e-02, -9.914979e-01, 1.265170e-01), 2.052226e+06, 4.450874e-05, 1.000000e+00, 23, 2367, 1)
|
||||
((6.461877e+00, -5.593034e+00, 5.464065e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450879e-05, 1.000000e+00, 23, 2367, 1)
|
||||
((6.570892e+00, -5.725160e+00, 5.464970e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450891e-05, 1.000000e+00, 32, 7, 1)
|
||||
((6.821003e+00, -6.028296e+00, 5.467047e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450917e-05, 1.000000e+00, 31, 7, 4)
|
||||
((7.101210e+00, -6.367908e+00, 5.469374e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450947e-05, 1.000000e+00, 32, 7, 1)
|
||||
((7.360920e+00, -6.682677e+00, 5.471531e+00), (6.364108e-01, -7.713322e-01, 5.284745e-03), 1.141417e+06, 4.450975e-05, 1.000000e+00, 23, 2353, 1)
|
||||
((7.833926e+00, -7.255962e+00, 5.475459e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451025e-05, 1.000000e+00, 23, 2353, 1)
|
||||
((8.142528e+00, -7.144944e+00, 5.464309e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451091e-05, 1.000000e+00, 22, 2353, 3)
|
||||
((8.590199e+00, -6.983897e+00, 5.448136e+00), (9.404210e-01, 3.383106e-01, -3.397550e-02), 1.289848e+05, 4.451187e-05, 1.000000e+00, 23, 2353, 1)
|
||||
((8.682515e+00, -6.950687e+00, 5.444801e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451207e-05, 1.000000e+00, 23, 2353, 1)
|
||||
((8.996680e+00, -6.629985e+00, 5.450966e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451307e-05, 1.000000e+00, 23, 2354, 1)
|
||||
((9.231138e+00, -6.390649e+00, 5.455567e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451382e-05, 1.000000e+00, 22, 2354, 3)
|
||||
((9.650189e+00, -5.962879e+00, 5.463790e+00), (6.997233e-01, 7.142820e-01, 1.373092e-02), 1.043159e+05, 4.451516e-05, 1.000000e+00, 23, 2354, 1)
|
||||
((9.721007e+00, -5.890588e+00, 5.465180e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451539e-05, 1.000000e+00, 23, 2354, 1)
|
||||
((9.939012e+00, -5.953026e+00, 5.222655e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451775e-05, 1.000000e+00, 22, 2354, 3)
|
||||
((1.002133e+01, -5.976602e+00, 5.131083e+00), (6.565855e-01, -1.880518e-01, -7.304327e-01), 1.036285e+04, 4.451864e-05, 1.000000e+00, 23, 2354, 1)
|
||||
((1.020258e+01, -6.028514e+00, 4.929446e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452060e-05, 1.000000e+00, 23, 2354, 1)
|
||||
((1.063244e+01, -6.047973e+00, 4.703991e+00), (8.848761e-01, -4.005580e-02, -4.641012e-01), 8.908873e+03, 4.452432e-05, 1.000000e+00, 23, 2355, 1)
|
||||
((1.084241e+01, -6.057477e+00, 4.593868e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452614e-05, 1.000000e+00, 23, 2355, 1)
|
||||
((1.107130e+01, -6.074053e+00, 4.699070e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.452930e-05, 1.000000e+00, 22, 2355, 3)
|
||||
((1.121611e+01, -6.084540e+00, 4.765623e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453130e-05, 1.000000e+00, 21, 2355, 2)
|
||||
((1.174815e+01, -6.123069e+00, 5.010155e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.453866e-05, 1.000000e+00, 22, 2355, 3)
|
||||
((1.189296e+01, -6.133556e+00, 5.076709e+00), (9.066652e-01, -6.565865e-02, 4.167099e-01), 3.324374e+03, 4.454067e-05, 1.000000e+00, 23, 2355, 1)
|
||||
((1.221698e+01, -6.157021e+00, 5.225634e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454515e-05, 1.000000e+00, 23, 2355, 1)
|
||||
((1.226820e+01, -6.225607e+00, 5.179351e+00), (5.263177e-01, -7.048209e-01, -4.756229e-01), 3.449618e+02, 4.454893e-05, 1.000000e+00, 23, 2519, 1)
|
||||
((1.230378e+01, -6.273253e+00, 5.147199e+00), (9.203567e-01, -2.667811e-01, -2.859569e-01), 2.269067e+02, 4.455157e-05, 1.000000e+00, 23, 2519, 1)
|
||||
((1.237909e+01, -6.295083e+00, 5.123800e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.455549e-05, 1.000000e+00, 23, 2519, 1)
|
||||
((1.250758e+01, -6.372926e+00, 5.147974e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456396e-05, 1.000000e+00, 22, 2519, 3)
|
||||
((1.258603e+01, -6.420455e+00, 5.162734e+00), (8.444192e-01, -5.115818e-01, 1.588717e-01), 1.686474e+02, 4.456914e-05, 1.000000e+00, 21, 2519, 2)
|
||||
((1.264082e+01, -6.453648e+00, 5.173042e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.457275e-05, 1.000000e+00, 21, 2519, 2)
|
||||
((1.288240e+01, -7.015898e+00, 5.025449e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.460837e-05, 1.000000e+00, 22, 2519, 3)
|
||||
((1.292943e+01, -7.125332e+00, 4.996722e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.461530e-05, 1.000000e+00, 23, 2519, 1)
|
||||
((1.303065e+01, -7.360920e+00, 4.934879e+00), (3.837750e-01, -8.931658e-01, -2.344604e-01), 1.632815e+02, 4.463022e-05, 1.000000e+00, 23, 2520, 1)
|
||||
((1.309295e+01, -7.505897e+00, 4.896822e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.463941e-05, 1.000000e+00, 23, 2520, 1)
|
||||
((1.311741e+01, -7.576618e+00, 4.913644e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.464426e-05, 1.000000e+00, 22, 2520, 3)
|
||||
((1.314895e+01, -7.667795e+00, 4.935331e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.465052e-05, 1.000000e+00, 21, 2520, 2)
|
||||
((1.345125e+01, -8.541749e+00, 5.143210e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471053e-05, 1.000000e+00, 22, 2520, 3)
|
||||
((1.348278e+01, -8.632925e+00, 5.164897e+00), (3.189366e-01, -9.220512e-01, 2.193195e-01), 1.303968e+02, 4.471679e-05, 1.000000e+00, 23, 2520, 1)
|
||||
((1.356121e+01, -8.859646e+00, 5.218825e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.473236e-05, 1.000000e+00, 23, 2520, 1)
|
||||
((1.361604e+01, -8.996680e+00, 5.275368e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.474248e-05, 1.000000e+00, 23, 2521, 1)
|
||||
((1.390396e+01, -9.716172e+00, 5.572247e+00), (3.469373e-01, -8.669828e-01, 3.577365e-01), 1.276458e+02, 4.479558e-05, 1.000000e+00, 23, 2536, 1)
|
||||
((1.399742e+01, -9.949713e+00, 5.668611e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.481282e-05, 1.000000e+00, 23, 2536, 1)
|
||||
((1.390396e+01, -1.004824e+01, 5.750282e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.483180e-05, 1.000000e+00, 23, 2521, 1)
|
||||
((1.334984e+01, -1.063244e+01, 6.234531e+00), (-5.897476e-01, -6.217559e-01, 5.153807e-01), 3.643244e+01, 4.494435e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.317711e+01, -1.081455e+01, 6.385480e+00), (-4.211158e-01, -4.515418e-01, 7.866203e-01), 3.302717e+01, 4.497943e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.316679e+01, -1.082561e+01, 6.404749e+00), (-5.182259e-01, 3.860612e-01, 7.631505e-01), 1.437084e+01, 4.498251e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.292206e+01, -1.064329e+01, 6.765147e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.507257e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.286229e+01, -1.063244e+01, 6.805923e+00), (-8.169098e-01, 1.482852e-01, 5.573777e-01), 1.219816e+01, 4.508772e-05, 1.000000e+00, 23, 2521, 1)
|
||||
((1.284917e+01, -1.063006e+01, 6.814880e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509105e-05, 1.000000e+00, 23, 2521, 1)
|
||||
((1.284547e+01, -1.063244e+01, 6.820442e+00), (-5.213758e-01, -3.360250e-01, 7.843816e-01), 8.052778e+00, 4.509285e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.249929e+01, -1.085555e+01, 7.341246e+00), (-1.520079e-01, -3.513652e-01, 9.238161e-01), 7.069024e+00, 4.526201e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.240103e+01, -1.108268e+01, 7.938428e+00), (-7.405967e-01, -3.230926e-01, 5.891754e-01), 4.460475e+00, 4.543779e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.229354e+01, -1.112958e+01, 8.023945e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.548748e-05, 1.000000e+00, 23, 2522, 1)
|
||||
((1.226820e+01, -1.110933e+01, 8.041241e+00), (-6.892797e-01, 5.508903e-01, 4.705458e-01), 2.006774e+00, 4.550624e-05, 1.000000e+00, 23, 2314, 1)
|
||||
((1.198501e+01, -1.088299e+01, 8.234567e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.571593e-05, 1.000000e+00, 23, 2314, 1)
|
||||
((1.156403e+01, -1.063244e+01, 8.480859e+00), (-7.677533e-01, 4.569444e-01, 4.491733e-01), 1.935517e+00, 4.600087e-05, 1.000000e+00, 23, 2329, 1)
|
||||
((1.150264e+01, -1.059590e+01, 8.516776e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.604243e-05, 1.000000e+00, 23, 2329, 1)
|
||||
((1.121659e+01, -1.063244e+01, 8.744860e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.623561e-05, 1.000000e+00, 23, 2314, 1)
|
||||
((1.063244e+01, -1.070706e+01, 9.210632e+00), (-7.780064e-01, -9.937785e-02, 6.203467e-01), 1.893413e+00, 4.663011e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.035391e+01, -1.074263e+01, 9.432717e+00), (-4.847677e-01, -8.685325e-01, -1.032060e-01), 5.647686e-01, 4.681821e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.031409e+01, -1.081397e+01, 9.424239e+00), (-4.227592e-01, -9.022601e-01, -8.486053e-02), 5.651902e-01, 4.689723e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.028497e+01, -1.087614e+01, 9.418392e+00), (1.549579e-01, -4.270887e-01, 8.908329e-01), 5.395517e-01, 4.696349e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.034128e+01, -1.103135e+01, 9.742126e+00), (5.631544e-01, 4.925564e-01, 6.635098e-01), 2.637257e-01, 4.732118e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.044415e+01, -1.094137e+01, 9.863334e+00), (-1.034377e-01, 7.912271e-01, 6.027108e-01), 1.474934e-01, 4.757836e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.043959e+01, -1.090643e+01, 9.889950e+00), (1.163182e-01, 9.160889e-01, -3.837331e-01), 1.522434e-01, 4.766149e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.045733e+01, -1.076664e+01, 9.831395e+00), (-8.136862e-01, 9.805444e-02, -5.729748e-01), 3.341488e-02, 4.794423e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.044231e+01, -1.076483e+01, 9.820815e+00), (-8.437241e-01, 5.222731e-01, -1.239373e-01), 3.874838e-02, 4.801727e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.028725e+01, -1.066884e+01, 9.798037e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.869227e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.021310e+01, -1.063244e+01, 9.757708e+00), (-8.066297e-01, 3.960430e-01, -4.387465e-01), 3.989754e-02, 4.902498e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.012717e+01, -1.059025e+01, 9.710967e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 4.941058e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.001043e+01, -1.038486e+01, 9.645483e+00), (-4.762033e-01, 8.377852e-01, -2.671075e-01), 3.271721e-02, 5.039049e-05, 1.000000e+00, 22, 2328, 3)
|
||||
((9.971285e+00, -1.031600e+01, 9.623530e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.071901e-05, 1.000000e+00, 22, 2328, 3)
|
||||
((1.002723e+01, -1.037881e+01, 9.564267e+00), (5.437395e-01, -6.104117e-01, -5.759730e-01), 2.765456e-02, 5.116633e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.025152e+01, -1.063060e+01, 9.326683e+00), (-8.159392e-01, -4.792697e-03, 5.781179e-01), 2.920905e-02, 5.295966e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.000779e+01, -1.063203e+01, 9.499373e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422329e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.000721e+01, -1.063244e+01, 9.498835e+00), (-6.486477e-01, -4.621598e-01, -6.047020e-01), 2.383638e-02, 5.422746e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.852478e+00, -1.074269e+01, 9.354584e+00), (-6.686452e-01, -2.988396e-01, 6.808880e-01), 2.993224e-02, 5.534454e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.765042e+00, -1.078177e+01, 9.443621e+00), (7.712484e-01, -5.215773e-01, 3.648739e-01), 3.590785e-02, 5.589099e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.798992e+00, -1.080472e+01, 9.459682e+00), (-4.563170e-01, 8.081811e-01, -3.723144e-01), 2.674168e-02, 5.605894e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.792857e+00, -1.079386e+01, 9.454677e+00), (-9.080336e-01, 4.172659e-01, 3.693418e-02), 9.753404e-03, 5.611838e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.653805e+00, -1.072996e+01, 9.460332e+00), (-3.727950e-01, 2.889342e-01, -8.817828e-01), 1.781716e-02, 5.723944e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.628677e+00, -1.071048e+01, 9.400895e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.760453e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.563380e+00, -1.063244e+01, 9.395105e+00), (-6.406523e-01, 7.657269e-01, -5.680598e-02), 1.764425e-02, 5.815928e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.411305e+00, -1.045068e+01, 9.381621e+00), (3.205568e-01, -1.311309e-02, -9.471385e-01), 2.153422e-02, 5.945128e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.860026e+00, -1.046903e+01, 8.055798e+00), (6.278124e-01, 1.023095e-01, -7.716115e-01), 2.013742e-02, 6.634788e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.007604e+01, -1.043383e+01, 7.790303e+00), (6.790346e-01, 5.167838e-01, 5.213891e-01), 1.340865e-02, 6.810089e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.008869e+01, -1.042421e+01, 7.800011e+00), (2.792456e-01, 1.367953e-01, 9.504257e-01), 8.576635e-03, 6.821715e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.017046e+01, -1.038415e+01, 8.078330e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.050324e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((1.008276e+01, -1.035463e+01, 8.083559e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.070353e-05, 1.000000e+00, 22, 2328, 3)
|
||||
((9.952201e+00, -1.031068e+01, 8.091343e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.100170e-05, 1.000000e+00, 21, 2328, 2)
|
||||
((9.404929e+00, -1.012646e+01, 8.123973e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.225157e-05, 1.000000e+00, 22, 2328, 3)
|
||||
((9.274369e+00, -1.008251e+01, 8.131758e+00), (-9.462370e-01, 3.185163e-01, 5.641780e-02), 1.119274e-01, 7.254974e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.126730e+00, -1.003281e+01, 8.140560e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.288692e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((8.996680e+00, -1.006767e+01, 8.217365e+00), (-8.389978e-01, -2.248732e-01, 4.954945e-01), 1.164832e-01, 7.321528e-05, 1.000000e+00, 23, 2327, 1)
|
||||
((8.694758e+00, -1.014859e+01, 8.395674e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.397758e-05, 1.000000e+00, 23, 2327, 1)
|
||||
((8.996680e+00, -9.720167e+00, 8.656770e+00), (5.156148e-01, 7.316558e-01, 4.458937e-01), 1.391972e-01, 7.511228e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.263031e+00, -9.342216e+00, 8.887105e+00), (5.734531e-01, -5.017666e-01, 6.475970e-01), 9.798082e-02, 7.611330e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.334809e+00, -9.405021e+00, 8.968164e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.640240e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.335117e+00, -9.448857e+00, 8.932084e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.651925e-05, 1.000000e+00, 22, 2328, 3)
|
||||
((9.336345e+00, -9.623801e+00, 8.788098e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.698556e-05, 1.000000e+00, 21, 2328, 2)
|
||||
((9.339070e+00, -1.001201e+01, 8.468584e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.802034e-05, 1.000000e+00, 22, 2328, 3)
|
||||
((9.340298e+00, -1.018696e+01, 8.324598e+00), (5.419546e-03, -7.721039e-01, -6.354732e-01), 1.234091e-01, 7.848665e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.343193e+00, -1.059945e+01, 7.985097e+00), (1.798796e-01, 3.522536e-02, -9.830577e-01), 1.283272e-01, 7.958616e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.397753e+00, -1.058877e+01, 7.686922e+00), (6.459563e-01, 7.279465e-03, -7.633397e-01), 1.319449e-01, 8.019832e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.462343e+00, -1.058804e+01, 7.610595e+00), (-5.748716e-01, 5.760301e-01, -5.811299e-01), 8.880732e-02, 8.039733e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.287877e+00, -1.041322e+01, 7.434230e+00), (-4.932135e-03, 1.668926e-01, 9.859627e-01), 3.503028e-02, 8.113361e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.286930e+00, -1.038117e+01, 7.623600e+00), (-9.325544e-02, -9.933000e-01, -6.825369e-02), 3.173764e-02, 8.187553e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.283901e+00, -1.041342e+01, 7.621384e+00), (-4.235208e-01, -5.129112e-01, 7.466942e-01), 4.258127e-02, 8.200731e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.264517e+00, -1.043690e+01, 7.655560e+00), (-7.165846e-01, 3.926265e-01, 5.764988e-01), 4.485063e-02, 8.216767e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.256348e+00, -1.043242e+01, 7.662132e+00), (1.703748e-01, -9.175599e-01, -3.592441e-01), 3.521226e-02, 8.220659e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.284015e+00, -1.058143e+01, 7.603793e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.283227e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.309126e+00, -1.063244e+01, 7.631745e+00), (3.963415e-01, -8.051509e-01, 4.411865e-01), 2.970280e-02, 8.309804e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.317824e+00, -1.065011e+01, 7.641427e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.319011e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.459378e+00, -1.063244e+01, 7.505770e+00), (7.190682e-01, 8.976507e-02, -6.891177e-01), 2.867417e-02, 8.403060e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.492454e+00, -1.062831e+01, 7.474071e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.422700e-05, 1.000000e+00, 23, 2328, 1)
|
||||
((9.492472e+00, -1.063244e+01, 7.472688e+00), (4.092619e-03, -9.482095e-01, -3.176193e-01), 4.656141e-02, 8.424159e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.492761e+00, -1.069927e+01, 7.450302e+00), (9.457151e-01, -1.928731e-01, 2.615777e-01), 4.542312e-02, 8.447773e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((9.890524e+00, -1.078039e+01, 7.560320e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.590450e-05, 1.000000e+00, 23, 2313, 1)
|
||||
((1.004645e+01, -1.080498e+01, 7.439717e+00), (7.849118e-01, -1.237812e-01, -6.071175e-01), 5.609444e-02, 8.651090e-05, 0.000000e+00, 23, 2313, 1)]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
<track>
|
||||
1 1 1
|
||||
1 1 2
|
||||
1 1 30
|
||||
2 1 60
|
||||
</track>
|
||||
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import glob
|
||||
import os
|
||||
from pathlib import Path
|
||||
from subprocess import call
|
||||
import shutil
|
||||
|
||||
import numpy as np
|
||||
import openmc
|
||||
import pytest
|
||||
|
||||
from tests.testing_harness import TestHarness
|
||||
from tests.testing_harness import TestHarness, config
|
||||
|
||||
|
||||
class TrackTestHarness(TestHarness):
|
||||
|
|
@ -13,26 +15,33 @@ class TrackTestHarness(TestHarness):
|
|||
"""Make sure statepoint.* and track* have been created."""
|
||||
TestHarness._test_output_created(self)
|
||||
|
||||
outputs = glob.glob('track_1_1_*.h5')
|
||||
assert len(outputs) == 2, 'Expected two track files.'
|
||||
if config['mpi'] and int(config['mpi_np']) > 1:
|
||||
outputs = Path.cwd().glob('tracks_p*.h5')
|
||||
assert len(list(outputs)) == int(config['mpi_np'])
|
||||
else:
|
||||
assert Path('tracks.h5').is_file()
|
||||
|
||||
def _get_results(self):
|
||||
"""Digest info in the statepoint and return as a string."""
|
||||
# Run the track-to-vtk conversion script.
|
||||
call(['../../../scripts/openmc-track-to-vtk', '-o', 'poly'] +
|
||||
glob.glob('track_1_1_*.h5'))
|
||||
"""Get data from track file and return as a string."""
|
||||
|
||||
# Make sure the vtk file was created then return it's contents.
|
||||
assert os.path.isfile('poly.pvtp'), 'poly.pvtp file not found.'
|
||||
# For MPI mode, combine track files
|
||||
if config['mpi']:
|
||||
call(['../../../scripts/openmc-track-combine', '-o', 'tracks.h5'] +
|
||||
glob.glob('tracks_p*.h5'))
|
||||
|
||||
with open('poly.pvtp', 'r') as fin:
|
||||
outstr = fin.read()
|
||||
# Get string of track file information
|
||||
outstr = ''
|
||||
tracks = openmc.Tracks('tracks.h5')
|
||||
for track in tracks:
|
||||
with np.printoptions(formatter={'float_kind': '{:.6e}'.format}):
|
||||
for ptrack in track:
|
||||
outstr += f"{ptrack.particle} {ptrack.states}\n"
|
||||
|
||||
return outstr
|
||||
|
||||
def _cleanup(self):
|
||||
TestHarness._cleanup(self)
|
||||
output = glob.glob('track*') + glob.glob('poly*')
|
||||
output = glob.glob('tracks*') + glob.glob('poly*')
|
||||
for f in output:
|
||||
if os.path.exists(f):
|
||||
os.remove(f)
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@
|
|||
<source strength="1.0">
|
||||
<space origin="0.0 0.0 0.0" type="spherical">
|
||||
<r parameters="0.0 0.0" type="uniform" />
|
||||
<theta type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</theta>
|
||||
<cos_theta type="discrete">
|
||||
<parameters>1.0 1.0</parameters>
|
||||
</cos_theta>
|
||||
<phi type="discrete">
|
||||
<parameters>0.0 1.0</parameters>
|
||||
</phi>
|
||||
|
|
|
|||
|
|
@ -228,10 +228,10 @@ def test_unstructured_mesh(test_opts):
|
|||
|
||||
# source setup
|
||||
r = openmc.stats.Uniform(a=0.0, b=0.0)
|
||||
theta = openmc.stats.Discrete(x=[0.0], p=[1.0])
|
||||
cos_theta = openmc.stats.Discrete(x=[1.0], p=[1.0])
|
||||
phi = openmc.stats.Discrete(x=[0.0], p=[1.0])
|
||||
|
||||
space = openmc.stats.SphericalIndependent(r, theta, phi)
|
||||
space = openmc.stats.SphericalIndependent(r, cos_theta, phi)
|
||||
energy = openmc.stats.Discrete(x=[15.e+06], p=[1.0])
|
||||
source = openmc.Source(space=space, energy=energy)
|
||||
settings.source = source
|
||||
|
|
|
|||
|
|
@ -297,3 +297,20 @@ def test_to_xml_element(cell_with_lattice):
|
|||
elem = c.create_xml_subelement(root)
|
||||
assert elem.get('region') == str(c.region)
|
||||
assert elem.get('temperature') == str(c.temperature)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("rotation", [
|
||||
(90, 45, 0),
|
||||
[[1.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, -1.0, 0.0]]
|
||||
])
|
||||
def test_rotation_from_xml(rotation):
|
||||
# Make sure rotation attribute (matrix) round trips through XML correctly
|
||||
s = openmc.ZCylinder(r=10.0)
|
||||
cell = openmc.Cell(region=-s)
|
||||
cell.rotation = rotation
|
||||
root = ET.Element('geometry')
|
||||
elem = cell.create_xml_subelement(root)
|
||||
new_cell = openmc.Cell.from_xml_element(
|
||||
elem, {s.id: s}, {'void': None}, openmc.Universe
|
||||
)
|
||||
np.testing.assert_allclose(new_cell.rotation, cell.rotation)
|
||||
|
|
|
|||
57
tests/unit_tests/test_heating_by_nuclide.py
Normal file
57
tests/unit_tests/test_heating_by_nuclide.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import openmc
|
||||
import pytest
|
||||
|
||||
from tests.testing_harness import config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def model():
|
||||
# Create simple sphere model
|
||||
model = openmc.Model()
|
||||
mat = openmc.Material()
|
||||
mat.add_nuclide('U235', 1.0)
|
||||
mat.add_nuclide('H1', 1.0)
|
||||
mat.set_density('g/cm3', 5.0)
|
||||
sph = openmc.Sphere(r=10.0, boundary_type='vacuum')
|
||||
cell = openmc.Cell(fill=mat, region=-sph)
|
||||
model.geometry = openmc.Geometry([cell])
|
||||
model.settings.particles = 1000
|
||||
model.settings.inactive = 0
|
||||
model.settings.batches = 5
|
||||
model.settings.photon_transport = True
|
||||
|
||||
# Add two tallies, one with heating by nuclide and one with total heating
|
||||
particle_filter = openmc.ParticleFilter(['neutron', 'photon'])
|
||||
heating_by_nuclide = openmc.Tally()
|
||||
heating_by_nuclide.filters = [particle_filter]
|
||||
heating_by_nuclide.nuclides = ['U235', 'H1']
|
||||
heating_by_nuclide.scores = ['heating']
|
||||
|
||||
heating_total = openmc.Tally()
|
||||
heating_total.filters = [particle_filter]
|
||||
heating_total.scores = ['heating']
|
||||
model.tallies.extend([heating_by_nuclide, heating_total])
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def test_heating_by_nuclide(model, run_in_tmpdir):
|
||||
# If running in MPI mode, setup proper keyword arguments for run()
|
||||
kwargs = {'openmc_exec': config['exe']}
|
||||
if config['mpi']:
|
||||
kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']]
|
||||
sp_path = model.run(**kwargs)
|
||||
|
||||
# Get tallies from resulting statepoint
|
||||
with openmc.StatePoint(sp_path) as sp:
|
||||
heating_by_nuclide = sp.tallies[model.tallies[0].id]
|
||||
heating_total = sp.tallies[model.tallies[1].id]
|
||||
|
||||
for particle in heating_by_nuclide.filters[0].bins:
|
||||
# Get slice of each tally corresponding to a single particle
|
||||
kwargs = {'filters': [openmc.ParticleFilter], 'filter_bins': [(particle,)]}
|
||||
particle_slice_by_nuclide = heating_by_nuclide.get_values(**kwargs)
|
||||
particle_slice_total = heating_total.get_values(**kwargs)
|
||||
|
||||
# Summing over nuclides should equal total
|
||||
assert particle_slice_by_nuclide.sum() == pytest.approx(particle_slice_total.sum())
|
||||
|
|
@ -92,6 +92,8 @@ def test_xml_element(myplot):
|
|||
def test_plots(run_in_tmpdir):
|
||||
p1 = openmc.Plot(name='plot1')
|
||||
p1.origin = (5., 5., 5.)
|
||||
p1.colors = {10: (255, 100, 0)}
|
||||
p1.mask_components = [2, 4, 6]
|
||||
p2 = openmc.Plot(name='plot2')
|
||||
p2.origin = (-3., -3., -3.)
|
||||
plots = openmc.Plots([p1, p2])
|
||||
|
|
@ -107,4 +109,6 @@ def test_plots(run_in_tmpdir):
|
|||
new_plots = openmc.Plots.from_xml()
|
||||
assert len(plots)
|
||||
assert plots[0].origin == p1.origin
|
||||
assert plots[0].colors == p1.colors
|
||||
assert plots[0].mask_components == p1.mask_components
|
||||
assert plots[1].origin == p2.origin
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ def test_export_to_xml(run_in_tmpdir):
|
|||
s.keff_trigger = {'type': 'std_dev', 'threshold': 0.001}
|
||||
s.energy_mode = 'continuous-energy'
|
||||
s.max_order = 5
|
||||
s.max_tracks = 1234
|
||||
s.source = openmc.Source(space=openmc.stats.Point())
|
||||
s.output = {'summary': True, 'tallies': False, 'path': 'here'}
|
||||
s.verbosity = 7
|
||||
|
|
@ -42,7 +43,7 @@ def test_export_to_xml(run_in_tmpdir):
|
|||
s.temperature = {'default': 293.6, 'method': 'interpolation',
|
||||
'multipole': True, 'range': (200., 1000.)}
|
||||
s.trace = (10, 1, 20)
|
||||
s.track = [1, 1, 1, 2, 1, 1]
|
||||
s.track = [(1, 1, 1), (2, 1, 1)]
|
||||
s.ufs_mesh = mesh
|
||||
s.resonance_scattering = {'enable': True, 'method': 'rvs',
|
||||
'energy_min': 1.0, 'energy_max': 1000.0,
|
||||
|
|
@ -71,6 +72,7 @@ def test_export_to_xml(run_in_tmpdir):
|
|||
assert s.keff_trigger == {'type': 'std_dev', 'threshold': 0.001}
|
||||
assert s.energy_mode == 'continuous-energy'
|
||||
assert s.max_order == 5
|
||||
assert s.max_tracks == 1234
|
||||
assert isinstance(s.source[0], openmc.Source)
|
||||
assert isinstance(s.source[0].space, openmc.stats.Point)
|
||||
assert s.output == {'summary': True, 'tallies': False, 'path': 'here'}
|
||||
|
|
@ -99,7 +101,7 @@ def test_export_to_xml(run_in_tmpdir):
|
|||
assert s.temperature == {'default': 293.6, 'method': 'interpolation',
|
||||
'multipole': True, 'range': [200., 1000.]}
|
||||
assert s.trace == [10, 1, 20]
|
||||
assert s.track == [1, 1, 1, 2, 1, 1]
|
||||
assert s.track == [(1, 1, 1), (2, 1, 1)]
|
||||
assert isinstance(s.ufs_mesh, openmc.RegularMesh)
|
||||
assert s.ufs_mesh.lower_left == [-10., -10., -10.]
|
||||
assert s.ufs_mesh.upper_right == [10., 10., 10.]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import openmc
|
||||
import openmc.stats
|
||||
|
||||
from math import pi
|
||||
|
||||
def test_source():
|
||||
space = openmc.stats.Point()
|
||||
|
|
@ -26,6 +26,22 @@ def test_source():
|
|||
assert src.strength == 1.0
|
||||
|
||||
|
||||
def test_spherical_uniform():
|
||||
r_outer = 2.0
|
||||
r_inner = 1.0
|
||||
thetas = (0.0, pi/2)
|
||||
phis = (0.0, pi)
|
||||
origin = (0.0, 1.0, 2.0)
|
||||
|
||||
sph_indep_function = openmc.stats.spherical_uniform(r_outer,
|
||||
r_inner,
|
||||
thetas,
|
||||
phis,
|
||||
origin)
|
||||
|
||||
assert isinstance(sph_indep_function, openmc.stats.SphericalIndependent)
|
||||
|
||||
|
||||
def test_source_file():
|
||||
filename = 'source.h5'
|
||||
src = openmc.Source(filename=filename)
|
||||
|
|
@ -35,6 +51,7 @@ def test_source_file():
|
|||
assert 'strength' in elem.attrib
|
||||
assert 'file' in elem.attrib
|
||||
|
||||
|
||||
def test_source_dlopen():
|
||||
library = './libsource.so'
|
||||
src = openmc.Source(library=library)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,29 @@ def test_discrete():
|
|||
assert len(d2) == 1
|
||||
|
||||
|
||||
def test_merge_discrete():
|
||||
x1 = [0.0, 1.0, 10.0]
|
||||
p1 = [0.3, 0.2, 0.5]
|
||||
d1 = openmc.stats.Discrete(x1, p1)
|
||||
|
||||
x2 = [0.5, 1.0, 5.0]
|
||||
p2 = [0.4, 0.5, 0.1]
|
||||
d2 = openmc.stats.Discrete(x2, p2)
|
||||
|
||||
# Merged distribution should have x values sorted and probabilities
|
||||
# appropriately combined. Duplicate x values should appear once.
|
||||
merged = openmc.stats.Discrete.merge([d1, d2], [0.6, 0.4])
|
||||
assert merged.x == pytest.approx([0.0, 0.5, 1.0, 5.0, 10.0])
|
||||
assert merged.p == pytest.approx(
|
||||
[0.6*0.3, 0.4*0.4, 0.6*0.2 + 0.4*0.5, 0.4*0.1, 0.6*0.5])
|
||||
|
||||
# Probabilities add up but are not normalized
|
||||
d1 = openmc.stats.Discrete([3.0], [1.0])
|
||||
triple = openmc.stats.Discrete.merge([d1, d1, d1], [1.0, 2.0, 3.0])
|
||||
assert triple.x == pytest.approx([3.0])
|
||||
assert triple.p == pytest.approx([6.0])
|
||||
|
||||
|
||||
def test_uniform():
|
||||
a, b = 10.0, 20.0
|
||||
d = openmc.stats.Uniform(a, b)
|
||||
|
|
|
|||
143
tests/unit_tests/test_tracks.py
Normal file
143
tests/unit_tests/test_tracks.py
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import openmc
|
||||
import pytest
|
||||
|
||||
from tests.testing_harness import config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sphere_model():
|
||||
openmc.reset_auto_ids()
|
||||
mat = openmc.Material()
|
||||
mat.add_nuclide('Zr90', 1.0)
|
||||
mat.set_density('g/cm3', 1.0)
|
||||
|
||||
model = openmc.Model()
|
||||
sph = openmc.Sphere(r=25.0, boundary_type='vacuum')
|
||||
cell = openmc.Cell(fill=mat, region=-sph)
|
||||
model.geometry = openmc.Geometry([cell])
|
||||
|
||||
model.settings.run_mode = 'fixed source'
|
||||
model.settings.batches = 2
|
||||
model.settings.particles = 50
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def generate_track_file(model, **kwargs):
|
||||
# If running in MPI mode, setup proper keyword arguments for run()
|
||||
kwargs.setdefault('openmc_exec', config['exe'])
|
||||
if config['mpi']:
|
||||
kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']]
|
||||
model.run(**kwargs)
|
||||
|
||||
if config['mpi'] and int(config['mpi_np']) > 1:
|
||||
# With MPI, we need to combine track files
|
||||
track_files = Path.cwd().glob('tracks_p*.h5')
|
||||
openmc.Tracks.combine(track_files, 'tracks.h5')
|
||||
else:
|
||||
track_file = Path('tracks.h5')
|
||||
assert track_file.is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("particle", ["neutron", "photon"])
|
||||
def test_tracks(sphere_model, particle, run_in_tmpdir):
|
||||
# Set track identifiers
|
||||
sphere_model.settings.track = [(1, 1, 1), (1, 1, 10), (2, 1, 15)]
|
||||
|
||||
# Set source particle
|
||||
sphere_model.settings.source = openmc.Source(particle=particle)
|
||||
|
||||
# Run OpenMC to generate tracks.h5 file
|
||||
generate_track_file(sphere_model)
|
||||
|
||||
# Open track file and make sure we have correct number of tracks
|
||||
tracks = openmc.Tracks('tracks.h5')
|
||||
assert len(tracks) == len(sphere_model.settings.track)
|
||||
|
||||
for track, identifier in zip(tracks, sphere_model.settings.track):
|
||||
# Check attributes on Track object
|
||||
assert isinstance(track, openmc.Track)
|
||||
assert track.identifier == identifier
|
||||
assert isinstance(track.particle_tracks, list)
|
||||
if particle == 'neutron':
|
||||
assert len(track.particle_tracks) == 1
|
||||
|
||||
# Check attributes on ParticleTrack object
|
||||
particle_track = track.particle_tracks[0]
|
||||
assert isinstance(particle_track, openmc.ParticleTrack)
|
||||
|
||||
assert particle_track.particle.name.lower() == particle
|
||||
assert isinstance(particle_track.states, np.ndarray)
|
||||
|
||||
# Sanity checks on actual data
|
||||
for state in particle_track.states:
|
||||
assert np.linalg.norm([*state['r']]) <= 25.0001
|
||||
assert np.linalg.norm([*state['u']]) == pytest.approx(1.0)
|
||||
assert 0.0 <= state['E'] <= 20.0e6
|
||||
assert state['time'] >= 0.0
|
||||
assert 0.0 <= state['wgt'] <= 1.0
|
||||
assert state['cell_id'] == 1
|
||||
assert state['material_id'] == 1
|
||||
|
||||
# Checks on 'sources' property
|
||||
sources = track.sources
|
||||
assert len(sources) == len(track.particle_tracks)
|
||||
x = sources[0]
|
||||
state = particle_track.states[0]
|
||||
assert x.r == (*state['r'],)
|
||||
assert x.u == (*state['u'],)
|
||||
assert x.E == state['E']
|
||||
assert x.time == state['time']
|
||||
assert x.wgt == state['wgt']
|
||||
assert x.particle == particle_track.particle
|
||||
|
||||
|
||||
def test_max_tracks(sphere_model, run_in_tmpdir):
|
||||
# Set maximum number of tracks per process to write
|
||||
sphere_model.settings.max_tracks = expected_num_tracks = 10
|
||||
if config['mpi']:
|
||||
expected_num_tracks *= int(config['mpi_np'])
|
||||
|
||||
# Run OpenMC to generate tracks.h5 file
|
||||
generate_track_file(sphere_model, tracks=True)
|
||||
|
||||
# Open track file and make sure we have correct number of tracks
|
||||
tracks = openmc.Tracks('tracks.h5')
|
||||
assert len(tracks) == expected_num_tracks
|
||||
|
||||
|
||||
def test_filter(sphere_model, run_in_tmpdir):
|
||||
# Set maximum number of tracks per process to write
|
||||
sphere_model.settings.max_tracks = 25
|
||||
sphere_model.settings.photon_transport = True
|
||||
|
||||
# Run OpenMC to generate tracks.h5 file
|
||||
generate_track_file(sphere_model, tracks=True)
|
||||
|
||||
tracks = openmc.Tracks('tracks.h5')
|
||||
for track in tracks:
|
||||
# Test filtering by particle
|
||||
matches = track.filter(particle='photon')
|
||||
for x in matches:
|
||||
assert x.particle == openmc.ParticleType.PHOTON
|
||||
|
||||
# Test general state filter
|
||||
matches = track.filter(state_filter=lambda s: s['cell_id'] == 1)
|
||||
assert isinstance(matches, openmc.Track)
|
||||
assert matches.particle_tracks == track.particle_tracks
|
||||
matches = track.filter(state_filter=lambda s: s['cell_id'] == 2)
|
||||
assert matches.particle_tracks == []
|
||||
matches = track.filter(state_filter=lambda s: s['E'] < 0.0)
|
||||
assert matches.particle_tracks == []
|
||||
|
||||
# Test filter method on Tracks
|
||||
matches = tracks.filter(particle='neutron')
|
||||
assert isinstance(matches, openmc.Tracks)
|
||||
assert matches == tracks
|
||||
matches = tracks.filter(state_filter=lambda s: s['E'] > 0.0)
|
||||
assert matches == tracks
|
||||
matches = tracks.filter(particle='bunnytron')
|
||||
assert matches == []
|
||||
Loading…
Add table
Add a link
Reference in a new issue