Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
MCGIDI_heatedCrossSections.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
14static LUPI_HOST void checkZeroReaction( GIDI::Vector &vector, bool a_zeroReactions );
15static LUPI_HOST GIDI::Vector collapseAndcheckZeroReaction( GIDI::Vector &a_vector, Transporting::MC const &a_settings,
16 GIDI::Transporting::Particles const &a_particles, double a_temperature, bool a_zeroReactions );
17static void writeVector( FILE *a_file, std::string const &a_prefix, std::size_t a_offset, Vector<double> const &a_vector );
18
19/*! \class HeatedReactionCrossSectionContinuousEnergy
20 * Class to store a reaction's cross section.
21 */
22
23/* *********************************************************************************************************//**
24 * Simple constructor needed for broadcasting.
25 ***********************************************************************************************************/
26
28 m_offset( 0 ),
29 m_threshold( 0.0 ),
30 m_crossSections( ),
31 m_URR_mode( Transporting::URR_mode::none ),
32 m_URR_probabilityTables( nullptr ),
33 m_ACE_URR_probabilityTables( nullptr ) {
34
35}
36
37/* *********************************************************************************************************//**
38 * @param a_offset [in] The offset of the first cross section point in the energy grid.
39 * @param a_threshold [in] The threshold for the reaction.
40 * @param a_crossSection [in] The cross section for the reaction.
41 ***********************************************************************************************************/
42
44 double a_threshold, Vector<double> &a_crossSection ) :
45 m_offset( a_offset ),
46 m_threshold( a_threshold ),
47 m_crossSections( a_crossSection.size( ) ),
48 m_URR_mode( Transporting::URR_mode::none ),
49 m_URR_probabilityTables( nullptr ),
50 m_ACE_URR_probabilityTables( nullptr ) {
51
52 std::size_t index = 0; // This and next line needed as m_crossSections may be an instance of Vector<float>.
53 for( auto iter = a_crossSection.begin( ); iter != a_crossSection.end( ); ++iter, ++index ) m_crossSections[index] = *iter;
54
55}
56
57/* *********************************************************************************************************//**
58 * @param a_threshold [in] The threshold for the reaction.
59 * @param a_crossSection [in] The cross section for the reaction.
60 * @param a_URR_probabilityTables [in] The pdf style URR probability tables.
61 * @param a_ACE_URR_probabilityTables [in] The ACE style URR probability tables.
62 ***********************************************************************************************************/
63
65 GIDI::Functions::Ys1d const &a_crossSection, Probabilities::ProbabilityBase2d *a_URR_probabilityTables,
66 ACE_URR_probabilityTables *a_ACE_URR_probabilityTables ) :
67 m_offset( a_crossSection.start( ) ),
68 m_threshold( a_threshold ),
69 m_crossSections( a_crossSection.Ys( ).size( ) ),
70 m_URR_mode( Transporting::URR_mode::none ),
71 m_URR_probabilityTables( a_URR_probabilityTables ),
72 m_ACE_URR_probabilityTables( a_ACE_URR_probabilityTables ) {
73
74 std::size_t index = 0; // Next lines needed as m_crossSections may be an instance of Vector<float>.
75 std::vector<double> const &Ys = a_crossSection.Ys( );
76 for( auto iter = Ys.begin( ); iter != Ys.end( ); ++iter, ++index ) m_crossSections[index] = *iter;
77
78 if( m_URR_probabilityTables != nullptr ) {
79 m_URR_mode = Transporting::URR_mode::pdfs; }
80 else if( m_ACE_URR_probabilityTables != nullptr ) {
81 m_URR_mode = Transporting::URR_mode::ACE_URR_probabilityTables;
82 }
83}
84
85/* *********************************************************************************************************//**
86 ***********************************************************************************************************/
87
89
90 delete m_URR_probabilityTables;
91 delete m_ACE_URR_probabilityTables;
92}
93
94/* *********************************************************************************************************//**
95 * Returns the minimum energy for the unresolved resonance region (URR) domain. If no URR data present, returns -1.
96 *
97 * @return true is if *this* has a URR data.
98 ***********************************************************************************************************/
99
101
102 if( m_URR_probabilityTables != nullptr ) return( m_URR_probabilityTables->domainMin( ) );
103 if( m_ACE_URR_probabilityTables != nullptr ) return( m_ACE_URR_probabilityTables->domainMin( ) );
104
105 return( -1.0 );
106}
107
108/* *********************************************************************************************************//**
109 * Returns the maximum energy for the unresolved resonance region (URR) domain. If no URR data present, returns -1.
110 *
111 * @return true is if *this* has a URR data.
112 ***********************************************************************************************************/
113
115
116 if( m_URR_probabilityTables != nullptr ) return( m_URR_probabilityTables->domainMax( ) );
117 if( m_ACE_URR_probabilityTables != nullptr ) return( m_ACE_URR_probabilityTables->domainMax( ) );
118
119 return( -1.0 );
120}
121
122/* *********************************************************************************************************//**
123 * Returns the reactions cross section as a GIDI::Functions::XYs1d instance.
124 *
125 * @returns A GIDI::Functions::XYs1d instance.
126 ***********************************************************************************************************/
127
129 Vector<double> const &a_energies ) const {
130
131 std::vector<double> energies = vectorToSTD_vector( a_energies );
132 std::vector<double> crossSection( energies.size( ), 0.0 );
133 for( std::size_t index = 0; index < m_crossSections.size( ); ++index ) crossSection[m_offset+index] = m_crossSections[index];
134
135 return( GIDI::Functions::XYs1d( GIDI::Axes( ), ptwXY_interpolationLinLin, energies, crossSection, 0, a_temperature ) );
136}
137
138/* *********************************************************************************************************//**
139 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
140 * bytes, pack *this* or unpack *this* depending on *a_mode*.
141 *
142 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
143 * @param a_mode [in] Specifies the action of this method.
144 ***********************************************************************************************************/
145
147
148 DATA_MEMBER_SIZE_T( m_offset, a_buffer, a_mode );
149 DATA_MEMBER_DOUBLE( m_threshold, a_buffer, a_mode );
150 DATA_MEMBER_VECTOR_FLOAT_OR_DOUBLE( m_crossSections, a_buffer, a_mode );
151 m_URR_mode = serializeURR_mode( m_URR_mode, a_buffer, a_mode );
152 m_URR_probabilityTables = serializeProbability2d( a_buffer, a_mode, m_URR_probabilityTables );
153 m_ACE_URR_probabilityTables = serializeACE_URR_probabilityTables( m_ACE_URR_probabilityTables, a_buffer, a_mode );
154}
155
156/* *********************************************************************************************************//**
157 * Print to *std::cout* the content of *this*. This is mainly meant for debugging.
158 *
159 * @param a_protareSingle [in] The ProtareSingle instance *this* resides in.
160 * @param a_indent [in] The buffer to read or write data to depending on *a_mode*.
161 * @param a_iFormat [in] C printf format specifier for any interger that is printed (e.g., "%3d").
162 * @param a_energyFormat [in] C printf format specifier for any interger that is printed (e.g., "%20.12e").
163 * @param a_dFormat [in] C printf format specifier for any interger that is printed (e.g., "%14.7e").
164 ***********************************************************************************************************/
165
166LUPI_HOST void HeatedReactionCrossSectionContinuousEnergy::print( LUPI_maybeUnused ProtareSingle const *a_protareSingle, std::string const &a_indent,
167 LUPI_maybeUnused std::string const &a_iFormat, LUPI_maybeUnused std::string const &a_energyFormat, std::string const &a_dFormat ) const {
168
169 std::cout << a_indent << "# Offset = " << m_offset << std::endl;
170 std::cout << a_indent << "# Threshold = " << m_threshold << std::endl;
171
172 std::cout << a_indent << "# Number of cross section points = " << m_crossSections.size( ) << std::endl;
173 for( auto iter = m_crossSections.begin( ); iter != m_crossSections.end( ); ++iter )
174 std::cout << a_indent << LUPI::Misc::argumentsToString( a_dFormat.c_str( ), *iter ) << std::endl;
175}
176
177/*
178============================================================
179=================== ContinuousEnergyGain ===================
180============================================================
181*/
182
183/* *********************************************************************************************************//**
184 ***********************************************************************************************************/
186 m_particleIntid( -1 ),
187 m_particleIndex( -1 ),
188 m_userParticleIndex( -1 ) {
189
190}
191
192/* *********************************************************************************************************//**
193 ***********************************************************************************************************/
194
195LUPI_HOST ContinuousEnergyGain::ContinuousEnergyGain( int a_particleIntid, int a_particleIndex, std::size_t a_size ) :
196 m_particleIntid( a_particleIntid ),
197 m_particleIndex( a_particleIndex ),
198 m_userParticleIndex( -1 ),
199 m_gain( a_size, static_cast<MCGIDI_FLOAT>( 0.0 ) ) {
200
201}
202
203/* *********************************************************************************************************//**
204 ***********************************************************************************************************/
205
207
208 m_particleIntid = a_continuousEnergyGain.particleIntid( );
209 m_particleIndex = a_continuousEnergyGain.particleIndex( );
210 m_userParticleIndex = a_continuousEnergyGain.userParticleIndex( );
211 m_gain = a_continuousEnergyGain.gain( );
212
213 return( *this );
214}
215
216/* *********************************************************************************************************//**
217 ***********************************************************************************************************/
218
219LUPI_HOST_DEVICE double ContinuousEnergyGain::gain( std::size_t a_energy_index, double a_energy_fraction ) const {
220
221 return( a_energy_fraction * m_gain[a_energy_index] + ( 1.0 - a_energy_fraction ) * m_gain[a_energy_index+1] );
222}
223
224/* *********************************************************************************************************//**
225 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
226 * bytes, pack *this* or unpack *this* depending on *a_mode*.
227 *
228 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
229 * @param a_mode [in] Specifies the action of this method.
230 ***********************************************************************************************************/
231
233
234 DATA_MEMBER_INT( m_particleIntid, a_buffer, a_mode );
235 DATA_MEMBER_INT( m_particleIndex, a_buffer, a_mode );
236 DATA_MEMBER_INT( m_userParticleIndex, a_buffer, a_mode );
237 DATA_MEMBER_VECTOR_FLOAT_OR_DOUBLE( m_gain, a_buffer, a_mode );
238}
239
240/* *********************************************************************************************************//**
241 * Print to *std::cout* the content of *this*. This is mainly meant for debugging.
242 *
243 * @param a_protareSingle [in] The ProtareSingle instance *this* resides in.
244 * @param a_indent [in] The buffer to read or write data to depending on *a_mode*.
245 * @param a_iFormat [in] C printf format specifier for any interger that is printed (e.g., "%3d").
246 * @param a_energyFormat [in] C printf format specifier for any interger that is printed (e.g., "%20.12e").
247 * @param a_dFormat [in] C printf format specifier for any interger that is printed (e.g., "%14.7e").
248 ***********************************************************************************************************/
249
250LUPI_HOST void ContinuousEnergyGain::print( LUPI_maybeUnused ProtareSingle const *a_protareSingle, std::string const &a_indent, LUPI_maybeUnused std::string const &a_iFormat,
251 LUPI_maybeUnused std::string const &a_energyFormat, std::string const &a_dFormat ) const {
252
253 std::cout << std::endl;
254 std::cout << a_indent << "# Particle intid = " << m_particleIntid << std::endl;
255 std::cout << a_indent << "# Particle index = " << m_particleIndex << std::endl;
256 std::cout << a_indent << "# Use particle index = " << m_userParticleIndex << std::endl;
257
258 std::cout << a_indent << "# Number of gains = " << m_gain.size( ) << std::endl;
259 for( auto iter = m_gain.begin( ); iter != m_gain.end( ); ++iter )
260 std::cout << a_indent << LUPI::Misc::argumentsToString( a_dFormat.c_str( ), *iter ) << std::endl;
261}
262
263/*
264============================================================
265=========== HeatedCrossSectionContinuousEnergy =============
266============================================================
267*/
269 m_temperature( 0.0 ),
270 m_hashIndices( ),
271 m_energies( ),
272 m_totalCrossSection( ),
273 m_depositionEnergy( ),
274 m_depositionMomentum( ),
275 m_productionEnergy( ),
276 m_gains( ),
277 m_URR_mode( Transporting::URR_mode::none ),
278 m_reactionsInURR_region( ),
279 m_reactionCrossSections( ),
280 m_ACE_URR_probabilityTables( nullptr ) {
281
282}
283
284/* *********************************************************************************************************//**
285 * Fills in *this* with the requested temperature data.
286 *
287 * @param a_setupInfo [in] Used internally when constructing a Protare to pass information to other components.
288 * @param a_settings [in] Used to pass user options to the *this* to instruct it which data are desired.
289 * @param a_particles [in] List of transporting particles and their information (e.g., multi-group boundaries and fluxes).
290 * @param a_domainHash [in] The hash data used when looking up a cross section.
291 * @param a_temperatureInfo [in] The list of temperatures to use.
292 * @param a_reactions [in] The list of reactions to use.
293 * @param a_orphanProducts [in] The list of orphan products to use.
294 * @param a_fixedGrid [in] If true, the specified fixed grid is used; otherwise, grid in the file is used.
295 * @param a_zeroReactions [in] Special case where no reaction in a protare is wanted so the first one is used but its cross section is set to 0.0 at all energies.
296 ***********************************************************************************************************/
297
299 GIDI::Transporting::Particles const &a_particles, DomainHash const &a_domainHash, GIDI::Styles::TemperatureInfo const &a_temperatureInfo,
300 std::vector<GIDI::Reaction const *> const &a_reactions, std::vector<GIDI::Reaction const *> const &a_orphanProducts, bool a_fixedGrid,
301 bool a_zeroReactions ) :
302 m_temperature( a_temperatureInfo.temperature( ).value( ) ),
303 m_hashIndices( ),
304 m_energies( ),
305 m_totalCrossSection( ),
306 m_depositionEnergy( ),
307 m_depositionMomentum( ),
308 m_productionEnergy( ),
309 m_gains( ),
310 m_URR_mode( Transporting::URR_mode::none ),
311 m_reactionsInURR_region( ),
312 m_reactionCrossSections( ),
313 m_ACE_URR_probabilityTables( nullptr ) {
314
315 bool isPhotoAtomic = a_setupInfo.m_protare.isPhotoAtomic( );
316 std::string label( a_temperatureInfo.griddedCrossSection( ) );
317 std::string URR_label( a_temperatureInfo.URR_probabilityTables( ) );
318
319 GIDI::Styles::GriddedCrossSection const &griddedCrossSectionStyle =
320 static_cast<GIDI::Styles::GriddedCrossSection const &>( *a_settings.styles( )->get<GIDI::Styles::Base>( label ) );
321 GIDI::Grid const &grid = griddedCrossSectionStyle.grid( );
322
323 std::vector<double> const *energiesPointer;
324 std::vector<double> const &energies = grid.data( ).vector();
325 std::vector<double> const &fixedGridPoints = a_settings.fixedGridPoints( );
326 std::vector<int> fixedGridIndices( fixedGridPoints.size( ) );
327 if( a_fixedGrid ) {
328 for( std::size_t i1 = 0; i1 < fixedGridPoints.size( ); ++i1 ) {
329 fixedGridIndices[i1] = binarySearchVector( fixedGridPoints[i1], energies );
330 }
331 energiesPointer = &fixedGridPoints;
332 m_energies = fixedGridPoints; }
333 else {
334 energiesPointer = &energies;
335 m_energies = energies;
336 }
337
338 m_hashIndices = a_domainHash.map( m_energies );
339
340 std::size_t reactionIndex = 0;
341 GIDI::Axes axes;
342 std::vector<double> dummy;
344 GIDI::Functions::Ys1d fixedGridCrossSection( axes, ptwXY_interpolationLinLin, 0, fixedGridPoints );
345 m_reactionCrossSections.resize( a_reactions.size( ) );
346 m_URR_mode = Transporting::URR_mode::none;
347 for( std::vector<GIDI::Reaction const *>::const_iterator reactionIter = a_reactions.begin( ); reactionIter != a_reactions.end( ); ++reactionIter, ++reactionIndex ) {
348 GIDI::Suite const &reactionCrossSectionSuite = (*reactionIter)->crossSection( );
349 GIDI::Functions::Ys1d const *reactionCrossSection3 = reactionCrossSectionSuite.get<GIDI::Functions::Ys1d>( label );
350 GIDI::Functions::Ys1d *reactionCrossSectionZeroReactions = nullptr;
351 if( a_zeroReactions ) {
352 reactionCrossSectionZeroReactions = new GIDI::Functions::Ys1d( *reactionCrossSection3 );
353 for( std::size_t index = 0; index < reactionCrossSectionZeroReactions->size( ); ++index ) reactionCrossSectionZeroReactions->set( index, 0.0 );
354 reactionCrossSection3 = reactionCrossSectionZeroReactions;
355 }
356
357 Probabilities::ProbabilityBase2d *URR_probabilityTables = nullptr;
358 if( ( a_settings._URR_mode( ) == Transporting::URR_mode::pdfs ) && ( URR_label != "" ) ) {
359 if( reactionCrossSectionSuite.has( URR_label ) ) {
360 GIDI::Functions::URR_probabilityTables1d const &URR_probability_tables1d( *reactionCrossSectionSuite.get<GIDI::Functions::URR_probabilityTables1d>( URR_label ) );
361 URR_probabilityTables = Probabilities::parseProbability2d( URR_probability_tables1d.function2d( ), nullptr );
362 m_URR_mode = Transporting::URR_mode::pdfs;
363 }
364 }
365
366 ACE_URR_probabilityTables *ACE_URR_probabilityTables1 = nullptr;
368 auto URR_iter = a_setupInfo.m_ACE_URR_probabilityTablesFromGIDI.find( URR_label );
369 if( URR_iter != a_setupInfo.m_ACE_URR_probabilityTablesFromGIDI.end( ) ) {
370 auto ACE_URR_probabilityTablesIter = (*URR_iter).second->m_ACE_URR_probabilityTables.find( (*reactionIter)->label( ) );
371 if( ACE_URR_probabilityTablesIter != (*URR_iter).second->m_ACE_URR_probabilityTables.end( ) ) {
372 ACE_URR_probabilityTables1 = (*ACE_URR_probabilityTablesIter).second;
373 (*ACE_URR_probabilityTablesIter).second = nullptr; // Set to nullptr so destructor of m_ACE_URR_probabilityTables does not delete.
375 }
376 }
377 }
378
379 if( a_fixedGrid ) {
380 GIDI::Functions::Ys1d *reactionCrossSection4 = &fixedGridCrossSection;
381
382 std::size_t start = 0;
383
384 if( energies[reactionCrossSection3->start( )] > fixedGridPoints[0] ) {
385 int intStart = binarySearchVector( energies[reactionCrossSection3->start( )], fixedGridPoints ) + 1;
386 if (intStart < 0) {
387 throw std::out_of_range( "Cross section out of range when initializing fixed grid!" );
388 }
389 start = static_cast<std::size_t>( intStart );
390 }
391
392 for( std::size_t i1 = 0; i1 < start; ++i1 ) reactionCrossSection4->set( i1, 0.0 );
393 for( std::size_t i1 = start; i1 < fixedGridPoints.size( ); ++i1 ) {
394 std::size_t index = static_cast<std::size_t>( fixedGridIndices[i1] );
395 double fraction = ( fixedGridPoints[i1] - energies[index] ) / ( energies[index+1] - energies[index] );
396
397 index -= reactionCrossSection3->start( );
398 reactionCrossSection4->set( i1, ( 1.0 - fraction ) * (*reactionCrossSection3)[index] + fraction * (*reactionCrossSection3)[index+1] );
399 }
400 reactionCrossSection3 = &fixedGridCrossSection;
401 }
402
403 m_reactionCrossSections[reactionIndex] = new HeatedReactionCrossSectionContinuousEnergy( (*reactionIter)->crossSectionThreshold( ),
404 *reactionCrossSection3, URR_probabilityTables, ACE_URR_probabilityTables1 );
405 totalCrossSection += *reactionCrossSection3;
406
407 delete reactionCrossSectionZeroReactions;
408 }
409 m_totalCrossSection.resize( totalCrossSection.length( ), 0.0 );
410 for( std::size_t i1 = 0; i1 < totalCrossSection.size( ); ++i1 ) m_totalCrossSection[i1+totalCrossSection.start()] = totalCrossSection[i1];
411
412 if( hasURR_probabilityTables( ) ) {
413 std::vector<std::size_t> reactions_in_URR_region;
414
415 for( reactionIndex = 0; reactionIndex < numberOfReactions( ); ++reactionIndex ) {
416 if( m_reactionCrossSections[reactionIndex]->threshold( ) < URR_domainMax( ) ) {
417 reactions_in_URR_region.push_back( reactionIndex );
418 }
419 }
420
421 m_reactionsInURR_region.resize( reactions_in_URR_region.size( ) );
422 for( std::size_t i1 = 0; i1 < reactions_in_URR_region.size( ); ++i1 ) m_reactionsInURR_region[i1] = reactions_in_URR_region[i1];
423
425 auto URR_iter = a_setupInfo.m_ACE_URR_probabilityTablesFromGIDI.find( URR_label );
426 if( URR_iter != a_setupInfo.m_ACE_URR_probabilityTablesFromGIDI.end( ) ) {
427 auto ACE_URR_probabilityTablesIter = (*URR_iter).second->m_ACE_URR_probabilityTables.find( "total" );
428 if( ACE_URR_probabilityTablesIter != (*URR_iter).second->m_ACE_URR_probabilityTables.end( ) ) {
429 m_ACE_URR_probabilityTables = (*ACE_URR_probabilityTablesIter).second;
430 (*ACE_URR_probabilityTablesIter).second = nullptr; // Set to nullptr so destructor of m_ACE_URR_probabilityTables does not delete.
431 }
432 }
433 }
434 }
435
436 if( a_settings.addExpectedValueData( ) ) {
437 m_depositionEnergy.resize( totalCrossSection.length( ), 0.0 );
438 m_depositionMomentum.resize( totalCrossSection.length( ), 0.0 );
439 m_productionEnergy.resize( totalCrossSection.length( ), 0.0 );
440
441 m_gains.resize( a_particles.particles( ).size( ) );
442 std::size_t i2 = 0;
443 int projectileGainIndex = -1;
444 int photonGainIndex = -1;
445 for( std::map<std::string, GIDI::Transporting::Particle>::const_iterator particle = a_particles.particles( ).begin( ); particle != a_particles.particles( ).end( );
446 ++particle, ++i2 ) {
447 int particleIntid = a_setupInfo.m_particleIntids[particle->first];
448 int particleIndex = a_setupInfo.m_particleIndices[particle->first];
449
450 if( particleIntid == a_setupInfo.m_protare.projectileIntid( ) ) projectileGainIndex = (int) i2;
451 m_gains[i2] = new ContinuousEnergyGain( particleIntid, particleIndex, totalCrossSection.length( ) );
452 if( particle->first == PoPI::IDs::photon ) photonGainIndex = (int) i2;
453 }
454
455 std::vector< std::vector<double> > gains( a_particles.particles( ).size( ) );
456 for( std::size_t reactionIndex2 = 0; reactionIndex2 < a_reactions.size( ) + a_orphanProducts.size( ); ++reactionIndex2 ) {
457
458 std::size_t offset = 0;
459 std::vector<double> deposition_energy( m_energies.size( ), 0.0 );
460 std::vector<double> deposition_momentum( m_energies.size( ), 0.0 );
461 std::vector<double> production_energy( m_energies.size( ), 0.0 );
462 for( std::size_t i1 = 0; i1 < gains.size( ); ++i1 ) gains[i1] = std::vector<double>( m_energies.size( ), 0.0 );
463
464 HeatedReactionCrossSectionContinuousEnergy *MCGIDI_reaction_cross_section = nullptr;
465 GIDI::Reaction const *reaction = nullptr;
466 GIDI::Functions::Ys1d const *reactionCrossSection = nullptr; // If nullptr, reaction is an orphanProduct node.
467 GIDI::Functions::Function1dForm const *available_energy = nullptr;
468 GIDI::Functions::Function1dForm const *available_momentum = nullptr;
469 if( reactionIndex2 < a_reactions.size( ) ) {
470 reaction = a_reactions[reactionIndex2];
471 available_energy = reaction->availableEnergy( ).get<GIDI::Functions::Function1dForm>( 0 );
472 available_momentum = reaction->availableMomentum( ).get<GIDI::Functions::Function1dForm>( 0 );
473 MCGIDI_reaction_cross_section = m_reactionCrossSections[reactionIndex2];
474 offset = MCGIDI_reaction_cross_section->offset( ); }
475 else {
476 reaction = a_orphanProducts[reactionIndex2-a_reactions.size( )];
477 GIDI::Suite const &reactionCrossSectionSuite = reaction->crossSection( );
478 reactionCrossSection = reactionCrossSectionSuite.get<GIDI::Functions::Ys1d>( label );
479 offset = reactionCrossSection->start( );
480 }
481 if( a_settings.useSlowerContinuousEnergyConversion( ) ) { // Old way which is slow as it does one energy at a time.
482 for( std::size_t energy_index = offset; energy_index < m_energies.size( ); ++energy_index ) {
483 double energy = m_energies[energy_index];
484
485 if( reactionCrossSection == nullptr ) {
486 if( isPhotoAtomic ) { // Treat as Q = 0.0 since 2 photons will be emitted.
487 deposition_energy[energy_index] = energy; }
488 else {
489 deposition_energy[energy_index] = available_energy->evaluate( energy );
490
491 double Q = deposition_energy[energy_index] - energy; // Should use Q node to get this.
492 if( fabs( Q ) < 1e-12 * deposition_energy[energy_index] )
493 Q = 0.0; // Probably 0.0 due to rounding errors.
494 production_energy[energy_index] = Q;
495 }
496 deposition_momentum[energy_index] = available_momentum->evaluate( energy );
497 }
498
499 std::size_t i1 = 0;
500 for( std::map<std::string, GIDI::Transporting::Particle>::const_iterator particle = a_particles.particles( ).begin( ); particle != a_particles.particles( ).end( );
501 ++particle, ++i1 ) {
502 double product_energy, product_momentum, product_gain;
503
504 if( particle->first == PoPI::IDs::electron ) continue; // As of this coding, electrons are not complete in GNDS files.
505 // When they are, this statement can be removed.
506 if( ( reactionCrossSection != nullptr ) && ( particle->first != PoPI::IDs::photon ) ) continue;
507
508 if( reaction->isPairProduction( ) && ( particle->first == PoPI::IDs::photon ) ) {
509 product_energy = 2.0 * PoPI_electronMass_MeV_c2; // Assumes energy unit is MeV.
510 product_momentum = 0.0;
511 product_gain = 2.0; }
512 else {
513 reaction->continuousEnergyProductData( a_settings, particle->first, energy, product_energy, product_momentum,
514 product_gain, true );
515 }
516 if( (int) i1 == projectileGainIndex ) --product_gain;
517
518 deposition_energy[energy_index] -= product_energy;
519 deposition_momentum[energy_index] -= product_momentum;
520 gains[i1][energy_index] = product_gain;
521 }
522 } }
523 else { // New way which is hopefully faster.
524 if( reactionCrossSection == nullptr ) {
525 if( isPhotoAtomic ) { // Treat as Q = 0.0 since 2 photons will be emitted.
526 for( std::size_t energyIndex = offset; energyIndex < m_energies.size( ); ++energyIndex ) {
527 deposition_energy[energyIndex] = m_energies[energyIndex];
528 } }
529 else {
530 available_energy->mapToXsAndAdd( offset, *energiesPointer, deposition_energy, 1.0 );
531 for( std::size_t energyIndex = offset; energyIndex < m_energies.size( ); ++energyIndex ) {
532 double Q = deposition_energy[energyIndex] - m_energies[energyIndex];
533 if( fabs( Q ) < 1e-12 * deposition_energy[energyIndex] )
534 Q = 0.0; // Probably 0.0 due to rounding errors.
535 production_energy[energyIndex] = Q;
536 }
537 }
538 available_momentum->mapToXsAndAdd( offset, *energiesPointer, deposition_momentum, 1.0 );
539 }
540
541 std::size_t i1 = 0;
542 for( std::map<std::string, GIDI::Transporting::Particle>::const_iterator particle = a_particles.particles( ).begin( );
543 particle != a_particles.particles( ).end( ); ++particle, ++i1 ) {
544 if( particle->first == PoPI::IDs::electron ) continue; // As of this coding, electrons are not complete in GNDS files.
545 // When they are, this statement can be removed.
546 if( ( reactionCrossSection != nullptr ) && ( particle->first != PoPI::IDs::photon ) ) continue;
547
548 if( reaction->isPairProduction( ) && ( particle->first == PoPI::IDs::photon ) ) {
549 for( std::size_t energyIndex = offset; energyIndex < m_energies.size( ); ++energyIndex ) {
550 deposition_energy[energyIndex] -= 2.0 * PoPI_electronMass_MeV_c2; // Assumes energy unit is MeV.
551 gains[i1][energyIndex] = 2.0;
552 } }
553 else {
554 reaction->mapContinuousEnergyProductData( a_settings, particle->first, *energiesPointer, offset, deposition_energy,
555 deposition_momentum, gains[i1], true );
556 }
557
558 if( (int) i1 == projectileGainIndex ) {
559 for( std::size_t energyIndex = offset; energyIndex < m_energies.size( ); ++energyIndex ) --gains[i1][energyIndex];
560 }
561 }
562 }
563
564 if( a_particles.hasParticle( PoPI::IDs::photon ) ) {
565 if( a_setupInfo.m_initialStateIndices.find( reaction->label( ) ) != a_setupInfo.m_initialStateIndices.end( ) ) {
566 int intInitialStateIndex = a_setupInfo.m_initialStateIndices[reaction->label( )];
567 if( intInitialStateIndex >= 0 ) {
568 std::size_t initialStateIndex = static_cast<std::size_t>( intInitialStateIndex );
569 NuclideGammaBranchStateInfo *nuclideGammaBranchStateInfo = a_setupInfo.m_protare.nuclideGammaBranchStateInfos( )[initialStateIndex];
570 double multiplicity = nuclideGammaBranchStateInfo->multiplicity( );
571 double averageGammaEnergy = nuclideGammaBranchStateInfo->averageGammaEnergy( );
572
573 for( std::size_t energyIndex = offset; energyIndex < m_energies.size( ); ++energyIndex ) {
574 deposition_energy[energyIndex] -= averageGammaEnergy;
575 if( photonGainIndex >= 0 ) gains[static_cast<std::size_t>(photonGainIndex)][energyIndex] += multiplicity;
576 }
577 }
578 }
579 }
580
581 double crossSection = 0.0;
582 for( std::size_t energyIndex = offset; energyIndex < m_energies.size( ); ++energyIndex ) {
583 if( reactionCrossSection == nullptr ) {
584 crossSection = MCGIDI_reaction_cross_section->crossSection( energyIndex ); }
585 else {
586 crossSection = (*reactionCrossSection)[energyIndex-offset];
587 }
588
589 m_depositionEnergy[energyIndex] += crossSection * deposition_energy[energyIndex];
590 m_depositionMomentum[energyIndex] += crossSection * deposition_momentum[energyIndex];
591 m_productionEnergy[energyIndex] += crossSection * production_energy[energyIndex];
592 for( std::size_t i1 = 0; i1 < m_gains.size( ); ++i1 ) {
593 m_gains[i1]->adjustGain( energyIndex, crossSection * gains[i1][energyIndex] );
594 }
595 }
596 }
597 }
598}
599
600/* *********************************************************************************************************//**
601 ***********************************************************************************************************/
602
604
605 for( auto iter = m_reactionCrossSections.begin( ); iter < m_reactionCrossSections.end( ); ++iter ) delete *iter;
606 for( auto iter = m_gains.begin( ); iter < m_gains.end( ); ++iter ) delete *iter;
607 delete m_ACE_URR_probabilityTables;
608}
609
610
611/* *********************************************************************************************************//**
612 * This function returns the index in *a_energies* where *a_energy* lies between the returned index and the next index.
613 * The returned index must lie between a_hashIndices[a_hashIndex] and a_hashIndices[a_hashIndex+1].
614 * If *a_energy* is below the domain of *a_energies*, 0 is returned. If *a_energy* is above the domain of *a_energies*,
615 * the size of *a_energies* minus 2 is returned.
616 * The argument *a_energyFraction* the weight for the energy at the returned index with the next index getting weighting 1 minus
617 * *a_energyFraction*.
618 *
619 * @param a_hashIndex [in] Specifies projectile energy hash index.
620 * @param a_energy [in] The energy whose index is requested.
621 * @param a_energyFraction [in] This represents the weighting to apply to the two bounding energies.
622 *
623 * @return The index bounding *a_energy* in the member *m_energies*.
624 ***********************************************************************************************************/
625
626LUPI_HOST_DEVICE std::size_t HeatedCrossSectionContinuousEnergy::evaluationInfo( std::size_t a_hashIndex, double a_energy, double *a_energyFraction ) const {
627
628 return Sampling::evaluationForHashIndex( a_hashIndex, m_hashIndices, a_energy, m_energies, a_energyFraction );
629}
630
631/* *********************************************************************************************************//**
632 * Returns true if *this* has a unresolved resonance region (URR) data and false otherwise.
633 *
634 * @return true is if *this* has a URR data.
635 ***********************************************************************************************************/
636
641
642/* *********************************************************************************************************//**
643 * Returns the minimum energy for the unresolved resonance region (URR) domain. If no URR data present, returns -1.
644 *
645 * @return true is if *this* has a URR data.
646 ***********************************************************************************************************/
647
649
650 if( m_ACE_URR_probabilityTables != nullptr ) return( m_ACE_URR_probabilityTables->domainMin( ) );
651
652 for( std::size_t i1 = 0; i1 < m_reactionCrossSections.size( ); ++i1 ) {
654
655 if( reactionCrossSection->hasURR_probabilityTables( ) ) return( reactionCrossSection->URR_domainMin( ) );
656 }
657
658 return( -1.0 );
659}
660
661/* *********************************************************************************************************//**
662 * Returns the maximum energy for the unresolved resonance region (URR) domain. If no URR data present, returns -1.
663 *
664 * @return true is if *this* has a URR data.
665 ***********************************************************************************************************/
666
668
669 if( m_ACE_URR_probabilityTables != nullptr ) return( m_ACE_URR_probabilityTables->domainMax( ) );
670
671 for( std::size_t i1 = 0; i1 < m_reactionCrossSections.size( ); ++i1 ) {
673
674 if( reactionCrossSection->hasURR_probabilityTables( ) ) return( reactionCrossSection->URR_domainMax( ) );
675 }
676
677 return( -1.0 );
678}
679/*
680=========================================================
681*/
683 std::size_t a_hashIndex, double a_energy, LUPI_maybeUnused bool a_sampling ) const {
684
685 double energy_fraction;
686 std::size_t energy_index = evaluationInfo( a_hashIndex, a_energy, &energy_fraction );
687
688 if( a_URR_index >= 0 ) {
689 URR_protareInfo const &URR_protare_info = a_URR_protareInfos[static_cast<std::size_t>(a_URR_index)];
690
691 if( URR_protare_info.m_inURR ) {
692 double cross_section = 0.0;
693 for( std::size_t i1 = 0; i1 < m_reactionsInURR_region.size( ); ++i1 ) {
694 cross_section += reactionCrossSection2( m_reactionsInURR_region[i1], a_URR_protareInfos, a_URR_index, a_energy,
695 energy_index, energy_fraction, false );
696 }
697 return( cross_section );
698 }
699 }
700
701 return( energy_fraction * m_totalCrossSection[energy_index] + ( 1.0 - energy_fraction ) * m_totalCrossSection[energy_index+1] );
702}
703/*
704=========================================================
705*/
706LUPI_HOST_DEVICE double HeatedCrossSectionContinuousEnergy::reactionCrossSection( std::size_t a_reactionIndex, URR_protareInfos const &a_URR_protareInfos,
707 int a_URR_index, std::size_t a_hashIndex, double a_energy, LUPI_maybeUnused bool a_sampling ) const {
708
709 double energyFraction;
710
711 std::size_t energyIndex = evaluationInfo( a_hashIndex, a_energy, &energyFraction );
712 return( reactionCrossSection2( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_energy, energyIndex, energyFraction ) );
713}
714/*
715=========================================================
716*/
717LUPI_HOST_DEVICE double HeatedCrossSectionContinuousEnergy::reactionCrossSection2( std::size_t a_reactionIndex, URR_protareInfos const &a_URR_protareInfos,
718 int a_URR_index, double a_energy, std::size_t a_energyIndex, double a_energyFraction, LUPI_maybeUnused bool a_sampling ) const {
719
720 HeatedReactionCrossSectionContinuousEnergy const &reaction = *m_reactionCrossSections[a_reactionIndex];
721 double URR_cross_section_factor = 1.0;
722
723 if( a_URR_index >= 0 ) {
724 URR_protareInfo const &URR_protare_info = a_URR_protareInfos[static_cast<std::size_t>(a_URR_index)];
725 if( URR_protare_info.m_inURR ) {
726 if( m_URR_mode == Transporting::URR_mode::pdfs ) {
727 if( reaction.URR_probabilityTables( ) != nullptr )
728 URR_cross_section_factor = reaction.URR_probabilityTables( )->sample( a_energy, URR_protare_info.m_rng_Value, []() -> double { return 0.0; } ); }
730 if( reaction._ACE_URR_probabilityTables( ) != nullptr )
731 URR_cross_section_factor = reaction._ACE_URR_probabilityTables( )->sample( a_energy, URR_protare_info.m_rng_Value );
732 }
733 }
734 }
735
736 return( URR_cross_section_factor * ( a_energyFraction * reaction.crossSection( a_energyIndex ) + ( 1.0 - a_energyFraction ) * reaction.crossSection( a_energyIndex + 1 ) ) );
737}
738
739/*
740=========================================================
741*/
743 URR_protareInfos const &a_URR_protareInfos, int a_URR_index, double a_energy_in ) const {
744
745 int intEnergyIndex = binarySearchVector( a_energy_in, m_energies );
746 std::size_t energyIndex = static_cast<std::size_t>( intEnergyIndex );
747 double energyFraction;
748
749 if( intEnergyIndex < 0 ) {
750 if( intEnergyIndex == -1 ) {
751 energyIndex = m_energies.size( ) - 2;
752 energyFraction = 0.0; }
753 else {
754 energyIndex = 0;
755 energyFraction = 1.0;
756 } }
757 else {
758 energyFraction = ( m_energies[energyIndex+1] - a_energy_in ) / ( m_energies[energyIndex+1] - m_energies[energyIndex] );
759 }
760
761 return( reactionCrossSection2( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_energy_in, energyIndex, energyFraction, false ) );
762}
763
764/* *********************************************************************************************************//**
765 * Returns the total cross section as a GIDI::Functions::XYs1d instance.
766 *
767 * @returns A GIDI::Functions::XYs1d instance.
768 ***********************************************************************************************************/
769
771
772 std::vector<double> energies = vectorToSTD_vector( m_energies );
773 std::vector<double> crossSection = vectorToSTD_vector( m_totalCrossSection );
774
776}
777
778/* *********************************************************************************************************//**
779 * Returns the reaction's cross section as GIDI::Functions::XYs1d instance.
780 *
781 * @param a_reactionIndex [in] Specifies the indexs of the reaction whose cross section is requested.
782 *
783 * @returns A GIDI::Functions::XYs1d instance.
784 ***********************************************************************************************************/
785
787
788 return( m_reactionCrossSections[a_reactionIndex]->crossSectionAsGIDI_XYs1d( m_temperature, m_energies ) );
789}
790
791/* *********************************************************************************************************//**
792 * Returns the index of a sampled reaction for a projectile with energy *a_energy* and total cross section
793 * *a_crossSection*. Random numbers are obtained via *a_userrng* and *a_rngState*.
794 *
795 * @param a_hashIndex [in] Specifies projectile energy hash index.
796 * @param a_energy [in] The energy of the projectile.
797 ***********************************************************************************************************/
798
799LUPI_HOST_DEVICE double HeatedCrossSectionContinuousEnergy::depositionEnergy( std::size_t a_hashIndex, double a_energy ) const {
800
801 double energy_fraction;
802 std::size_t energy_index = evaluationInfo( a_hashIndex, a_energy, &energy_fraction );
803
804 return( energy_fraction * m_depositionEnergy[energy_index] + ( 1.0 - energy_fraction ) * m_depositionEnergy[energy_index+1] );
805}
806
807/* *********************************************************************************************************//**
808 * Returns the index of a sampled reaction for a projectile with energy *a_energy* and total cross section
809 * *a_crossSection*. Random numbers are obtained via *a_userrng* and *a_rngState*.
810 *
811 * @param a_hashIndex [in] Specifies projectile energy hash index.
812 * @param a_energy [in] The energy of the projectile.
813 ***********************************************************************************************************/
814
815LUPI_HOST_DEVICE double HeatedCrossSectionContinuousEnergy::depositionMomentum( std::size_t a_hashIndex, double a_energy ) const {
816
817 double energy_fraction;
818 std::size_t energy_index = evaluationInfo( a_hashIndex, a_energy, &energy_fraction );
819
820 return( energy_fraction * m_depositionMomentum[energy_index] + ( 1.0 - energy_fraction ) * m_depositionMomentum[energy_index+1] );
821}
822
823/* *********************************************************************************************************//**
824 * Returns the index of a sampled reaction for a projectile with energy *a_energy* and total cross section
825 * *a_crossSection*. Random numbers are obtained via *a_userrng* and *a_rngState*.
826 *
827 * @param a_hashIndex [in] Specifies projectile energy hash index.
828 * @param a_energy [in] The energy of the projectile.
829 ***********************************************************************************************************/
830
831LUPI_HOST_DEVICE double HeatedCrossSectionContinuousEnergy::productionEnergy( std::size_t a_hashIndex, double a_energy ) const {
832
833 double energy_fraction;
834 std::size_t energy_index = evaluationInfo( a_hashIndex, a_energy, &energy_fraction );
835
836 return( energy_fraction * m_productionEnergy[energy_index] + ( 1.0 - energy_fraction ) * m_productionEnergy[energy_index+1] );
837}
838
839/* *********************************************************************************************************//**
840 * Returns the gain for the particle with index *a_particleIndex* for projectile energy *a_energy*.
841 *
842 * @param a_hashIndex [in] Specifies projectile energy hash index.
843 * @param a_energy [in] The energy of the projectile.
844 * @param a_particleIndex [in] The index of the particle whose gain is requested.
845 ***********************************************************************************************************/
846
847LUPI_HOST_DEVICE double HeatedCrossSectionContinuousEnergy::gain( std::size_t a_hashIndex, double a_energy, int a_particleIndex ) const {
848
849 double energy_fraction;
850 std::size_t energy_index = evaluationInfo( a_hashIndex, a_energy, &energy_fraction );
851
852 for( std::size_t i1 = 0; i1 < m_gains.size( ); ++i1 ) {
853 if( a_particleIndex == m_gains[i1]->particleIndex( ) ) return( m_gains[i1]->gain( energy_index, energy_fraction ) );
854 }
855
856 return( 0.0 );
857}
858
859/* *********************************************************************************************************//**
860 * Returns the gain for the particle with intid *a_particleIntid* for projectile energy *a_energy*.
861 *
862 * @param a_hashIndex [in] Specifies projectile energy hash index.
863 * @param a_energy [in] The energy of the projectile.
864 * @param a_particleIntid [in] The intid of the particle whose gain is requested.
865 ***********************************************************************************************************/
866
867LUPI_HOST_DEVICE double HeatedCrossSectionContinuousEnergy::gainViaIntid( std::size_t a_hashIndex, double a_energy, int a_particleIntid ) const {
868
869 double energy_fraction;
870 std::size_t energy_index = evaluationInfo( a_hashIndex, a_energy, &energy_fraction );
871
872 for( std::size_t i1 = 0; i1 < m_gains.size( ); ++i1 ) {
873 if( a_particleIntid == m_gains[i1]->particleIntid( ) ) return( m_gains[i1]->gain( energy_index, energy_fraction ) );
874 }
875
876 return( 0.0 );
877}
878
879/* *********************************************************************************************************//**
880 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs index *a_particleIndex*.
881 *
882 * @param a_particleIndex [in] The PoPs index of the particle whose user index is to be set.
883 * @param a_userParticleIndex [in] The particle index specified by the user.
884 ***********************************************************************************************************/
885
886LUPI_HOST void HeatedCrossSectionContinuousEnergy::setUserParticleIndex( int a_particleIndex, int a_userParticleIndex ) {
887
888 for( auto iter = m_gains.begin( ); iter != m_gains.end( ); ++iter ) (*iter)->setUserParticleIndex( a_particleIndex, a_userParticleIndex );
889}
890
891/* *********************************************************************************************************//**
892 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs intid *a_particleIntid*.
893 *
894 * @param a_particleIntid [in] The intid of the particle whose user index is to be set.
895 * @param a_userParticleIndex [in] The particle index specified by the user.
896 ***********************************************************************************************************/
897
898LUPI_HOST void HeatedCrossSectionContinuousEnergy::setUserParticleIndexViaIntid( int a_particleIntid, int a_userParticleIndex ) {
899
900 for( auto iter = m_gains.begin( ); iter != m_gains.end( ); ++iter ) (*iter)->setUserParticleIndexViaIntid( a_particleIntid, a_userParticleIndex );
901}
902
903/* *********************************************************************************************************//**
904 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
905 * bytes, pack *this* or unpack *this* depending on *a_mode*.
906 *
907 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
908 * @param a_mode [in] Specifies the action of this method.
909 ***********************************************************************************************************/
910
912
913 DATA_MEMBER_DOUBLE( m_temperature, a_buffer, a_mode );
914 DATA_MEMBER_VECTOR_SIZE_T( m_hashIndices, a_buffer, a_mode );
915 DATA_MEMBER_VECTOR_DOUBLE( m_energies, a_buffer, a_mode );
916 DATA_MEMBER_VECTOR_FLOAT_OR_DOUBLE( m_totalCrossSection, a_buffer, a_mode );
917 DATA_MEMBER_VECTOR_FLOAT_OR_DOUBLE( m_depositionEnergy, a_buffer, a_mode );
918 DATA_MEMBER_VECTOR_FLOAT_OR_DOUBLE( m_depositionMomentum, a_buffer, a_mode );
919 DATA_MEMBER_VECTOR_FLOAT_OR_DOUBLE( m_productionEnergy, a_buffer, a_mode );
920 m_URR_mode = serializeURR_mode( m_URR_mode, a_buffer, a_mode );
921 DATA_MEMBER_VECTOR_SIZE_T( m_reactionsInURR_region, a_buffer, a_mode );
922 m_ACE_URR_probabilityTables = serializeACE_URR_probabilityTables( m_ACE_URR_probabilityTables, a_buffer, a_mode );
923
924 std::size_t vectorSize = m_reactionCrossSections.size( );
925 int vectorSizeInt = (int) vectorSize;
926 DATA_MEMBER_INT( vectorSizeInt, a_buffer, a_mode );
927 vectorSize = (std::size_t) vectorSizeInt;
928
929 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) m_reactionCrossSections.resize( vectorSize, &a_buffer.m_placement );
930 if( a_mode == LUPI::DataBuffer::Mode::Memory ) a_buffer.m_placement += m_reactionCrossSections.internalSize();
931 for( std::size_t memberIndex = 0; memberIndex < vectorSize; ++memberIndex ) {
932 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
933 if( a_buffer.m_placement != nullptr ) {
934 m_reactionCrossSections[memberIndex] = new(a_buffer.m_placement) HeatedReactionCrossSectionContinuousEnergy;
936 else {
937 m_reactionCrossSections[memberIndex] = new HeatedReactionCrossSectionContinuousEnergy;
938 }
939 }
940 if( a_mode == LUPI::DataBuffer::Mode::Memory ) {
942 }
943 m_reactionCrossSections[memberIndex]->serialize( a_buffer, a_mode );
944 }
945
946 vectorSize = m_gains.size( );
947 vectorSizeInt = (int) vectorSize;
948 DATA_MEMBER_INT( vectorSizeInt, a_buffer, a_mode );
949 vectorSize = (std::size_t) vectorSizeInt;
950 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) m_gains.resize( vectorSize, &a_buffer.m_placement );
951 if( a_mode == LUPI::DataBuffer::Mode::Memory ) a_buffer.m_placement += m_gains.internalSize();
952 for( std::size_t memberIndex = 0; memberIndex < vectorSize; ++memberIndex ) {
953 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
954 if( a_buffer.m_placement != nullptr ) {
955 m_gains[memberIndex] = new(a_buffer.m_placement) ContinuousEnergyGain;
956 a_buffer.incrementPlacement( sizeof( ContinuousEnergyGain ) ); }
957 else {
958 m_gains[memberIndex] = new ContinuousEnergyGain;
959 }
960 }
961
962 if( a_mode == LUPI::DataBuffer::Mode::Memory ) {
963 a_buffer.incrementPlacement( sizeof( ContinuousEnergyGain ) );
964 }
965 m_gains[memberIndex]->serialize( a_buffer, a_mode );
966 }
967}
968
969/* *********************************************************************************************************//**
970 * Print to *std::cout* the content of *this*. This is mainly meant for debugging.
971 *
972 * @param a_protareSingle [in] The ProtareSingle instance *this* resides in.
973 * @param a_indent [in] The buffer to read or write data to depending on *a_mode*.
974 * @param a_iFormat [in] C printf format specifier for any interger that is printed (e.g., "%3d").
975 * @param a_energyFormat [in] C printf format specifier for any interger that is printed (e.g., "%20.12e").
976 * @param a_dFormat [in] C printf format specifier for any interger that is printed (e.g., "%14.7e").
977 ***********************************************************************************************************/
978
979LUPI_HOST void HeatedCrossSectionContinuousEnergy::print( ProtareSingle const *a_protareSingle, std::string const &a_indent,
980 std::string const &a_iFormat, std::string const &a_energyFormat, std::string const &a_dFormat ) const {
981
982 char const *dFormat = a_dFormat.c_str( );
983 std::string indent2 = a_indent + " ";
984 std::string lineFormat = indent2 + a_energyFormat + " " + a_dFormat + " " + a_dFormat + " " + a_dFormat + " " + a_dFormat;
985
986 std::cout << std::endl;
987 std::cout << a_indent << "# Temperature = " << LUPI::Misc::doubleToString3( dFormat, m_temperature, true ) << std::endl;
988
989 std::cout << a_indent << "# Number of hash indices = " << m_hashIndices.size( ) << std::endl;
990 for( auto iter = m_hashIndices.begin( ); iter != m_hashIndices.end( ); ++iter )
991 std::cout << indent2 << LUPI::Misc::argumentsToString( a_iFormat.c_str( ), *iter ) << std::endl;
992 std::cout << std::endl;
993 std::size_t energySize = m_energies.size( );
994 std::cout << a_indent << "# Number of energies = " << m_energies.size( ) << std::endl;
995 std::cout << "# projectile total deposition deposition production" << std::endl;
996 std::cout << "# energy cross section energy momentum energy"<< std::endl;
997 std::cout << "#====================================================================================================="<< std::endl;
998 for( std::size_t index = 0; index != energySize; ++index ) {
999 std::cout << LUPI::Misc::argumentsToString( lineFormat.c_str( ), m_energies[index], m_totalCrossSection[index], m_depositionEnergy[index],
1000 m_depositionMomentum[index], m_productionEnergy[index] ) << std::endl;
1001 }
1002
1003 for( auto iter = m_gains.begin( ); iter != m_gains.end( ); ++iter ) (*iter)->print( a_protareSingle, a_indent, a_iFormat, a_energyFormat, a_dFormat );
1004
1005 std::cout << std::endl;
1006 std::cout << "# URR mode is ";
1007 if( m_URR_mode == Transporting::URR_mode::none ) {
1008 std::cout << "none" << std::endl; }
1009 else if( m_URR_mode == Transporting::URR_mode::pdfs ) {
1010 std::cout << "pdfs" << std::endl; }
1011 else if( m_URR_mode == Transporting::URR_mode::ACE_URR_probabilityTables ) {
1012 std::cout << "ACE style protability tables" << std::endl; }
1013 else {
1014 std::cout << "Oops, need to code into print method." << std::endl;
1015 }
1016
1017 std::cout << a_indent << "# Index of reactions in URR region:";
1018 for( auto reactionIter = m_reactionsInURR_region.begin( ); reactionIter != m_reactionsInURR_region.end( ); ++reactionIter ) {
1019 std::cout << indent2 << LUPI::Misc::argumentsToString( a_iFormat.c_str( ), *reactionIter ) << std::endl;
1020 }
1021 std::cout << std::endl;
1022
1023 std::size_t reactionIndex = 0;
1024 std::cout << std::endl;
1025 std::cout << a_indent << "# Number of reactions = " << m_reactionCrossSections.size( ) << std::endl;
1026 for( auto iter = m_reactionCrossSections.begin( ); iter != m_reactionCrossSections.end( ); ++iter, ++reactionIndex ) {
1027 Reaction const *reaction = a_protareSingle->reaction( reactionIndex );
1028
1029 std::cout << a_indent << "# Reaction number " << reactionIndex << std::endl;
1030 std::cout << a_indent << "# Reaction label: " << reaction->label( ).c_str( ) << std::endl;
1031 (*iter)->print( a_protareSingle, a_indent, a_iFormat, a_energyFormat, a_dFormat );
1032 }
1033}
1034
1035/*
1036============================================================
1037=========== HeatedCrossSectionsContinuousEnergy ============
1038============================================================
1039*/
1041 m_temperatures( ),
1042 m_thresholds( ),
1043 m_heatedCrossSections( ) {
1044
1045}
1046
1047/* *********************************************************************************************************//**
1048 ***********************************************************************************************************/
1049
1054
1055/* *********************************************************************************************************//**
1056 ***********************************************************************************************************/
1057
1059
1060 for( Vector<HeatedCrossSectionContinuousEnergy *>::const_iterator iter = m_heatedCrossSections.begin( ); iter != m_heatedCrossSections.end( ); ++iter ) delete *iter;
1061 m_heatedCrossSections.clear( );
1062}
1063
1064/* *********************************************************************************************************//**
1065 * Fills in *this* with the requested temperature data.
1066 *
1067 * @param a_smr [Out] If errors are not to be thrown, then the error is reported via this instance.
1068 * @param a_setupInfo [in] Used internally when constructing a Protare to pass information to other components.
1069 * @param a_settings [in] Used to pass user options to the *this* to instruct it which data are desired.
1070 * @param a_particles [in] List of transporting particles and their information (e.g., multi-group boundaries and fluxes).
1071 * @param a_domainHash [in] The hash data used when looking up a cross section.
1072 * @param a_temperatureInfos [in] The list of temperatures to use.
1073 * @param a_reactions [in] The list of reactions to use.
1074 * @param a_orphanProducts [in] The list of orphan products to use.
1075 * @param a_fixedGrid [in] If true, the specified fixed grid is used; otherwise, grid in the file is used.
1076 * @param a_zeroReactions [in] Special case where no reaction in a protare is wanted so the first one is used but its cross section is set to 0.0 at all energies.
1077 ***********************************************************************************************************/
1078
1080 Transporting::MC const &a_settings, GIDI::Transporting::Particles const &a_particles, DomainHash const &a_domainHash,
1081 GIDI::Styles::TemperatureInfos const &a_temperatureInfos, std::vector<GIDI::Reaction const *> const &a_reactions,
1082 std::vector<GIDI::Reaction const *> const &a_orphanProducts, bool a_fixedGrid, bool a_zeroReactions ) {
1083
1084 m_temperatures.reserve( a_temperatureInfos.size( ) );
1085 m_heatedCrossSections.reserve( a_temperatureInfos.size( ) );
1086
1087 for( GIDI::Styles::TemperatureInfos::const_iterator iter = a_temperatureInfos.begin( ); iter != a_temperatureInfos.end( ); ++iter ) {
1088 m_temperatures.push_back( iter->temperature( ).value( ) );
1089 m_heatedCrossSections.push_back( new HeatedCrossSectionContinuousEnergy( a_setupInfo, a_settings, a_particles, a_domainHash, *iter,
1090 a_reactions, a_orphanProducts, a_fixedGrid, a_zeroReactions ) );
1091 }
1092
1093 m_thresholds.resize( m_heatedCrossSections[0]->numberOfReactions( ) );
1094 for( std::size_t i1 = 0; i1 < m_heatedCrossSections[0]->numberOfReactions( ); ++i1 ) m_thresholds[i1] = m_heatedCrossSections[0]->threshold( i1 );
1095}
1096
1097/* *********************************************************************************************************//**
1098 * Returns the cross section for target temperature *a_temperature* and projectile energy *a_energy*.
1099 *
1100 * @param a_URR_protareInfos [in] URR information.
1101 * @param a_URR_index [in] If not negative, specifies the index in *a_URR_protareInfos*.
1102 * @param a_hashIndex [in] Specifies projectile energy hash index.
1103 * @param a_temperature [in] The temperature of the target.
1104 * @param a_energy [in] The energy of the projectile.
1105 * @param a_sampling [in] If *true* the cross section is to be used for sampling, otherwise, just for looking up.
1106 ***********************************************************************************************************/
1107
1109 std::size_t a_hashIndex, double a_temperature, double a_energy, bool a_sampling ) const {
1110
1111 double cross_section;
1112
1113 if( a_temperature <= m_temperatures[0] ) {
1114 cross_section = m_heatedCrossSections[0]->crossSection( a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling ); }
1115 else if( a_temperature >= m_temperatures.back( ) ) {
1116 cross_section = m_heatedCrossSections.back( )->crossSection( a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling ); }
1117 else {
1118 std::size_t i1;
1119 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1120 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1121 cross_section = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->crossSection( a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling )
1122 + fraction * m_heatedCrossSections[i1]->crossSection( a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling );
1123 }
1124
1125 return( cross_section );
1126}
1127
1128/* *********************************************************************************************************//**
1129 * Adds the energy dependent, total cross section corresponding to the temperature *a_temperature* multiplied by *a_userFactor* to *a_crossSectionVector*.
1130 * This function only works for fixed-grid data.
1131 *
1132 * @param a_temperature [in] Specifies the temperature of the material.
1133 * @param a_userFactor [in] User factor which all cross sections are multiplied by.
1134 * @param a_numberAllocated [in] The length of memory allocated for *a_crossSectionVector*.
1135 * @param a_crossSectionVector [in/out] The energy dependent, total cross section to add cross section data to.
1136 ***********************************************************************************************************/
1137
1138LUPI_HOST_DEVICE void HeatedCrossSectionsContinuousEnergy::crossSectionVector( double a_temperature, double a_userFactor,
1139 std::size_t a_numberAllocated, double *a_crossSectionVector ) const {
1140
1141 std::size_t index1 = 0, index2 = 0;
1142 double fraction = 0.0;
1143
1144 if( a_temperature <= m_temperatures[0] ) {
1145 }
1146 else if( a_temperature >= m_temperatures.back( ) ) {
1147 index1 = index2 = m_temperatures.size( ) - 1;
1148 fraction = 1.0; }
1149 else {
1150 for( ; index2 < m_temperatures.size( ); ++index2 ) if( a_temperature < m_temperatures[index2] ) break;
1151 index1 = index2 - 1;
1152 fraction = ( a_temperature - m_temperatures[index1] ) / ( m_temperatures[index2] - m_temperatures[index1] );
1153 }
1154
1155 Vector<MCGIDI_FLOAT> &totalCrossSection1 = m_heatedCrossSections[index1]->totalCrossSection( );
1156 Vector<MCGIDI_FLOAT> &totalCrossSection2 = m_heatedCrossSections[index2]->totalCrossSection( );
1157 std::size_t size = totalCrossSection1.size( );
1158 double factor1 = a_userFactor * ( 1.0 - fraction ), factor2 = a_userFactor * fraction;
1159
1160 if( a_numberAllocated < totalCrossSection1.size( ) ) LUPI_THROW( "HeatedCrossSectionsContinuousEnergy::crossSectionVector: a_numberAllocated too small." );
1161 for( std::size_t i1 = 0; i1 < size; ++i1 ) {
1162 a_crossSectionVector[i1] += factor1 * totalCrossSection1[i1] + factor2 * totalCrossSection2[i1];
1163 }
1164}
1165
1166/* *********************************************************************************************************//**
1167 * Returns the total cross section as a GIDI::Functions::XYs1d instance.
1168 *
1169 * @param a_temperature [in] Specifies the temperature requested for the cross section.
1170 *
1171 * @returns A GIDI::Functions::XYs1d instance.
1172 ***********************************************************************************************************/
1173
1175
1176 GIDI::Functions::XYs1d crossSection1;
1177
1178 if( a_temperature <= m_temperatures[0] ) {
1179 crossSection1 = m_heatedCrossSections[0]->crossSectionAsGIDI_XYs1d( ); }
1180 else if( a_temperature >= m_temperatures.back( ) ) {
1181 crossSection1 = m_heatedCrossSections.back( )->crossSectionAsGIDI_XYs1d( ); }
1182 else {
1183 std::size_t i1 = 0;
1184 for( ; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1185 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1186 crossSection1 = m_heatedCrossSections[i1-1]->crossSectionAsGIDI_XYs1d( );
1187 crossSection1 *= ( 1. - fraction );
1188 GIDI::Functions::XYs1d crossSection2( m_heatedCrossSections[i1-1]->crossSectionAsGIDI_XYs1d( ) );
1189 crossSection2 *= fraction;
1190 crossSection1 += crossSection2;
1191 }
1192
1193 return( crossSection1 );
1194}
1195
1196/* *********************************************************************************************************//**
1197 * Returns the reaction's cross section as GIDI::Functions::XYs1d instance.
1198 *
1199 * @param a_reactionIndex [in] Specifies the indexs of the reaction whose cross section is requested.
1200 * @param a_temperature [in] Specifies the temperature requested for the cross section.
1201 *
1202 * @returns A GIDI::Functions::XYs1d instance.
1203 ***********************************************************************************************************/
1204
1206 double a_temperature ) const {
1207
1208 GIDI::Functions::XYs1d crossSection1;
1209
1210 if( a_temperature <= m_temperatures[0] ) {
1211 crossSection1 = m_heatedCrossSections[0]->reactionCrossSectionAsGIDI_XYs1d( a_reactionIndex ); }
1212 else if( a_temperature >= m_temperatures.back( ) ) {
1213 crossSection1 = m_heatedCrossSections.back( )->reactionCrossSectionAsGIDI_XYs1d( a_reactionIndex ); }
1214 else {
1215 std::size_t i1 = 0;
1216 for( ; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1217 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1218 crossSection1 = m_heatedCrossSections[i1-1]->reactionCrossSectionAsGIDI_XYs1d( a_reactionIndex );
1219 crossSection1 *= ( 1. - fraction );
1220 GIDI::Functions::XYs1d crossSection2( m_heatedCrossSections[i1-1]->reactionCrossSectionAsGIDI_XYs1d( a_reactionIndex ) );
1221 crossSection2 *= fraction;
1222 crossSection1 += crossSection2;
1223 }
1224
1225 return( crossSection1 );
1226}
1227
1228/*
1229=========================================================
1230*/
1231LUPI_HOST_DEVICE double HeatedCrossSectionsContinuousEnergy::reactionCrossSection( std::size_t a_reactionIndex, URR_protareInfos const &a_URR_protareInfos, int a_URR_index,
1232 std::size_t a_hashIndex, double a_temperature, double a_energy, bool a_sampling ) const {
1233
1234 double cross_section;
1235
1236 if( a_temperature <= m_temperatures[0] ) {
1237 cross_section = m_heatedCrossSections[0]->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling ); }
1238 else if( a_temperature >= m_temperatures.back( ) ) {
1239 cross_section = m_heatedCrossSections.back( )->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling ); }
1240 else {
1241 std::size_t i1;
1242 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1243 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1244 cross_section = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling )
1245 + fraction * m_heatedCrossSections[i1]->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_hashIndex, a_energy, a_sampling );
1246 }
1247
1248 return( cross_section );
1249}
1250
1251/*
1252=========================================================
1253*/
1254LUPI_HOST_DEVICE double HeatedCrossSectionsContinuousEnergy::reactionCrossSection( std::size_t a_reactionIndex, URR_protareInfos const &a_URR_protareInfos, int a_URR_index,
1255 double a_temperature, double a_energy_in ) const {
1256
1257 double cross_section;
1258
1259 if( a_temperature <= m_temperatures[0] ) {
1260 cross_section = m_heatedCrossSections[0]->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_energy_in ); }
1261 else if( a_temperature >= m_temperatures.back( ) ) {
1262 cross_section = m_heatedCrossSections.back( )->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_energy_in ); }
1263 else {
1264 std::size_t i1;
1265 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1266 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1267 cross_section = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_energy_in )
1268 + fraction * m_heatedCrossSections[i1]->reactionCrossSection( a_reactionIndex, a_URR_protareInfos, a_URR_index, a_energy_in );
1269 }
1270
1271 return( cross_section );
1272}
1273
1274/* *********************************************************************************************************//**
1275 * Returns the deposition energy for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
1276 *
1277 * @param a_hashIndex [in] Specifies projectile energy hash index.
1278 * @param a_temperature [in] The temperature of the target.
1279 * @param a_energy [in] The energy of the projectile.
1280 ***********************************************************************************************************/
1281
1282LUPI_HOST_DEVICE double HeatedCrossSectionsContinuousEnergy::depositionEnergy( std::size_t a_hashIndex, double a_temperature, double a_energy ) const {
1283
1284 double deposition_energy;
1285
1286 if( a_temperature <= m_temperatures[0] ) {
1287 deposition_energy = m_heatedCrossSections[0]->depositionEnergy( a_hashIndex, a_energy ); }
1288 else if( a_temperature >= m_temperatures.back( ) ) {
1289 deposition_energy = m_heatedCrossSections.back( )->depositionEnergy( a_hashIndex, a_energy ); }
1290 else {
1291 std::size_t i1;
1292 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1293 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1294 deposition_energy = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->depositionEnergy( a_hashIndex, a_energy )
1295 + fraction * m_heatedCrossSections[i1]->depositionEnergy( a_hashIndex, a_energy );
1296 }
1297
1298 return( deposition_energy );
1299}
1300
1301/* *********************************************************************************************************//**
1302 * Returns the deposition momentum for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
1303 *
1304 * @param a_hashIndex [in] Specifies projectile energy hash index.
1305 * @param a_temperature [in] The temperature of the target.
1306 * @param a_energy [in] The energy of the projectile.
1307 ***********************************************************************************************************/
1308
1309LUPI_HOST_DEVICE double HeatedCrossSectionsContinuousEnergy::depositionMomentum( std::size_t a_hashIndex, double a_temperature, double a_energy ) const {
1310
1311 double deposition_momentum;
1312
1313 if( a_temperature <= m_temperatures[0] ) {
1314 deposition_momentum = m_heatedCrossSections[0]->depositionMomentum( a_hashIndex, a_energy ); }
1315 else if( a_temperature >= m_temperatures.back( ) ) {
1316 deposition_momentum = m_heatedCrossSections.back( )->depositionMomentum( a_hashIndex, a_energy ); }
1317 else {
1318 std::size_t i1;
1319 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1320 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1321 deposition_momentum = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->depositionMomentum( a_hashIndex, a_energy )
1322 + fraction * m_heatedCrossSections[i1]->depositionMomentum( a_hashIndex, a_energy );
1323 }
1324
1325 return( deposition_momentum );
1326}
1327
1328/* *********************************************************************************************************//**
1329 * Returns the production momentum for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
1330 *
1331 * @param a_hashIndex [in] Specifies projectile energy hash index.
1332 * @param a_temperature [in] The temperature of the target.
1333 * @param a_energy [in] The energy of the projectile.
1334 ***********************************************************************************************************/
1335
1336LUPI_HOST_DEVICE double HeatedCrossSectionsContinuousEnergy::productionEnergy( std::size_t a_hashIndex, double a_temperature, double a_energy ) const {
1337
1338 double production_energy;
1339
1340 if( a_temperature <= m_temperatures[0] ) {
1341 production_energy = m_heatedCrossSections[0]->productionEnergy( a_hashIndex, a_energy ); }
1342 else if( a_temperature >= m_temperatures.back( ) ) {
1343 production_energy = m_heatedCrossSections.back( )->productionEnergy( a_hashIndex, a_energy ); }
1344 else {
1345 std::size_t i1;
1346 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1347 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1348 production_energy = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->productionEnergy( a_hashIndex, a_energy )
1349 + fraction * m_heatedCrossSections[i1]->productionEnergy( a_hashIndex, a_energy );
1350 }
1351
1352 return( production_energy );
1353}
1354
1355/* *********************************************************************************************************//**
1356 * Returns the gain for particle with index *a_particleIndex* for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
1357 *
1358 * @param a_hashIndex [in] Specifies projectile energy hash index.
1359 * @param a_temperature [in] The temperature of the target.
1360 * @param a_energy [in] The energy of the projectile.
1361 * @param a_particleIndex [in] The index of the particle whose gain is requested.
1362 ***********************************************************************************************************/
1363
1364LUPI_HOST_DEVICE double HeatedCrossSectionsContinuousEnergy::gain( std::size_t a_hashIndex, double a_temperature,
1365 double a_energy, int a_particleIndex ) const {
1366
1367 double production_energy;
1368
1369 if( a_temperature <= m_temperatures[0] ) {
1370 production_energy = m_heatedCrossSections[0]->gain( a_hashIndex, a_energy, a_particleIndex ); }
1371 else if( a_temperature >= m_temperatures.back( ) ) {
1372 production_energy = m_heatedCrossSections.back( )->gain( a_hashIndex, a_energy, a_particleIndex ); }
1373 else {
1374 std::size_t i1;
1375 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1376 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1377 production_energy = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->gain( a_hashIndex, a_energy, a_particleIndex )
1378 + fraction * m_heatedCrossSections[i1]->gain( a_hashIndex, a_energy, a_particleIndex );
1379 }
1380
1381 return( production_energy );
1382}
1383
1384/* *********************************************************************************************************//**
1385 * Returns the gain for particle with intid *a_particleIntid* for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
1386 *
1387 * @param a_hashIndex [in] Specifies projectile energy hash index.
1388 * @param a_temperature [in] The temperature of the target.
1389 * @param a_energy [in] The energy of the projectile.
1390 * @param a_particleIntid [in] The intid of the particle whose gain is requested.
1391 ***********************************************************************************************************/
1392
1393LUPI_HOST_DEVICE double HeatedCrossSectionsContinuousEnergy::gainViaIntid( std::size_t a_hashIndex, double a_temperature,
1394 double a_energy, int a_particleIntid ) const {
1395
1396 double production_energy;
1397
1398 if( a_temperature <= m_temperatures[0] ) {
1399 production_energy = m_heatedCrossSections[0]->gainViaIntid( a_hashIndex, a_energy, a_particleIntid ); }
1400 else if( a_temperature >= m_temperatures.back( ) ) {
1401 production_energy = m_heatedCrossSections.back( )->gainViaIntid( a_hashIndex, a_energy, a_particleIntid ); }
1402 else {
1403 std::size_t i1;
1404 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1405 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1406 production_energy = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->gainViaIntid( a_hashIndex, a_energy, a_particleIntid )
1407 + fraction * m_heatedCrossSections[i1]->gainViaIntid( a_hashIndex, a_energy, a_particleIntid );
1408 }
1409
1410 return( production_energy );
1411}
1412
1413/* *********************************************************************************************************//**
1414 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs index *a_particleIndex*.
1415 *
1416 * @param a_particleIndex [in] The index of the particle whose user index is to be set.
1417 * @param a_userParticleIndex [in] The particle index specified by the user.
1418 ***********************************************************************************************************/
1419
1420LUPI_HOST void HeatedCrossSectionsContinuousEnergy::setUserParticleIndex( int a_particleIndex, int a_userParticleIndex ) {
1421
1422 for( auto iter = m_heatedCrossSections.begin( ); iter != m_heatedCrossSections.end( ); ++iter ) (*iter)->setUserParticleIndex( a_particleIndex, a_userParticleIndex );
1423}
1424
1425/* *********************************************************************************************************//**
1426 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs intid *a_particleIntid*.
1427 *
1428 * @param a_particleIntid [in] The intid of the particle whose user index is to be set.
1429 * @param a_userParticleIndex [in] The particle index specified by the user.
1430 ***********************************************************************************************************/
1431
1432LUPI_HOST void HeatedCrossSectionsContinuousEnergy::setUserParticleIndexViaIntid( int a_particleIntid, int a_userParticleIndex ) {
1433
1434 for( auto iter = m_heatedCrossSections.begin( ); iter != m_heatedCrossSections.end( ); ++iter ) (*iter)->setUserParticleIndexViaIntid( a_particleIntid, a_userParticleIndex );
1435}
1436
1437/* *********************************************************************************************************//**
1438 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
1439 * bytes, pack *this* or unpack *this* depending on *a_mode*.
1440 *
1441 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
1442 * @param a_mode [in] Specifies the action of this method.
1443 ***********************************************************************************************************/
1444
1446
1447 DATA_MEMBER_VECTOR_DOUBLE( m_temperatures, a_buffer, a_mode );
1448 DATA_MEMBER_VECTOR_DOUBLE( m_thresholds, a_buffer, a_mode );
1449
1450 std::size_t vectorSize = m_heatedCrossSections.size( );
1451 int vectorSizeInt = (int) vectorSize;
1452 DATA_MEMBER_INT( vectorSizeInt, a_buffer, a_mode );
1453 vectorSize = (std::size_t) vectorSizeInt;
1454
1455 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) m_heatedCrossSections.resize( vectorSize, &a_buffer.m_placement );
1456 if( a_mode == LUPI::DataBuffer::Mode::Memory ) a_buffer.m_placement += m_heatedCrossSections.internalSize();
1457 for( std::size_t memberIndex = 0; memberIndex < vectorSize; ++memberIndex ) {
1458 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
1459 if( a_buffer.m_placement != nullptr ) {
1460 m_heatedCrossSections[memberIndex] = new(a_buffer.m_placement) HeatedCrossSectionContinuousEnergy;
1462 else {
1463 m_heatedCrossSections[memberIndex] = new HeatedCrossSectionContinuousEnergy;
1464 }
1465 }
1466 if( a_mode == LUPI::DataBuffer::Mode::Memory ) {
1468 }
1469 m_heatedCrossSections[memberIndex]->serialize( a_buffer, a_mode );
1470 }
1471}
1472
1473/* *********************************************************************************************************//**
1474 * Print to *std::cout* the content of *this*. This is mainly meant for debugging.
1475 *
1476 * @param a_protareSingle [in] The GIDI::ProtareSingle instance that contains *this*.
1477 * @param a_indent [in] The buffer to read or write data to depending on *a_mode*.
1478 * @param a_iFormat [in] C printf format specifier for any interger that is printed (e.g., "%3d").
1479 * @param a_energyFormat [in] C printf format specifier for any interger that is printed (e.g., "%20.12e").
1480 * @param a_dFormat [in] C printf format specifier for any interger that is printed (e.g., "%14.7e").
1481 ***********************************************************************************************************/
1482
1483LUPI_HOST void HeatedCrossSectionsContinuousEnergy::print( ProtareSingle const *a_protareSingle, std::string const &a_indent,
1484 std::string const &a_iFormat, std::string const &a_energyFormat, std::string const &a_dFormat ) const {
1485
1486 std::cout << "Temperatures present:" << std::endl;
1487 for( auto temperatureIter = m_temperatures.begin( ); temperatureIter != m_temperatures.end( ); ++temperatureIter ) {
1488 std::cout << LUPI::Misc::argumentsToString( a_dFormat.c_str( ), *temperatureIter ) << std::endl;
1489 }
1490 std::cout << "Reaction thresholds:" << std::endl;
1491 for( auto reactionIter = m_thresholds.begin( ); reactionIter != m_thresholds.end( ); ++reactionIter ) {
1492 std::cout << LUPI::Misc::argumentsToString( a_dFormat.c_str( ), *reactionIter ) << std::endl;
1493 }
1494 for( auto heatedCrossSections = m_heatedCrossSections.begin( ); heatedCrossSections != m_heatedCrossSections.end( ); ++heatedCrossSections ) {
1495 (*heatedCrossSections)->print( a_protareSingle, a_indent, a_iFormat, a_energyFormat, a_dFormat );
1496 }
1497}
1498
1499/*! \class MultiGroupGain
1500 * This class store a particles index and gain for a protare.
1501 */
1502
1503/* *********************************************************************************************************//**
1504 ***********************************************************************************************************/
1505
1507 m_particleIntid( -1 ),
1508 m_particleIndex( -1 ),
1509 m_userParticleIndex( -1 ) {
1510
1511}
1512
1513/* *********************************************************************************************************//**
1514 ***********************************************************************************************************/
1515
1516LUPI_HOST MultiGroupGain::MultiGroupGain( int a_particleIntid, int a_particleIndex, GIDI::Vector const &a_gain ) :
1517 m_particleIntid( a_particleIntid ),
1518 m_particleIndex( a_particleIndex ),
1519 m_userParticleIndex( -1 ),
1520 m_gain( GIDI_VectorDoublesToMCGIDI_VectorDoubles( a_gain ) ) {
1521
1522}
1523
1524/* *********************************************************************************************************//**
1525 * @param a_multiGroupGain [in] The **MultiGroupGain** whose contents are to be copied.
1526 ***********************************************************************************************************/
1527
1529
1530 m_particleIntid = a_multiGroupGain.particleIntid( );
1531 m_particleIndex = a_multiGroupGain.particleIndex( );
1532 m_userParticleIndex = a_multiGroupGain.userParticleIndex( );
1533 m_gain = a_multiGroupGain.gain( );
1534
1535 return( *this );
1536}
1537
1538/* *********************************************************************************************************//**
1539 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
1540 * bytes, pack *this* or unpack *this* depending on *a_mode*.
1541 *
1542 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
1543 * @param a_mode [in] Specifies the action of this method.
1544 ***********************************************************************************************************/
1545
1547
1548 DATA_MEMBER_INT( m_particleIntid, a_buffer, a_mode );
1549 DATA_MEMBER_INT( m_particleIndex, a_buffer, a_mode );
1550 DATA_MEMBER_INT( m_userParticleIndex, a_buffer, a_mode );
1551 DATA_MEMBER_VECTOR_DOUBLE( m_gain, a_buffer, a_mode );
1552}
1553
1554/* *********************************************************************************************************//**
1555 * This method writes the multi-group data.
1556 *
1557 * @param a_file [in] The buffer to read or write data to depending on *a_mode*.
1558 ***********************************************************************************************************/
1559
1560LUPI_HOST void MultiGroupGain::write( FILE *a_file ) const {
1561
1562 std::string buffer = LUPI::Misc::argumentsToString( "Gain for particle %d (%d, %d)", m_particleIntid, m_particleIndex, m_userParticleIndex );
1563 writeVector( a_file, buffer, 0, m_gain );
1564}
1565
1566/*
1567============================================================
1568=========== HeatedReactionCrossSectionMultiGroup ===========
1569============================================================
1570*/
1574/*
1575=========================================================
1576*/
1578 std::size_t a_offset, std::vector<double> const &a_crossSection, double a_threshold ) :
1579 m_threshold( a_threshold ),
1580 m_offset( a_offset ),
1581 m_crossSections( a_crossSection ),
1582 m_augmentedThresholdCrossSection( 0.0 ) {
1583
1584 Vector<double> const &boundaries = a_setupInfo.m_protare.projectileMultiGroupBoundariesCollapsed( );
1585
1586 if( ( a_offset > 0 ) && ( boundaries[a_offset] < a_threshold ) ) { // This uses the linear rejection above threshold in the group m_offset.
1587 if( ( boundaries[a_offset] < a_threshold ) && ( a_threshold < boundaries[a_offset+1] ) ) {
1588 m_augmentedThresholdCrossSection = m_crossSections[0] * ( boundaries[a_offset+1] + a_threshold - 2.0 * boundaries[a_offset] ) / ( boundaries[a_offset+1] - a_threshold ); }
1589 else {
1590 m_crossSections[0] = 0.0;
1591 }
1592 }
1593}
1594
1595/* *********************************************************************************************************//**
1596 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
1597 * bytes, pack *this* or unpack *this* depending on *a_mode*.
1598 *
1599 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
1600 * @param a_mode [in] Specifies the action of this method.
1601 ***********************************************************************************************************/
1602
1604
1605 DATA_MEMBER_DOUBLE( m_threshold, a_buffer, a_mode );
1606 DATA_MEMBER_SIZE_T( m_offset, a_buffer, a_mode );
1607 DATA_MEMBER_VECTOR_DOUBLE( m_crossSections, a_buffer, a_mode );
1608 DATA_MEMBER_DOUBLE( m_augmentedThresholdCrossSection, a_buffer, a_mode );
1609}
1610
1611/* *********************************************************************************************************//**
1612 * This method writes the multi-group data.
1613 *
1614 * @param a_file [in] The buffer to read or write data to depending on *a_mode*.
1615 * @param a_reactionIndex [in] The index of the reaction.
1616 ***********************************************************************************************************/
1617
1618LUPI_HOST void HeatedReactionCrossSectionMultiGroup::write( FILE *a_file, std::size_t a_reactionIndex ) const {
1619
1620 std::string buffer = LUPI::Misc::argumentsToString( "Reaction cross section (%3d)", a_reactionIndex );
1621 writeVector( a_file, buffer, m_offset, m_crossSections );
1622}
1623
1624/*
1625============================================================
1626============= HeatedCrossSectionMultiGroup ================
1627============================================================
1628*/
1632/*
1633=========================================================
1634*/
1636 SetupInfo &a_setupInfo, Transporting::MC const &a_settings, GIDI::Styles::TemperatureInfo const &a_temperatureInfo,
1637 GIDI::Transporting::Particles const &a_particles, std::vector<GIDI::Reaction const *> const &a_reactions, LUPI_maybeUnused std::string const &a_label,
1638 bool a_zeroReactions, GIDI::ExcludeReactionsSet const &a_reactionsToExclude ) :
1639 m_totalCrossSection( ),
1640 m_augmentedCrossSection( ),
1641 m_reactionCrossSections( ) {
1642
1645 || ( a_settings.upscatterModel( ) == Sampling::Upscatter::Model::A ) )
1647 GIDI::Transporting::MG multi_group_settings( a_settings.projectileID( ), transportMode, a_settings.delayedNeutrons( ) );
1648 multi_group_settings.setThrowOnError( a_settings.throwOnError( ) );
1649
1650 GIDI::Axes axes;
1651 std::vector<double> dummy;
1653 GIDI::Vector vector;
1654
1655 m_reactionCrossSections.reserve( a_reactions.size( ) );
1656 int index = 0; // Only used for debugging.
1658 MG_settings.setThrowOnError( a_settings.throwOnError( ) );
1659
1660 for( std::vector<GIDI::Reaction const *>::const_iterator reactionIter = a_reactions.begin( ); reactionIter != a_reactions.end( ); ++reactionIter, ++index ) {
1661 GIDI::Vector crossSectionVector = (*reactionIter)->multiGroupCrossSection( a_smr, MG_settings, a_temperatureInfo );
1662
1663 vector = GIDI::collapse( crossSectionVector, a_settings, a_particles, 0.0 );
1664
1665 std::size_t start = 0;
1666 for( ; start < vector.size( ); ++start ) {
1667 if( vector[start] != 0.0 ) break;
1668 }
1669 checkZeroReaction( vector, a_zeroReactions );
1670 std::vector<double> data;
1671 for( std::size_t i1 = start; i1 < vector.size( ); ++i1 ) data.push_back( vector[i1] );
1672
1673 m_reactionCrossSections.push_back( new HeatedReactionCrossSectionMultiGroup( a_setupInfo, a_settings, start, data,
1674 (*reactionIter)->crossSectionThreshold( ) ) );
1675
1676 totalCrossSection += vector;
1677 }
1678
1679 m_totalCrossSection = totalCrossSection.data( );
1680
1681 m_augmentedCrossSection.resize( totalCrossSection.size( ) );
1682 for( std::size_t i1 = 0; i1 < m_augmentedCrossSection.size( ); ++i1 ) m_augmentedCrossSection[i1] = 0;
1683 for( std::size_t i1 = 0; i1 < m_reactionCrossSections.size( ); ++i1 )
1684 m_augmentedCrossSection[m_reactionCrossSections[i1]->offset( )] += m_reactionCrossSections[i1]->augmentedThresholdCrossSection( );
1685
1686
1687 vector = a_protare.multiGroupDepositionEnergy( a_smr, multi_group_settings, a_temperatureInfo, a_particles, a_reactionsToExclude );
1688 vector = collapseAndcheckZeroReaction( vector, a_settings, a_particles, 0.0, a_zeroReactions );
1689 m_depositionEnergy = GIDI_VectorDoublesToMCGIDI_VectorDoubles( vector );
1690
1691 vector = a_protare.multiGroupDepositionMomentum( a_smr, multi_group_settings, a_temperatureInfo, a_particles, a_reactionsToExclude );
1692 vector = collapseAndcheckZeroReaction( vector, a_settings, a_particles, 0.0, a_zeroReactions );
1693 m_depositionMomentum = GIDI_VectorDoublesToMCGIDI_VectorDoubles( vector );
1694
1695 vector = a_protare.multiGroupQ( a_smr, multi_group_settings, a_temperatureInfo, true, true, a_reactionsToExclude );
1696 vector = collapseAndcheckZeroReaction( vector, a_settings, a_particles, 0.0, a_zeroReactions );
1697 m_productionEnergy = GIDI_VectorDoublesToMCGIDI_VectorDoubles( vector );
1698
1699 std::map<std::string, GIDI::Transporting::Particle> particles = a_particles.particles( );
1700 m_gains.resize( particles.size( ) );
1701 std::size_t i1 = 0;
1702 for( std::map<std::string, GIDI::Transporting::Particle>::const_iterator particle = particles.begin( ); particle != particles.end( ); ++particle, ++i1 ) {
1703 int particleIntid = a_setupInfo.m_particleIntids[particle->first];
1704 int particleIndex = a_setupInfo.m_particleIndices[particle->first];
1705
1706 vector = a_protare.multiGroupGain( a_smr, multi_group_settings, a_temperatureInfo, particle->first, a_reactionsToExclude );
1707 vector = collapseAndcheckZeroReaction( vector, a_settings, a_particles, 0.0, a_zeroReactions );
1708 m_gains[i1] = new MultiGroupGain( particleIntid, particleIndex, vector );
1709 }
1710}
1711
1712/* *********************************************************************************************************//**
1713 ***********************************************************************************************************/
1714
1716
1717 for( auto iter = m_reactionCrossSections.begin( ); iter < m_reactionCrossSections.end( ); ++iter ) delete *iter;
1718 for( auto iter = m_gains.begin( ); iter < m_gains.end( ); ++iter ) delete *iter;
1719}
1720
1721/* *********************************************************************************************************//**
1722 * Returns the multi-group cross section.
1723 *
1724 * @param a_hashIndex [in] The multi-group index.
1725 * @param a_sampling [in] Fix me.
1726 *
1727 * @return A vector of the length of the number of multi-group groups.
1728 ***********************************************************************************************************/
1729
1730LUPI_HOST_DEVICE double HeatedCrossSectionMultiGroup::crossSection( std::size_t a_hashIndex, bool a_sampling ) const {
1731
1732 double crossSection2 = m_totalCrossSection[a_hashIndex];
1733
1734 if( a_sampling ) crossSection2 += m_augmentedCrossSection[a_hashIndex];
1735
1736 return( crossSection2 );
1737}
1738
1739/* *********************************************************************************************************//**
1740 * Returns the multi-group gain for particle with index *a_particleIndex*. If no particle is found, a Vector of all 0's is returned.
1741 *
1742 * @param a_particleIndex [in] The index of the particle whose gain is to be returned.
1743 * @param a_hashIndex [in] The multi-group index.
1744 *
1745 * @return A vector of the length of the number of multi-group groups.
1746 ***********************************************************************************************************/
1747
1748LUPI_HOST_DEVICE double HeatedCrossSectionMultiGroup::gain( std::size_t a_hashIndex, int a_particleIndex ) const {
1749
1750 for( std::size_t i1 = 0; i1 < m_gains.size( ); ++i1 ) {
1751 if( a_particleIndex == m_gains[i1]->particleIndex( ) ) return( m_gains[i1]->gain( a_hashIndex ) );
1752 }
1753
1754 return( 0.0 );
1755}
1756
1757/* *********************************************************************************************************//**
1758 * Returns the multi-group gain for particle with intid *a_particleIntid*. If no particle is found, a Vector of all 0's is returned.
1759 *
1760 * @param a_particleIntid [in] The intid of the particle whose gain is to be returned.
1761 * @param a_hashIndex [in] The multi-group index.
1762 *
1763 * @return A vector of the length of the number of multi-group groups.
1764 ***********************************************************************************************************/
1765
1766LUPI_HOST_DEVICE double HeatedCrossSectionMultiGroup::gainViaIntid( std::size_t a_hashIndex, int a_particleIntid ) const {
1767
1768 for( std::size_t i1 = 0; i1 < m_gains.size( ); ++i1 ) {
1769 if( a_particleIntid == m_gains[i1]->particleIntid( ) ) return( m_gains[i1]->gain( a_hashIndex ) );
1770 }
1771
1772 return( 0.0 );
1773}
1774
1775/* *********************************************************************************************************//**
1776 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs index *a_particleIntid*.
1777 *
1778 * @param a_particleIndex [in] The index of the particle whose user index is to be set.
1779 * @param a_userParticleIndex [in] The particle index specified by the user.
1780 ***********************************************************************************************************/
1781
1782LUPI_HOST void HeatedCrossSectionMultiGroup::setUserParticleIndex( int a_particleIndex, int a_userParticleIndex ) {
1783
1784 for( auto iter = m_gains.begin( ); iter != m_gains.end( ); ++iter ) (*iter)->setUserParticleIndex( a_particleIndex, a_userParticleIndex );
1785}
1786
1787/* *********************************************************************************************************//**
1788 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs intid *a_particleIntid*.
1789 *
1790 * @param a_particleIntid [in] The intid of the particle whose user index is to be set.
1791 * @param a_userParticleIndex [in] The particle index specified by the user.
1792 ***********************************************************************************************************/
1793
1794LUPI_HOST void HeatedCrossSectionMultiGroup::setUserParticleIndexViaIntid( int a_particleIntid, int a_userParticleIndex ) {
1795
1796 for( auto iter = m_gains.begin( ); iter != m_gains.end( ); ++iter ) (*iter)->setUserParticleIndexViaIntid( a_particleIntid, a_userParticleIndex );
1797}
1798
1799/* *********************************************************************************************************//**
1800 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
1801 * bytes, pack *this* or unpack *this* depending on *a_mode*.
1802 *
1803 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
1804 * @param a_mode [in] Specifies the action of this method.
1805 ***********************************************************************************************************/
1806
1808
1809 DATA_MEMBER_VECTOR_DOUBLE( m_totalCrossSection, a_buffer, a_mode );
1810 DATA_MEMBER_VECTOR_DOUBLE( m_augmentedCrossSection, a_buffer, a_mode );
1811 DATA_MEMBER_VECTOR_DOUBLE( m_depositionEnergy, a_buffer, a_mode );
1812 DATA_MEMBER_VECTOR_DOUBLE( m_depositionMomentum, a_buffer, a_mode );
1813 DATA_MEMBER_VECTOR_DOUBLE( m_productionEnergy, a_buffer, a_mode );
1814
1815 std::size_t vectorSize = m_reactionCrossSections.size( );
1816 int vectorSizeInt = (int) vectorSize;
1817 DATA_MEMBER_INT( vectorSizeInt, a_buffer, a_mode );
1818 vectorSize = (std::size_t) vectorSizeInt;
1819
1820 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) m_reactionCrossSections.resize( vectorSize, &a_buffer.m_placement );
1821 if( a_mode == LUPI::DataBuffer::Mode::Memory ) a_buffer.m_placement += m_reactionCrossSections.internalSize();
1822 for( std::size_t memberIndex = 0; memberIndex < vectorSize; ++memberIndex ) {
1823 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
1824 if( a_buffer.m_placement != nullptr ) {
1825 m_reactionCrossSections[memberIndex] = new(a_buffer.m_placement) HeatedReactionCrossSectionMultiGroup;
1827 else {
1828 m_reactionCrossSections[memberIndex] = new HeatedReactionCrossSectionMultiGroup;
1829 }
1830 }
1831 if( a_mode == LUPI::DataBuffer::Mode::Memory ) {
1833 }
1834 m_reactionCrossSections[memberIndex]->serialize( a_buffer, a_mode );
1835 }
1836
1837 vectorSize = m_gains.size( );
1838 vectorSizeInt = (int) vectorSize;
1839 DATA_MEMBER_INT( vectorSizeInt, a_buffer, a_mode );
1840 vectorSize = (std::size_t) vectorSizeInt;
1841 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) m_gains.resize( vectorSize, &a_buffer.m_placement );
1842 if( a_mode == LUPI::DataBuffer::Mode::Memory ) a_buffer.m_placement += m_gains.internalSize();
1843 for( std::size_t memberIndex = 0; memberIndex < vectorSize; ++memberIndex ) {
1844 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
1845 if( a_buffer.m_placement != nullptr ) {
1846 m_gains[memberIndex] = new(a_buffer.m_placement) MultiGroupGain;
1847 a_buffer.incrementPlacement( sizeof( MultiGroupGain ) ); }
1848 else {
1849 m_gains[memberIndex] = new MultiGroupGain;
1850 }
1851 }
1852 if( a_mode == LUPI::DataBuffer::Mode::Memory ) {
1853 a_buffer.incrementPlacement( sizeof( MultiGroupGain ) );
1854 }
1855 m_gains[memberIndex]->serialize( a_buffer, a_mode );
1856 }
1857}
1858
1859/* *********************************************************************************************************//**
1860 * This method writes the multi-group data.
1861 *
1862 * @param a_file [in] The buffer to read or write data to depending on *a_mode*.
1863 ***********************************************************************************************************/
1864
1866
1867 writeVector( a_file, "Total cross section", 0, m_totalCrossSection );
1868 writeVector( a_file, "Augmented cross section", 0, m_augmentedCrossSection );
1869 writeVector( a_file, "Deposition energy", 0, m_depositionEnergy );
1870 writeVector( a_file, "Deposition momentum", 0, m_depositionMomentum );
1871 writeVector( a_file, "Production energy", 0, m_productionEnergy );
1872
1873 for( auto iter = m_gains.begin( ); iter != m_gains.end( ); ++iter ) (*iter)->write( a_file );
1874 std::size_t reactionIndex = 0;
1875 for( Vector<HeatedReactionCrossSectionMultiGroup *>::const_iterator iter = m_reactionCrossSections.begin( ); iter < m_reactionCrossSections.end( ); ++iter ) {
1876 (*iter)->write( a_file, reactionIndex );
1877 ++reactionIndex;
1878 }
1879}
1880
1881/*! \class Protare
1882 * Base class for the protare sub-classes.
1883 */
1884
1885/* *********************************************************************************************************//**
1886 * Generic constructor.
1887 ***********************************************************************************************************/
1888
1892
1893/* *********************************************************************************************************//**
1894 * Generic constructor.
1895 ***********************************************************************************************************/
1896
1898
1899 for( Vector<HeatedCrossSectionMultiGroup *>::const_iterator iter = m_heatedCrossSections.begin( ); iter != m_heatedCrossSections.end( ); ++iter ) delete *iter;
1900}
1901
1902/* *********************************************************************************************************//**
1903 * Fills in *this* with the requested temperature data.
1904 *
1905 * @param a_smr [Out] If errors are not to be thrown, then the error is reported via this instance.
1906 * @param a_protare [in] The GIDI::Protare used to constuct the Protare that *this* is a part of.
1907 * @param a_setupInfo [in] Used internally when constructing a Protare to pass information to other components.
1908 * @param a_settings [in] Used to pass user options to the *this* to instruct it which data are desired.
1909 * @param a_particles [in] List of transporting particles and their information (e.g., multi-group boundaries and fluxes).
1910 * @param a_temperatureInfos [in] The list of temperatures to use.
1911 * @param a_reactions [in] The list of reactions to use.
1912 * @param a_orphanProducts [in] The list of orphan products to use.
1913 * @param a_zeroReactions [in] Special case where no reaction in a protare is wanted so the first one is used but its cross section is set to 0.0 at all energies.
1914 ***********************************************************************************************************/
1915
1917 SetupInfo &a_setupInfo, Transporting::MC const &a_settings, GIDI::Transporting::Particles const &a_particles,
1918 GIDI::Styles::TemperatureInfos const &a_temperatureInfos, std::vector<GIDI::Reaction const *> const &a_reactions,
1919 LUPI_maybeUnused std::vector<GIDI::Reaction const *> const &a_orphanProducts, bool a_zeroReactions,
1920 GIDI::ExcludeReactionsSet const &a_reactionsToExclude ) {
1921
1922 m_temperatures.reserve( a_temperatureInfos.size( ) );
1923 m_heatedCrossSections.reserve( a_temperatureInfos.size( ) );
1924
1925 for( GIDI::Styles::TemperatureInfos::const_iterator iter = a_temperatureInfos.begin( ); iter != a_temperatureInfos.end( ); ++iter ) {
1926 m_temperatures.push_back( iter->temperature( ).value( ) );
1927 m_heatedCrossSections.push_back( new HeatedCrossSectionMultiGroup( a_smr, a_protare, a_setupInfo, a_settings, *iter, a_particles,
1928 a_reactions, iter->heatedMultiGroup( ), a_zeroReactions, a_reactionsToExclude ) );
1929 }
1930
1931 m_thresholds.resize( m_heatedCrossSections[0]->numberOfReactions( ) );
1932 for( std::size_t i1 = 0; i1 < m_heatedCrossSections[0]->numberOfReactions( ); ++i1 ) m_thresholds[i1] = m_heatedCrossSections[0]->threshold( i1 );
1933
1934 m_multiGroupThresholdIndex.resize( m_heatedCrossSections[0]->numberOfReactions( ) );
1935 for( std::size_t i1 = 0; i1 < m_heatedCrossSections[0]->numberOfReactions( ); ++i1 ) {
1936 m_multiGroupThresholdIndex[i1] = -1;
1937 if( m_thresholds[i1] > 0 ) m_multiGroupThresholdIndex[i1] = static_cast<int>( m_heatedCrossSections[0]->thresholdOffset( i1 ) );
1938 }
1939
1940 m_projectileMultiGroupBoundariesCollapsed = a_setupInfo.m_protare.projectileMultiGroupBoundariesCollapsed( );
1941}
1942
1943/* *********************************************************************************************************//**
1944 * Returns the total multi-group cross section for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
1945 *
1946 * @param a_hashIndex [in] The multi-group index.
1947 * @param a_temperature [in] The temperature of the target.
1948 * @param a_sampling [in] Used for multi-group look up. If *true*, use augmented cross sections.
1949 ***********************************************************************************************************/
1950
1951LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::crossSection( std::size_t a_hashIndex, double a_temperature, bool a_sampling ) const {
1952
1953 double cross_section;
1954
1955 if( a_temperature <= m_temperatures[0] ) {
1956 cross_section = m_heatedCrossSections[0]->crossSection( a_hashIndex, a_sampling ); }
1957 else if( a_temperature >= m_temperatures.back( ) ) {
1958 cross_section = m_heatedCrossSections.back( )->crossSection( a_hashIndex, a_sampling ); }
1959 else {
1960 std::size_t i1;
1961 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
1962 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
1963
1964 cross_section = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->crossSection( a_hashIndex, a_sampling )
1965 + fraction * m_heatedCrossSections[i1]->crossSection( a_hashIndex, a_sampling );
1966 }
1967
1968 return( cross_section );
1969}
1970
1971/* *********************************************************************************************************//**
1972 * Adds the energy dependent, total cross section corresponding to the temperature *a_temperature* multiplied by *a_userFactor* to *a_crossSectionVector*.
1973 *
1974 * @param a_temperature [in] Specifies the temperature of the material.
1975 * @param a_userFactor [in] User factor which all cross sections are multiplied by.
1976 * @param a_numberAllocated [in] The length of memory allocated for *a_crossSectionVector*.
1977 * @param a_crossSectionVector [in/out] The energy dependent, total cross section to add cross section data to.
1978 ***********************************************************************************************************/
1979
1980LUPI_HOST_DEVICE void HeatedCrossSectionsMultiGroup::crossSectionVector( double a_temperature, double a_userFactor,
1981 std::size_t a_numberAllocated, double *a_crossSectionVector ) const {
1982
1983 std::size_t index1 = 0, index2 = 0;
1984 double fraction = 0.0;
1985
1986 if( a_temperature <= m_temperatures[0] ) {
1987 }
1988 else if( a_temperature >= m_temperatures.back( ) ) {
1989 index1 = index2 = m_temperatures.size( ) - 1;
1990 fraction = 1.0; }
1991 else {
1992 for( ; index2 < m_temperatures.size( ); ++index2 ) if( a_temperature < m_temperatures[index2] ) break;
1993 index1 = index2 - 1;
1994 fraction = ( a_temperature - m_temperatures[index1] ) / ( m_temperatures[index2] - m_temperatures[index1] );
1995 }
1996
1997 Vector<double> &totalCrossSection1 = m_heatedCrossSections[index1]->totalCrossSection( );
1998 Vector<double> &totalCrossSection2 = m_heatedCrossSections[index2]->totalCrossSection( );
1999 std::size_t size = totalCrossSection1.size( );
2000 double factor1 = a_userFactor * ( 1.0 - fraction ), factor2 = a_userFactor * fraction;
2001
2002 if( a_numberAllocated < totalCrossSection1.size( ) ) LUPI_THROW( "HeatedCrossSectionsMultiGroup::crossSectionVector: a_numberAllocated too small." );
2003 for( std::size_t i1 = 0; i1 < size; ++i1 ) {
2004 a_crossSectionVector[i1] += factor1 * totalCrossSection1[i1] + factor2 * totalCrossSection2[i1];
2005 }
2006}
2007
2008/* *********************************************************************************************************//**
2009 * Returns the requested reaction's multi-group cross section for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
2010 *
2011 * @param a_reactionIndex [in] The index of the reaction.
2012 * @param a_hashIndex [in] The multi-group index.
2013 * @param a_temperature [in] The temperature of the target.
2014 * @param a_sampling [in] If *true*, use augmented cross sections.
2015 ***********************************************************************************************************/
2016
2017LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::reactionCrossSection( std::size_t a_reactionIndex, std::size_t a_hashIndex, double a_temperature, bool a_sampling ) const {
2018
2019 double cross_section;
2020
2021 if( a_temperature <= m_temperatures[0] ) {
2022 cross_section = m_heatedCrossSections[0]->reactionCrossSection( a_reactionIndex, a_hashIndex, a_sampling ); }
2023 else if( a_temperature >= m_temperatures.back( ) ) {
2024 cross_section = m_heatedCrossSections.back( )->reactionCrossSection( a_reactionIndex, a_hashIndex, a_sampling ); }
2025 else {
2026 std::size_t i1;
2027 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
2028 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
2029 cross_section = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->reactionCrossSection( a_reactionIndex, a_hashIndex, a_sampling )
2030 + fraction * m_heatedCrossSections[i1]->reactionCrossSection( a_reactionIndex, a_hashIndex, a_sampling );
2031 }
2032
2033 return( cross_section );
2034}
2035
2036/* *********************************************************************************************************//**
2037 * Returns the requested reaction's multi-group cross section for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
2038 *
2039 * @param a_reactionIndex [in] The index of the reaction.
2040 * @param a_temperature [in] The temperature of the target.
2041 * @param a_energy_in [in] The energy of the projectile.
2042 ***********************************************************************************************************/
2043
2044LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::reactionCrossSection( std::size_t a_reactionIndex, double a_temperature, double a_energy_in ) const {
2045
2046 int intEnergyIndex = binarySearchVector( a_energy_in, m_projectileMultiGroupBoundariesCollapsed );
2047 std::size_t energyIndex = static_cast<std::size_t>( intEnergyIndex );
2048
2049 if( intEnergyIndex == -2 ) {
2050 energyIndex = 0; }
2051 else {
2052 energyIndex = m_projectileMultiGroupBoundariesCollapsed.size( ) - 2;
2053 }
2054
2055
2056 return( reactionCrossSection( a_reactionIndex, energyIndex, a_temperature, false ) );
2057}
2058
2059/* *********************************************************************************************************//**
2060 * Returns the multi-group deposition energy for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
2061 *
2062 * @param a_hashIndex [in] The multi-group index.
2063 * @param a_temperature [in] The temperature of the target.
2064 *
2065 * @return The deposition energy.
2066 ***********************************************************************************************************/
2067
2068LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::depositionEnergy( std::size_t a_hashIndex, double a_temperature ) const {
2069
2070 double deposition_energy;
2071
2072 if( a_temperature <= m_temperatures[0] ) {
2073 deposition_energy = m_heatedCrossSections[0]->depositionEnergy( a_hashIndex ); }
2074 else if( a_temperature >= m_temperatures.back( ) ) {
2075 deposition_energy = m_heatedCrossSections.back( )->depositionEnergy( a_hashIndex ); }
2076 else {
2077 std::size_t i1;
2078 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
2079 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
2080 deposition_energy = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->depositionEnergy( a_hashIndex )
2081 + fraction * m_heatedCrossSections[i1]->depositionEnergy( a_hashIndex );
2082 }
2083
2084 return( deposition_energy );
2085}
2086
2087/* *********************************************************************************************************//**
2088 * Returns the multi-group deposition momentum for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
2089 *
2090 * @param a_hashIndex [in] The multi-group index.
2091 * @param a_temperature [in] The temperature of the target.
2092 *
2093 * @return The deposition energy.
2094 ***********************************************************************************************************/
2095
2096LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::depositionMomentum( std::size_t a_hashIndex, double a_temperature ) const {
2097
2098 double deposition_momentum;
2099
2100 if( a_temperature <= m_temperatures[0] ) {
2101 deposition_momentum = m_heatedCrossSections[0]->depositionMomentum( a_hashIndex ); }
2102 else if( a_temperature >= m_temperatures.back( ) ) {
2103 deposition_momentum = m_heatedCrossSections.back( )->depositionMomentum( a_hashIndex ); }
2104 else {
2105 std::size_t i1;
2106 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
2107 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
2108 deposition_momentum = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->depositionMomentum( a_hashIndex )
2109 + fraction * m_heatedCrossSections[i1]->depositionMomentum( a_hashIndex );
2110 }
2111
2112 return( deposition_momentum );
2113}
2114
2115/* *********************************************************************************************************//**
2116 * Returns the multi-group production energy for target temperature *a_temperature* and projectile multi-group *a_hashIndex*.
2117 *
2118 * @param a_hashIndex [in] The multi-group index.
2119 * @param a_temperature [in] The temperature of the target.
2120 *
2121 * @return The deposition energy.
2122 ***********************************************************************************************************/
2123
2124LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::productionEnergy( std::size_t a_hashIndex, double a_temperature ) const {
2125
2126 double production_energy;
2127
2128 if( a_temperature <= m_temperatures[0] ) {
2129 production_energy = m_heatedCrossSections[0]->productionEnergy( a_hashIndex ); }
2130 else if( a_temperature >= m_temperatures.back( ) ) {
2131 production_energy = m_heatedCrossSections.back( )->productionEnergy( a_hashIndex ); }
2132 else {
2133 std::size_t i1;
2134 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
2135 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
2136
2137 production_energy = ( 1. - fraction ) * m_heatedCrossSections[i1-1]->productionEnergy( a_hashIndex )
2138 + fraction * m_heatedCrossSections[i1]->productionEnergy( a_hashIndex );
2139 }
2140
2141 return( production_energy );
2142}
2143
2144/* *********************************************************************************************************//**
2145 * Returns the multi-group gain for particle with index *a_particleIndex*. If no particle is found, a Vector of all 0's is returned.
2146 *
2147 * @param a_hashIndex [in] The multi-group index.
2148 * @param a_temperature [in] The temperature of the target.
2149 * @param a_particleIndex [in] The index of the particle whose gain is to be returned.
2150 *
2151 * @return The multi-group gain.
2152 ***********************************************************************************************************/
2153
2154LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::gain( std::size_t a_hashIndex, double a_temperature, int a_particleIndex ) const {
2155
2156 if( a_temperature <= m_temperatures[0] ) {
2157 return( m_heatedCrossSections[0]->gain( a_hashIndex, a_particleIndex ) ); }
2158 else if( a_temperature >= m_temperatures.back( ) ) {
2159 return( m_heatedCrossSections.back( )->gain( a_hashIndex, a_particleIndex ) );
2160 }
2161
2162 std::size_t i1;
2163 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
2164 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
2165
2166 double gain1 = m_heatedCrossSections[i1-1]->gain( a_hashIndex, a_particleIndex );
2167 double gain2 = m_heatedCrossSections[i1]->gain( a_hashIndex, a_particleIndex );
2168
2169 return( ( 1. - fraction ) * gain1 + fraction * gain2 );
2170}
2171
2172/* *********************************************************************************************************//**
2173 * Returns the multi-group gain for particle with intid *a_particleIntid*. If no particle is found, a Vector of all 0's is returned.
2174 *
2175 * @param a_hashIndex [in] The multi-group index.
2176 * @param a_temperature [in] The temperature of the target.
2177 * @param a_particleIntid [in] The intid of the particle whose gain is to be returned.
2178 *
2179 * @return The multi-group gain.
2180 ***********************************************************************************************************/
2181
2182LUPI_HOST_DEVICE double HeatedCrossSectionsMultiGroup::gainViaIntid( std::size_t a_hashIndex, double a_temperature, int a_particleIntid ) const {
2183
2184 if( a_temperature <= m_temperatures[0] ) {
2185 return( m_heatedCrossSections[0]->gainViaIntid( a_hashIndex, a_particleIntid ) ); }
2186 else if( a_temperature >= m_temperatures.back( ) ) {
2187 return( m_heatedCrossSections.back( )->gainViaIntid( a_hashIndex, a_particleIntid ) );
2188 }
2189
2190 std::size_t i1;
2191 for( i1 = 0; i1 < m_temperatures.size( ); ++i1 ) if( a_temperature < m_temperatures[i1] ) break;
2192 double fraction = ( a_temperature - m_temperatures[i1-1] ) / ( m_temperatures[i1] - m_temperatures[i1-1] );
2193
2194 double gain1 = m_heatedCrossSections[i1-1]->gainViaIntid( a_hashIndex, a_particleIntid );
2195 double gain2 = m_heatedCrossSections[i1]->gainViaIntid( a_hashIndex, a_particleIntid );
2196
2197 return( ( 1. - fraction ) * gain1 + fraction * gain2 );
2198}
2199
2200/* *********************************************************************************************************//**
2201 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs index *a_particleIndex*.
2202 *
2203 * @param a_particleIndex [in] The PoPs index of the particle whose user index is to be set.
2204 * @param a_userParticleIndex [in] The particle index specified by the user.
2205 ***********************************************************************************************************/
2206
2207LUPI_HOST void HeatedCrossSectionsMultiGroup::setUserParticleIndex( int a_particleIndex, int a_userParticleIndex ) {
2208
2209 for( auto iter = m_heatedCrossSections.begin( ); iter != m_heatedCrossSections.end( ); ++iter ) (*iter)->setUserParticleIndex( a_particleIndex, a_userParticleIndex );
2210}
2211
2212/* *********************************************************************************************************//**
2213 * Updates the m_userParticleIndex to *a_userParticleIndex* for all particles with PoPs intid *a_particleIntid*.
2214 *
2215 * @param a_particleIntid [in] The intid of the particle whose user index is to be set.
2216 * @param a_userParticleIndex [in] The particle index specified by the user.
2217 ***********************************************************************************************************/
2218
2219LUPI_HOST void HeatedCrossSectionsMultiGroup::setUserParticleIndexViaIntid( int a_particleIntid, int a_userParticleIndex ) {
2220
2221 for( auto iter = m_heatedCrossSections.begin( ); iter != m_heatedCrossSections.end( ); ++iter ) (*iter)->setUserParticleIndexViaIntid( a_particleIntid, a_userParticleIndex );
2222}
2223
2224/* *********************************************************************************************************//**
2225 * This method serializes *this* for broadcasting as needed for MPI and GPUs. The method can count the number of required
2226 * bytes, pack *this* or unpack *this* depending on *a_mode*.
2227 *
2228 * @param a_buffer [in] The buffer to read or write data to depending on *a_mode*.
2229 * @param a_mode [in] Specifies the action of this method.
2230 ***********************************************************************************************************/
2231
2233
2234 DATA_MEMBER_VECTOR_DOUBLE( m_temperatures, a_buffer, a_mode );
2235 DATA_MEMBER_VECTOR_DOUBLE( m_thresholds, a_buffer, a_mode );
2236 DATA_MEMBER_VECTOR_INT( m_multiGroupThresholdIndex, a_buffer, a_mode );
2237 DATA_MEMBER_VECTOR_DOUBLE( m_projectileMultiGroupBoundariesCollapsed, a_buffer, a_mode );
2238
2239 std::size_t vectorSize = m_heatedCrossSections.size( );
2240 int vectorSizeInt = (int) vectorSize;
2241 DATA_MEMBER_INT( vectorSizeInt, a_buffer, a_mode );
2242 vectorSize = (std::size_t) vectorSizeInt;
2243
2244 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) m_heatedCrossSections.resize( vectorSize, &a_buffer.m_placement );
2245 if( a_mode == LUPI::DataBuffer::Mode::Memory ) a_buffer.m_placement += m_heatedCrossSections.internalSize();
2246 for( std::size_t memberIndex = 0; memberIndex < vectorSize; ++memberIndex ) {
2247 if( a_mode == LUPI::DataBuffer::Mode::Unpack ) {
2248 if( a_buffer.m_placement != nullptr ) {
2249 m_heatedCrossSections[memberIndex] = new(a_buffer.m_placement) HeatedCrossSectionMultiGroup;
2250 a_buffer.incrementPlacement( sizeof( HeatedCrossSectionMultiGroup ) ); }
2251 else {
2252 m_heatedCrossSections[memberIndex] = new HeatedCrossSectionMultiGroup;
2253 }
2254 }
2255 if( a_mode == LUPI::DataBuffer::Mode::Memory ) {
2257 }
2258 m_heatedCrossSections[memberIndex]->serialize( a_buffer, a_mode );
2259 }
2260}
2261
2262/* *********************************************************************************************************//**
2263 * This method writes the multi-group data at temperature index *a_temperatureIndex* to *a_file*.
2264 *
2265 * @param a_file [in] The buffer to read or write data to depending on *a_mode*.
2266 * @param a_temperatureIndex [in] The index of the temperature whose data are written.
2267 ***********************************************************************************************************/
2268
2269LUPI_HOST void HeatedCrossSectionsMultiGroup::write( FILE *a_file, int a_temperatureIndex ) const {
2270
2271 if( a_temperatureIndex < 0 ) return;
2272
2273 std::size_t temperatureIndex = (std::size_t) a_temperatureIndex;
2274 if( temperatureIndex >= m_temperatures.size( ) ) return;
2275
2276 printf( "HeatedCrossSectionsMultiGroup::write for temperature %.4e\n", m_temperatures[temperatureIndex] );
2277
2278 fprintf( a_file, " boundaries index " );
2279 std::string space( 14, ' ' );
2280 for( std::size_t index = 0; index < m_projectileMultiGroupBoundariesCollapsed.size( ); ++index ) {
2281 fprintf( a_file, "%s%6zu", space.c_str( ), index );
2282 }
2283 fprintf( a_file, "\n" );
2284 writeVector( a_file, "boundaries", 0, m_projectileMultiGroupBoundariesCollapsed );
2285
2286 m_heatedCrossSections[temperatureIndex]->write( a_file );
2287}
2288
2289/* *********************************************************************************************************//**
2290 * This method calls write for every temperature dataset in *this* with the file type stdout.
2291 ***********************************************************************************************************/
2292
2294
2295 for( std::size_t index = 0; index < m_heatedCrossSections.size( ); ++index ) write( stdout, static_cast<int>( index ) );
2296}
2297
2298/* *********************************************************************************************************//**
2299 * Sets all elements of *a_vector* to 0.0 if *a_zeroReactions* is true, otherwise does nothing.
2300 *
2301 * @param a_vector [in] The vector to zero if *a_zeroReactions* is true.
2302 * @param a_zeroReactions [in] If true all elements of *a_vector* are set to 0.0.
2303 ***********************************************************************************************************/
2304
2305static LUPI_HOST void checkZeroReaction( GIDI::Vector &a_vector, bool a_zeroReactions ) {
2306
2307 if( a_zeroReactions ) a_vector.setToValueInFlatRange( 0, a_vector.size( ), 0.0 );
2308}
2309
2310/* *********************************************************************************************************//**
2311 * Collapses the data in *a_vector* and calls *checkZeroReaction*.
2312 *
2313 * @param a_vector [in] The vector to collapse.
2314 * @param a_settings [in] Used to pass user options to the *this* to instruct it which data are desired.
2315 * @param a_particles [in] List of transporting particles and their information (e.g., multi-group boundaries and fluxes).
2316 * @param a_temperature [in] The temperature or the material.
2317 * @param a_zeroReactions [in] If true all elements of the returned **GIDI::Vector** are set to 0.0.
2318 ***********************************************************************************************************/
2319
2320static LUPI_HOST GIDI::Vector collapseAndcheckZeroReaction( GIDI::Vector &a_vector, Transporting::MC const &a_settings,
2321 GIDI::Transporting::Particles const &a_particles, LUPI_maybeUnused double a_temperature, bool a_zeroReactions ) {
2322
2323 GIDI::Vector vector = GIDI::collapse( a_vector, a_settings, a_particles, 0.0 );
2324 checkZeroReaction( vector, a_zeroReactions );
2325
2326 return( vector );
2327}
2328
2329/* *********************************************************************************************************//**
2330 * @param a_file [in] The buffer to read or write data to depending on *a_mode*.
2331 * @param a_prefix [in] The prefix that starts the beginning of the line that the vector data are written to.
2332 * @param a_offset [in] Specifies the number of spaces to indent the line.
2333 * @param a_vector [in] The vector to write.
2334 ***********************************************************************************************************/
2335
2336static void writeVector( FILE *a_file, std::string const &a_prefix, std::size_t a_offset, Vector<double> const &a_vector ) {
2337
2338 std::string indent( 20 * a_offset, ' ' );
2339
2340 std::string fmt = LUPI::Misc::argumentsToString( " %%-%ds (%%4d) :: %%s", 40 );
2341 fprintf( a_file, fmt.c_str( ), a_prefix.c_str( ), (int) a_vector.size( ), indent.c_str( ) );
2342 for( Vector<double>::const_iterator iter = a_vector.begin( ); iter != a_vector.end( ); ++iter ) fprintf( a_file, " %19.11e", *iter );
2343 fprintf( a_file, "\n" );
2344}
2345
2346}
G4ThreadLocal T * G4GeomSplitter< T >::offset
#define DATA_MEMBER_VECTOR_INT(member, buf, mode)
#define DATA_MEMBER_VECTOR_DOUBLE(member, buf, mode)
#define DATA_MEMBER_SIZE_T(member, buf, mode)
#define DATA_MEMBER_VECTOR_SIZE_T(member, buf, mode)
#define DATA_MEMBER_DOUBLE(member, buf, mode)
#define DATA_MEMBER_INT( member, buf, mode)
#define LUPI_HOST_DEVICE
#define LUPI_THROW(arg)
#define LUPI_HOST
#define LUPI_maybeUnused
#define DATA_MEMBER_VECTOR_FLOAT_OR_DOUBLE
Definition MCGIDI.hpp:19
#define MCGIDI_FLOAT
Definition MCGIDI.hpp:18
#define PoPI_electronMass_MeV_c2
Definition PoPI.hpp:31
virtual void mapToXsAndAdd(std::size_t a_offset, std::vector< double > const &a_Xs, std::vector< double > &a_results, double a_scaleFactor) const
Definition GIDI_form.cc:424
virtual double evaluate(double a_x1) const =0
Function2dForm const * function2d() const
Definition GIDI.hpp:1466
std::vector< double > const & Ys() const
Definition GIDI.hpp:1166
void set(std::size_t a_index, double a_value)
Definition GIDI.hpp:1170
std::size_t start() const
Definition GIDI.hpp:1163
Vector multiGroupDepositionEnergy(LUPI::StatusMessageReporting &a_smr, Transporting::MG const &a_settings, Styles::TemperatureInfo const &a_temperatureInfo, Transporting::Particles const &a_particles, ExcludeReactionsSet const &a_reactionsToExclude=ExcludeReactionsSet {}) const
Vector multiGroupDepositionMomentum(LUPI::StatusMessageReporting &a_smr, Transporting::MG const &a_settings, Styles::TemperatureInfo const &a_temperatureInfo, Transporting::Particles const &a_particles, ExcludeReactionsSet const &a_reactionsToExclude=ExcludeReactionsSet {}) const
Vector multiGroupQ(LUPI::StatusMessageReporting &a_smr, Transporting::MG const &a_settings, Styles::TemperatureInfo const &a_temperatureInfo, bool a_final, bool a_effectivePhotoAtomic=true, ExcludeReactionsSet const &a_reactionsToExclude=ExcludeReactionsSet {}) const
Vector multiGroupGain(LUPI::StatusMessageReporting &a_smr, Transporting::MG const &a_settings, Styles::TemperatureInfo const &a_temperatureInfo, std::string const &a_productID, ExcludeReactionsSet const &a_reactionsToExclude=ExcludeReactionsSet {}) const
Grid const & grid() const
Definition GIDI.hpp:3368
std::string const & griddedCrossSection() const
Definition GIDI.hpp:3432
std::string const & URR_probabilityTables() const
Definition GIDI.hpp:3433
bool has(std::string const &a_label) const
Definition GIDI.hpp:2616
T * get(std::size_t a_Index)
Definition GIDI.hpp:2642
std::map< std::string, Particle > & particles()
Definition GIDI.hpp:3692
bool hasParticle(std::string const &a_id) const
void setThrowOnError(bool a_throwOnError)
Definition GIDI.hpp:3739
std::string const & projectileID() const
Definition GIDI.hpp:3725
DelayedNeutrons delayedNeutrons() const
Definition GIDI.hpp:3727
std::size_t size() const
Definition GIDI_data.hpp:79
void setToValueInFlatRange(std::size_t a_start, std::size_t a_end, double a_value)
LUPI_HOST_DEVICE void incrementPlacement(std::size_t a_delta)
LUPI_HOST_DEVICE int userParticleIndex() const
Definition MCGIDI.hpp:593
LUPI_HOST_DEVICE Vector< MCGIDI_FLOAT > const & gain() const
Definition MCGIDI.hpp:600
LUPI_HOST void print(ProtareSingle const *a_protareSingle, std::string const &a_indent, std::string const &a_iFormat, std::string const &a_energyFormat, std::string const &a_dFormat) const
LUPI_HOST_DEVICE int particleIntid() const
Definition MCGIDI.hpp:591
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE int particleIndex() const
Definition MCGIDI.hpp:592
LUPI_HOST ContinuousEnergyGain & operator=(ContinuousEnergyGain const &a_continuousEnergyGain)
LUPI_HOST_DEVICE Vector< std::size_t > map(Vector< double > const &a_domainValues) const
LUPI_HOST_DEVICE Vector< double > const & energies() const
Definition MCGIDI.hpp:678
LUPI_HOST_DEVICE double depositionMomentum(std::size_t a_hashIndex, double a_energy) const
LUPI_HOST_DEVICE double gain(std::size_t a_hashIndex, double a_energy, int a_particleIndex) const
LUPI_HOST_DEVICE double depositionEnergy(std::size_t a_hashIndex, double a_energy) const
LUPI_HOST_DEVICE double temperature() const
Definition MCGIDI.hpp:643
LUPI_HOST void setUserParticleIndexViaIntid(int a_particleIntid, int a_userParticleIndex)
LUPI_HOST_DEVICE double threshold(std::size_t a_reactionIndex) const
Definition MCGIDI.hpp:651
LUPI_HOST_DEVICE double productionEnergy(std::size_t a_hashIndex, double a_energy) const
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE double gainViaIntid(std::size_t a_hashIndex, double a_energy, int a_particleIntid) const
LUPI_HOST void setUserParticleIndex(int a_particleIndex, int a_userParticleIndex)
LUPI_HOST_DEVICE double reactionCrossSection2(std::size_t a_reactionIndex, URR_protareInfos const &a_URR_protareInfos, int a_URR_index, double a_energy, std::size_t a_energyIndex, double a_energyFraction, bool a_sampling=false) const
LUPI_HOST_DEVICE Vector< MCGIDI_FLOAT > & totalCrossSection()
Definition MCGIDI.hpp:658
LUPI_HOST_DEVICE std::size_t evaluationInfo(std::size_t a_hashIndex, double a_energy, double *a_energyFraction) const
LUPI_HOST GIDI::Functions::XYs1d crossSectionAsGIDI_XYs1d() const
LUPI_HOST GIDI::Functions::XYs1d reactionCrossSectionAsGIDI_XYs1d(std::size_t a_reactionIndex) const
LUPI_HOST void print(ProtareSingle const *a_protareSingle, std::string const &a_indent, std::string const &a_iFormat, std::string const &a_energyFormat, std::string const &a_dFormat) const
LUPI_HOST HeatedReactionCrossSectionContinuousEnergy const * reactionCrossSection(std::size_t a_index) const
Definition MCGIDI.hpp:640
LUPI_HOST_DEVICE std::size_t numberOfReactions() const
Definition MCGIDI.hpp:646
LUPI_HOST_DEVICE double crossSection(URR_protareInfos const &a_URR_protareInfos, int a_URR_index, std::size_t a_hashIndex, double a_energy, bool a_sampling=false) const
LUPI_HOST_DEVICE double gainViaIntid(std::size_t a_hashIndex, int a_particleIntid) const
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST void setUserParticleIndex(int a_particleIndex, int a_userParticleIndex)
LUPI_HOST void setUserParticleIndexViaIntid(int a_particleIntid, int a_userParticleIndex)
LUPI_HOST_DEVICE double gain(std::size_t a_hashIndex, int a_particleIndex) const
LUPI_HOST_DEVICE double crossSection(std::size_t a_hashIndex, bool a_sampling=false) const
LUPI_HOST_DEVICE Vector< double > & totalCrossSection()
Definition MCGIDI.hpp:854
LUPI_HOST_DEVICE double threshold(std::size_t a_index) const
Definition MCGIDI.hpp:713
LUPI_HOST GIDI::Functions::XYs1d crossSectionAsGIDI_XYs1d(double a_temperature) const
Vector< HeatedCrossSectionContinuousEnergy * > & heatedCrossSections()
Definition MCGIDI.hpp:711
LUPI_HOST_DEVICE double productionEnergy(std::size_t a_hashIndex, double a_temperature, double a_energy) const
LUPI_HOST_DEVICE double depositionEnergy(std::size_t a_hashIndex, double a_temperature, double a_energy) const
LUPI_HOST void update(LUPI::StatusMessageReporting &a_smr, SetupInfo &a_setupInfo, Transporting::MC const &a_settings, GIDI::Transporting::Particles const &a_particles, DomainHash const &a_domainHash, GIDI::Styles::TemperatureInfos const &a_temperatureInfos, std::vector< GIDI::Reaction const * > const &a_reactions, std::vector< GIDI::Reaction const * > const &a_orphanProducts, bool a_fixedGrid, bool a_zeroReactions)
LUPI_HOST_DEVICE double crossSection(URR_protareInfos const &a_URR_protareInfos, int a_URR_index, std::size_t a_hashIndex, double a_temperature, double a_energy, bool a_sampling=false) const
LUPI_HOST_DEVICE double gain(std::size_t a_hashIndex, double a_temperature, double a_energy, int a_particleIndex) const
LUPI_HOST void setUserParticleIndex(int a_particleIndex, int a_userParticleIndex)
LUPI_HOST_DEVICE double reactionCrossSection(std::size_t a_reactionIndex, URR_protareInfos const &a_URR_protareInfos, int a_URR_index, std::size_t a_hashIndex, double a_temperature, double a_energy, bool a_sampling=false) const
LUPI_HOST void setUserParticleIndexViaIntid(int a_particleIntid, int a_userParticleIndex)
LUPI_HOST_DEVICE double depositionMomentum(std::size_t a_hashIndex, double a_temperature, double a_energy) const
LUPI_HOST GIDI::Functions::XYs1d reactionCrossSectionAsGIDI_XYs1d(std::size_t a_reactionIndex, double a_temperature) const
LUPI_HOST void print(ProtareSingle const *a_protareSingle, std::string const &a_indent, std::string const &a_iFormat, std::string const &a_energyFormat, std::string const &a_dFormat) const
LUPI_HOST_DEVICE double gainViaIntid(std::size_t a_hashIndex, double a_temperature, double a_energy, int a_particleIntid) const
LUPI_HOST_DEVICE void crossSectionVector(double a_temperature, double a_userFactor, std::size_t a_numberAllocated, double *a_crossSectionVector) const
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE double productionEnergy(std::size_t a_hashIndex, double a_temperature) const
LUPI_HOST_DEVICE double depositionMomentum(std::size_t a_hashIndex, double a_temperature) const
LUPI_HOST_DEVICE double depositionEnergy(std::size_t a_hashIndex, double a_temperature) const
LUPI_HOST_DEVICE double gain(std::size_t a_hashIndex, double a_temperature, int a_particleIndex) const
LUPI_HOST void write(FILE *a_file, int a_temperatureIndex) const
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE double crossSection(std::size_t a_hashIndex, double a_temperature, bool a_sampling=false) const
LUPI_HOST_DEVICE double reactionCrossSection(std::size_t a_reactionIndex, std::size_t a_hashIndex, double a_temperature, bool a_sampling=false) const
LUPI_HOST_DEVICE double threshold(std::size_t a_index) const
Definition MCGIDI.hpp:908
LUPI_HOST void setUserParticleIndexViaIntid(int a_particleIntid, int a_userParticleIndex)
LUPI_HOST_DEVICE void crossSectionVector(double a_temperature, double a_userFactor, std::size_t a_numberAllocated, double *a_crossSectionVector) const
LUPI_HOST void setUserParticleIndex(int a_particleIndex, int a_userParticleIndex)
LUPI_HOST void update(LUPI::StatusMessageReporting &a_smr, GIDI::ProtareSingle const &a_protare, SetupInfo &a_setupInfo, Transporting::MC const &a_settings, GIDI::Transporting::Particles const &a_particles, GIDI::Styles::TemperatureInfos const &a_temperatureInfos, std::vector< GIDI::Reaction const * > const &a_reactions, std::vector< GIDI::Reaction const * > const &a_orphanProducts, bool a_zeroReactions, GIDI::ExcludeReactionsSet const &a_reactionsToExclude)
LUPI_HOST_DEVICE double gainViaIntid(std::size_t a_hashIndex, double a_temperature, int a_particleIntid) const
LUPI_HOST GIDI::Functions::XYs1d crossSectionAsGIDI_XYs1d(double a_temperature, Vector< double > const &a_energies) const
LUPI_HOST_DEVICE double crossSection(std::size_t a_index) const
Definition MCGIDI.hpp:557
LUPI_HOST_DEVICE Transporting::URR_mode URR_mode() const
Definition MCGIDI.hpp:552
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST void print(ProtareSingle const *a_protareSingle, std::string const &a_indent, std::string const &a_iFormat, std::string const &a_energyFormat, std::string const &a_dFormat) const
LUPI_HOST void write(FILE *a_file, std::size_t a_reactionIndex) const
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST void write(FILE *a_file) const
LUPI_HOST_DEVICE int particleIntid() const
Definition MCGIDI.hpp:767
LUPI_HOST_DEVICE Vector< double > const & gain() const
Definition MCGIDI.hpp:776
LUPI_HOST_DEVICE int userParticleIndex() const
Definition MCGIDI.hpp:769
LUPI_HOST MultiGroupGain & operator=(MultiGroupGain const &a_multiGroupGain)
LUPI_HOST_DEVICE void serialize(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE int particleIndex() const
Definition MCGIDI.hpp:768
LUPI_HOST_DEVICE double averageGammaEnergy() const
Definition MCGIDI.hpp:992
LUPI_HOST_DEVICE double multiplicity() const
Definition MCGIDI.hpp:991
LUPI_HOST_DEVICE Reaction const * reaction(std::size_t a_index) const
Definition MCGIDI.hpp:1695
LUPI_HOST_DEVICE bool isPhotoAtomic() const
Definition MCGIDI.hpp:1650
LUPI_HOST_DEVICE const Vector< NuclideGammaBranchStateInfo * > & nuclideGammaBranchStateInfos() const
Definition MCGIDI.hpp:1658
LUPI_HOST Vector< double > const & projectileMultiGroupBoundariesCollapsed() const
Definition MCGIDI.hpp:1691
LUPI_HOST_DEVICE int projectileIntid() const
Definition MCGIDI.hpp:1517
std::map< std::string, ACE_URR_probabilityTablesFromGIDI * > m_ACE_URR_probabilityTablesFromGIDI
Definition MCGIDI.hpp:279
std::map< std::string, int > m_particleIntids
Definition MCGIDI.hpp:270
std::map< std::string, int > m_initialStateIndices
Definition MCGIDI.hpp:276
std::map< std::string, int > m_particleIndices
Definition MCGIDI.hpp:271
ProtareSingle & m_protare
Definition MCGIDI.hpp:254
LUPI_HOST std::vector< double > fixedGridPoints() const
Definition MCGIDI.hpp:212
LUPI_HOST bool useSlowerContinuousEnergyConversion() const
Definition MCGIDI.hpp:151
LUPI_HOST Sampling::Upscatter::Model upscatterModel() const
Definition MCGIDI.hpp:176
LUPI_HOST URR_mode _URR_mode() const
Definition MCGIDI.hpp:194
LUPI_HOST bool addExpectedValueData() const
Definition MCGIDI.hpp:155
LUPI_HOST GIDI::Styles::Suite const * styles() const
Definition MCGIDI.hpp:131
LUPI_HOST_DEVICE std::size_t size() const
LUPI_HOST_DEVICE iterator begin()
LUPI_HOST_DEVICE void resize(std::size_t s, char **address=nullptr, bool mem_flag=CPU_MEM)
LUPI_HOST_DEVICE iterator end()
std::vector< Styles::TemperatureInfo > TemperatureInfos
Definition GIDI.hpp:3440
Vector collapse(Vector const &a_vector, Transporting::Settings const &a_settings, Transporting::Particles const &a_particles, double a_temperature)
std::set< std::size_t > ExcludeReactionsSet
Definition GIDI.hpp:47
std::string argumentsToString(char const *a_format,...)
Definition LUPI_misc.cc:305
std::string doubleToString3(char const *a_format, double a_value, bool a_reduceBits=false)
Definition LUPI_misc.cc:327
LUPI_HOST ProbabilityBase2d * parseProbability2d(Transporting::MC const &a_settings, GIDI::Suite const &a_suite, SetupInfo *a_setupInfo)
LUPI_HOST_DEVICE std::size_t evaluationForHashIndex(std::size_t a_hashIndex, Vector< std::size_t > const &a_hashIndices, double a_energy, Vector< double > const &a_energies, double *a_energyFraction)
Simple C++ string class, useful as replacement for std::string if this cannot be used,...
Definition MCGIDI.hpp:43
LUPI_HOST_DEVICE Probabilities::ProbabilityBase2d * serializeProbability2d(LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode, Probabilities::ProbabilityBase2d *a_probability2d)
LUPI_HOST Vector< double > GIDI_VectorDoublesToMCGIDI_VectorDoubles(GIDI::Vector a_vector)
LUPI_HOST_DEVICE ACE_URR_probabilityTables * serializeACE_URR_probabilityTables(ACE_URR_probabilityTables *a_ACE_URR_probabilityTables, LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE Transporting::URR_mode serializeURR_mode(Transporting::URR_mode a_URR_mode, LUPI::DataBuffer &a_buffer, LUPI::DataBuffer::Mode a_mode)
LUPI_HOST_DEVICE int binarySearchVector(double a_x, Vector< double > const &a_Xs, bool a_boundIndex=false)
Definition MCGIDI.hpp:318
LUPI_HOST std::vector< double > vectorToSTD_vector(Vector< double > a_input)
@ ptwXY_interpolationLinLin
Definition ptwXY.h:37
static std::string const photon
Definition PoPI.hpp:162
static std::string const electron
Definition PoPI.hpp:163