Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
MCGIDI_product.cc
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# Copyright 2019, Lawrence Livermore National Security, LLC.
4# This file is part of the gidiplus package (https://github.com/LLNL/gidiplus).
5# gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT).
6# SPDX-License-Identifier: MIT
7# <<END-copyright>>
8*/
9
10#include "MCGIDI.hpp"
11
12namespace MCGIDI {
13
14/*! \class Product
15 * This class represents a **GNDS** <**product**> node with only data needed for Monte Carlo transport.
16 */
17
18/* *********************************************************************************************************//**
19 * Default constructor used when broadcasting a Protare as needed by MPI or GPUs.
20 ***********************************************************************************************************/
21
23 m_ID( ),
24 m_intid( -1 ),
25 m_index( -1 ),
26 m_userParticleIndex( -1 ),
27 m_isCompleteParticle( false ),
28 m_mass( 0.0 ),
29 m_excitationEnergy( 0.0 ),
30 m_twoBodyOrder( TwoBodyOrder::notApplicable ),
31 m_initialStateIndex( -1 ),
32 m_multiplicity( nullptr ),
33 m_distribution( nullptr ),
34 m_outputChannel( nullptr ) {
35
36}
37
38/* *********************************************************************************************************//**
39 * @param a_product [in] The GIDI::Product whose data is to be used to construct *this*.
40 * @param a_setupInfo [in] Used internally when constructing a Protare to pass information to other constructors.
41 * @param a_settings [in] Used to pass user options to the *this* to instruct it which data are desired.
42 * @param a_particles [in] List of transporting particles and their information (e.g., multi-group boundaries and fluxes).
43 * @param a_isFission [in] *true* if parent channel is a fission channel and *false* otherwise.
44 ***********************************************************************************************************/
45
46LUPI_HOST Product::Product( GIDI::Product const *a_product, SetupInfo &a_setupInfo, Transporting::MC const &a_settings,
47 GIDI::Transporting::Particles const &a_particles, bool a_isFission ) :
48 m_ID( a_product->particle( ).ID( ).c_str( ) ),
49 m_intid( MCGIDI_popsIntid( a_setupInfo.m_pops, a_product->particle( ).ID( ) ) ),
50 m_index( MCGIDI_popsIndex( a_setupInfo.m_popsUser, a_product->particle( ).ID( ) ) ),
51 m_userParticleIndex( -1 ),
52 m_label( a_product->label( ).c_str( ) ),
53 m_isCompleteParticle( a_product->isCompleteParticle( ) ),
54 m_mass( a_product->particle( ).mass( "MeV/c**2" ) ), // Includes nuclear excitation energy.
55 m_excitationEnergy( a_product->particle( ).excitationEnergy( ).value( ) ),
56 m_twoBodyOrder( a_setupInfo.m_twoBodyOrder ),
57 m_initialStateIndex( -1 ),
58 m_multiplicity( Functions::parseMultiplicityFunction1d( a_setupInfo, a_settings, a_product->multiplicity( ) ) ),
59 m_distribution( nullptr ),
60 m_outputChannel( nullptr ) {
61
62 a_setupInfo.m_product1Mass = mass( ); // Includes nuclear excitation energy.
63 a_setupInfo.m_initialStateIndex = -1;
64 m_distribution = Distributions::parseGIDI( a_product->distribution( ), a_setupInfo, a_settings );
65 m_initialStateIndex = a_setupInfo.m_initialStateIndex;
66
67 GIDI::OutputChannel const *output_channel = a_product->outputChannel( );
68 if( output_channel != nullptr ) m_outputChannel = new OutputChannel( output_channel, a_setupInfo, a_settings, a_particles );
69
70 if( a_isFission && ( m_intid == PoPI::Intids::neutron ) && a_settings.wantTerrellPromptNeutronDistribution( ) ) {
71 Functions::Function1d_d1 *multiplicity1 = static_cast<Functions::Function1d_d1 *>( m_multiplicity );
72
73 m_multiplicity = new Functions::TerrellFissionNeutronMultiplicityModel( -1.0, multiplicity1 );
74 }
75}
76
77/* *********************************************************************************************************//**
78 * @param a_pops [in] A PoPs Database instance used to get particle intids and possibly other particle information.
79 * @param a_ID [in] The PoPs id for the product.
80 * @param a_label [in] The **GNDS** label for the product.
81 ***********************************************************************************************************/
82
83LUPI_HOST Product::Product( PoPI::Database const &a_pops, std::string const &a_ID, std::string const &a_label ) :
84 m_ID( a_ID.c_str( ) ),
85 m_intid( MCGIDI_popsIntid( a_pops, a_ID ) ),
86 m_index( MCGIDI_popsIndex( a_pops, a_ID ) ),
87 m_userParticleIndex( -1 ),
88 m_label( a_label.c_str( ) ),
89 m_mass( 0.0 ), // FIXME, good for photon but nothing else. Still need to implement.
90 m_excitationEnergy( 0.0 ),
91 m_twoBodyOrder( TwoBodyOrder::notApplicable ),
92 m_initialStateIndex( -1 ),
93 m_multiplicity( nullptr ),
94 m_distribution( nullptr ),
95 m_outputChannel( nullptr ) {
96
97}
98
99/* *********************************************************************************************************//**
100 ***********************************************************************************************************/
101
103
104 delete m_multiplicity;
105
107 if( m_distribution != nullptr ) type = m_distribution->type( );
108 switch( type ) {
110 break;
112 delete static_cast<Distributions::Unspecified *>( m_distribution );
113 break;
115 delete static_cast<Distributions::AngularTwoBody *>( m_distribution );
116 break;
118 delete static_cast<Distributions::KalbachMann *>( m_distribution );
119 break;
121 delete static_cast<Distributions::Uncorrelated *>( m_distribution );
122 break;
124 delete static_cast<Distributions::Branching3d *>( m_distribution );
125 break;
127 delete static_cast<Distributions::EnergyAngularMC *>( m_distribution );
128 break;
130 delete static_cast<Distributions::AngularEnergyMC *>( m_distribution );
131 break;
133 delete static_cast<Distributions::CoherentPhotoAtomicScattering *>( m_distribution );
134 break;
136 delete static_cast<Distributions::IncoherentPhotoAtomicScattering *>( m_distribution );
137 break;
139 delete static_cast<Distributions::IncoherentBoundToFreePhotoAtomicScattering *>( m_distribution );
140 break;
142 delete static_cast<Distributions::IncoherentPhotoAtomicScatteringElectron *>( m_distribution );
143 break;
145 delete static_cast<Distributions::PairProductionGamma *>( m_distribution );
146 break;
148 delete static_cast<Distributions::CoherentElasticTNSL *>( m_distribution );
149 break;
151 delete static_cast<Distributions::IncoherentElasticTNSL *>( m_distribution );
152 break;
153 }
154
155 delete m_outputChannel;
156}
157
158/* *********************************************************************************************************//**
159 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs index *a_particleIndex*.
160 *
161 * @param a_particleIndex [in] The PoPs index of the particle whose user index is to be set.
162 * @param a_userParticleIndex [in] The particle index specified by the user.
163 ***********************************************************************************************************/
164
165LUPI_HOST void Product::setUserParticleIndex( int a_particleIndex, int a_userParticleIndex ) {
166
167 if( m_index == a_particleIndex ) m_userParticleIndex = a_userParticleIndex;
168#ifdef MCGIDI_USE_OUTPUT_CHANNEL
169 if( m_outputChannel != nullptr ) m_outputChannel->setUserParticleIndex( a_particleIndex, a_userParticleIndex );
170#endif
171}
172
173/* *********************************************************************************************************//**
174 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs intid *a_particleIntid*.
175 *
176 * @param a_particleIntid [in] The PoPs intid of the particle whose user index is to be set.
177 * @param a_userParticleIndex [in] The particle index specified by the user.
178 ***********************************************************************************************************/
179
180LUPI_HOST void Product::setUserParticleIndexViaIntid( int a_particleIntid, int a_userParticleIndex ) {
181
182 if( m_intid == a_particleIntid ) m_userParticleIndex = a_userParticleIndex;
183#ifdef MCGIDI_USE_OUTPUT_CHANNEL
184 if( m_outputChannel != nullptr ) m_outputChannel->setUserParticleIndexViaIntid( a_particleIntid, a_userParticleIndex );
185#endif
186}
187
188/* *********************************************************************************************************//**
189 * This method calls the **setModelDBRC_data* method on the distribution of *this* with *a_modelDBRC_data*.
190 *
191 * @param a_modelDBRC_data [in] The instance storing data needed to treat the DRRC upscatter mode.
192 ***********************************************************************************************************/
193
195
196 m_distribution->setModelDBRC_data( a_modelDBRC_data );
197}
198
199/* *********************************************************************************************************//**
200 * This method returns the final Q for *this* by getting its output channel's finalQ.
201 *
202 * @param a_x1 [in] The energy of the projectile.
203 *
204 * @return The Q-value at product energy *a_x1*.
205 ***********************************************************************************************************/
206
208
209#ifdef MCGIDI_USE_OUTPUT_CHANNEL
210 if( m_outputChannel != nullptr ) return( m_outputChannel->finalQ( a_x1 ) );
211#endif
212 return( m_excitationEnergy );
213}
214
215/* *********************************************************************************************************//**
216 * This method returns *true* if the output channel or any of its sub-output channels is a fission channel and *false* otherwise.
217 *
218 * @return *true* if any sub-output channel is a fission channel and *false* otherwise.
219 ***********************************************************************************************************/
220
222
223#ifdef MCGIDI_USE_OUTPUT_CHANNEL
224 if( m_outputChannel != nullptr ) return( m_outputChannel->hasFission( ) );
225#endif
226 return( false );
227}
228
229/* *********************************************************************************************************//**
230 * Returns the energy dependent multiplicity for outgoing particle with pops index *a_index*. The returned value may not
231 * be an integer. Energy dependent multiplicities mainly occurs for photons and fission neutrons.
232 *
233 * @param a_index [in] The PoPs index of the requested particle.
234 * @param a_projectileEnergy [in] The energy of the projectile.
235 *
236 * @return The multiplicity value for the requested particle.
237 ***********************************************************************************************************/
238
239LUPI_HOST_DEVICE double Product::productAverageMultiplicity( int a_index, double a_projectileEnergy ) const {
240
241 double multiplicity1 = 0.0;
242
243 if( a_index == m_index ) {
244 if( ( m_multiplicity->domainMin( ) <= a_projectileEnergy ) && ( m_multiplicity->domainMax( ) >= a_projectileEnergy ) )
245 multiplicity1 += m_multiplicity->evaluate( a_projectileEnergy );
246 }
247#ifdef MCGIDI_USE_OUTPUT_CHANNEL
248 if( m_outputChannel != nullptr ) multiplicity1 += m_outputChannel->productAverageMultiplicity( a_index, a_projectileEnergy );
249#endif
250
251 return( multiplicity1 );
252}
253
254/* *********************************************************************************************************//**
255 * Returns the energy dependent multiplicity for outgoing particle with pops intid *a_intid*. The returned value may not
256 * be an integer. Energy dependent multiplicities mainly occurs for photons and fission neutrons.
257 *
258 * @param a_intid [in] The PoPs intid of the requested particle.
259 * @param a_projectileEnergy [in] The energy of the projectile.
260 *
261 * @return The multiplicity value for the requested particle.
262 ***********************************************************************************************************/
263
264LUPI_HOST_DEVICE double Product::productAverageMultiplicityViaIntid( int a_intid, double a_projectileEnergy ) const {
265
266 double multiplicity1 = 0.0;
267
268 if( a_intid == m_intid ) {
269 if( ( m_multiplicity->domainMin( ) <= a_projectileEnergy ) && ( m_multiplicity->domainMax( ) >= a_projectileEnergy ) )
270 multiplicity1 += m_multiplicity->evaluate( a_projectileEnergy );
271 }
272#ifdef MCGIDI_USE_OUTPUT_CHANNEL
273 if( m_outputChannel != nullptr ) multiplicity1 += m_outputChannel->productAverageMultiplicityViaIntid( a_intid, a_projectileEnergy );
274#endif
275
276 return( multiplicity1 );
277}
278
279/* *********************************************************************************************************//**
280 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
281 * bytes, pack *this* or unpack *this* depending on *a_mode*.
282 *
283 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
284 * @param a_mode [in] Specifies the action of this method.
285 ***********************************************************************************************************/
286
288
289 DATA_MEMBER_STRING( m_ID, a_buffer, a_mode );
290 DATA_MEMBER_INT( m_intid, a_buffer, a_mode );
291 DATA_MEMBER_INT( m_index, a_buffer, a_mode );
292 DATA_MEMBER_INT( m_userParticleIndex, a_buffer, a_mode );
293 DATA_MEMBER_STRING( m_label, a_buffer, a_mode );
294 DATA_MEMBER_CAST( m_isCompleteParticle, a_buffer, a_mode, bool );
295 DATA_MEMBER_DOUBLE( m_mass, a_buffer, a_mode );
296 DATA_MEMBER_DOUBLE( m_excitationEnergy, a_buffer, a_mode );
297
298 int twoBodyOrder = 0;
299 switch( m_twoBodyOrder ) {
301 break;
303 twoBodyOrder = 1;
304 break;
306 twoBodyOrder = 2;
307 break;
308 }
309 DATA_MEMBER_INT( twoBodyOrder , a_buffer, a_mode );
310 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
311 switch( twoBodyOrder ) {
312 case 0 :
313 m_twoBodyOrder = TwoBodyOrder::notApplicable;
314 break;
315 case 1 :
316 m_twoBodyOrder = TwoBodyOrder::firstParticle;
317 break;
318 case 2 :
319 m_twoBodyOrder = TwoBodyOrder::secondParticle;
320 break;
321 }
322 }
323
324 DATA_MEMBER_INT( m_initialStateIndex, a_buffer, a_mode );
325
326 m_multiplicity = serializeFunction1d( a_buffer, a_mode, m_multiplicity );
327 m_distribution = serializeDistribution( a_buffer, a_mode, m_distribution );
328
329#ifdef MCGIDI_USE_OUTPUT_CHANNEL
330 bool haveChannel = m_outputChannel != nullptr;
331 DATA_MEMBER_CAST( haveChannel, a_buffer, a_mode, bool );
332 if( haveChannel ) {
333 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
334 if (a_buffer.m_placement != nullptr) {
335 m_outputChannel = new(a_buffer.m_placement) OutputChannel();
336 a_buffer.incrementPlacement( sizeof(OutputChannel));
337 }
338 else {
339 m_outputChannel = new OutputChannel();
340 }
341 }
342 if( a_mode == LUPI::DataBuffer::Mode::Memory ) {
343 a_buffer.incrementPlacement( sizeof(OutputChannel));
344 }
345 m_outputChannel->serialize( a_buffer, a_mode );
346 }
347#endif
348}
349
350}
#define DATA_MEMBER_STRING(member, buf, mode)
#define DATA_MEMBER_CAST(member, buf, mode, someType)
#define DATA_MEMBER_DOUBLE(member, buf, mode)
#define DATA_MEMBER_INT( member, buf, mode)
#define LUPI_HOST_DEVICE
#define LUPI_HOST
#define LUPI_maybeUnused
OutputChannel * outputChannel() const
Definition GIDI.hpp:3906
Component & distribution()
Definition GIDI.hpp:3900
LUPI_HOST_DEVICE void incrementPlacement(std::size_t a_delta)
LUPI_HOST void setUserParticleIndex(int a_particleIndex, int a_userParticleIndex)
LUPI_HOST_DEVICE Product()
LUPI_HOST_DEVICE bool isCompleteParticle() const
Definition MCGIDI.hpp:1207
LUPI_HOST_DEVICE ~Product()
LUPI_HOST_DEVICE double productAverageMultiplicity(int a_index, double a_projectileEnergy) const
LUPI_HOST_DEVICE double productAverageMultiplicityViaIntid(int a_intid, double a_projectileEnergy) const
LUPI_HOST String const & ID() const
Definition MCGIDI.hpp:1199
LUPI_HOST void setModelDBRC_data(Sampling::Upscatter::ModelDBRC_data *a_modelDBRC_data)
LUPI_HOST_DEVICE TwoBodyOrder twoBodyOrder() const
Definition MCGIDI.hpp:1210
LUPI_HOST_DEVICE Functions::Function1d const * multiplicity() const
Definition MCGIDI.hpp:1215
LUPI_HOST_DEVICE double finalQ(double a_x1) const
LUPI_HOST_DEVICE double excitationEnergy() const
Definition MCGIDI.hpp:1209
LUPI_HOST void setUserParticleIndexViaIntid(int a_particleIntid, int a_userParticleIndex)
LUPI_HOST_DEVICE bool hasFission() const
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE double mass() const
Definition MCGIDI.hpp:1208
LUPI_HOST_DEVICE String label() const
Definition MCGIDI.hpp:1206
double m_product1Mass
Definition MCGIDI.hpp:262
LUPI_HOST bool wantTerrellPromptNeutronDistribution() const
Definition MCGIDI.hpp:197
LUPI_HOST Distribution * parseGIDI(GIDI::Suite const &a_distribution, SetupInfo &a_setupInfo, Transporting::MC const &a_settings)
Simple C++ string class, useful as replacement for std::string if this cannot be used,...
Definition MCGIDI.hpp:43
LUPI_HOST_DEVICE Distributions::Distribution * serializeDistribution(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode, Distributions::Distribution *a_distribution)
LUPI_HOST int MCGIDI_popsIntid(PoPI::Database const &a_pops, std::string const &a_ID)
LUPI_HOST int MCGIDI_popsIndex(PoPI::Database const &a_pops, std::string const &a_ID)
TwoBodyOrder
Definition MCGIDI.hpp:229
LUPI_HOST_DEVICE Functions::Function1d * serializeFunction1d(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode, Functions::Function1d *a_function1d)
static int constexpr neutron
Definition PoPI.hpp:177