Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
MCGIDI_energy.cc
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# <<END-copyright>>
4*/
5#include <string.h>
6#include <cmath>
7
8#ifdef WIN32
9#define M_PI 3.141592653589793238463
10#endif
11
12#include "MCGIDI_fromTOM.h"
13#include "MCGIDI_misc.h"
14#include "MCGIDI_private.h"
15#include <nf_specialFunctions.h>
16
17#if defined __cplusplus
18#include "G4Exp.hh"
19#include "G4Log.hh"
20#include "G4Pow.hh"
21namespace GIDI {
22using namespace GIDI;
23#endif
24
25static int MCGIDI_energy_parseWeightFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energyWeightedFunctional *weightedFunctional );
26static int MCGIDI_energy_parseWeightedFunctionalsFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy );
27static int MCGIDI_energy_parseGeneralEvaporationFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy );
28static int MCGIDI_energy_parseEvaporationFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy );
29static int MCGIDI_energy_parseWattFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy );
30static int MCGIDI_energy_parseSimpleMaxwellianFissionFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy );
31static int MCGIDI_energy_parseMadlandNixFromTOM( statusMessageReporting *smr, xDataTOM_element *functional, MCGIDI_energy *energy );
32static nfu_status MCGIDI_energy_parseMadlandNixFromTOM_callback( double x, double *y, void *argList );
33static double MCGIDI_energy_parseMadlandNixFromTOM_callback_g( double Ep, double EFL, double T_M, nfu_status *status );
34static int MCGIDI_energy_parseNBodyPhaseSpaceFromTOM( statusMessageReporting *smr, xDataTOM_element *functional, MCGIDI_energy *energy,
35 MCGIDI_distribution *distribution );
36
37static int MCGIDI_energy_sampleSimpleMaxwellianFission( statusMessageReporting *smr, double e_in_U_theta, MCGIDI_decaySamplingInfo *decaySamplingInfo );
38static int MCGIDI_energy_sampleEvaporation( statusMessageReporting *smr, double e_in_U_theta, MCGIDI_decaySamplingInfo *decaySamplingInfo );
39static int MCGIDI_energy_sampleWatt( statusMessageReporting *smr, double e_in_U, double Watt_a, double Watt_b, MCGIDI_decaySamplingInfo *decaySamplingInfo );
40static int MCGIDI_energy_sampleWeightedFunctional( statusMessageReporting *smr, MCGIDI_energy *energy,
41 MCGIDI_quantitiesLookupModes &modes, MCGIDI_decaySamplingInfo *decaySamplingInfo );
42static nfu_status MCGIDI_energy_NBodyPhaseSpacePDF_callback( double x, double *y, void *argList );
43/*
44************************************************************
45*/
47
48 MCGIDI_energy *energy;
49
50 if( ( energy = (MCGIDI_energy *) smr_malloc2( smr, sizeof( MCGIDI_energy ), 0, "energy" ) ) == NULL ) return( NULL );
51 if( MCGIDI_energy_initialize( smr, energy ) ) energy = MCGIDI_energy_free( smr, energy );
52 return( energy );
53}
54/*
55************************************************************
56*/
58
59 memset( energy, 0, sizeof( MCGIDI_energy ) );
60 return( 0 );
61}
62/*
63************************************************************
64*/
66
67 MCGIDI_energy_release( smr, energy );
68 smr_freeMemory( (void **) &energy );
69 return( NULL );
70}
71/*
72************************************************************
73*/
75
76 int i;
77
78 MCGIDI_sampling_pdfsOfXGivenW_release( smr, &(energy->dists) );
79 if( energy->theta ) energy->theta = ptwXY_free( energy->theta );
80 if( energy->Watt_a ) energy->Watt_a = ptwXY_free( energy->Watt_a );
81 if( energy->Watt_b ) energy->Watt_b = ptwXY_free( energy->Watt_b );
82 if( ( energy->type == MCGIDI_energyType_generalEvaporation ) || ( energy->type == MCGIDI_energyType_NBodyPhaseSpace ) ) {
83 MCGIDI_sampling_pdfsOfX_release( smr, &(energy->g) ); }
84 else if( energy->type == MCGIDI_energyType_weightedFunctional ) {
85 for( i = 0; i < energy->weightedFunctionals.numberOfWeights; i++ ) {
86 ptwXY_free( energy->weightedFunctionals.weightedFunctional[i].weight );
87 MCGIDI_energy_free( smr, energy->weightedFunctionals.weightedFunctional[i].energy );
88 }
89 }
90
91 MCGIDI_energy_initialize( smr, energy );
92 return( 0 );
93}
94/*
95************************************************************
96*/
98 enum MCGIDI_energyType energyType, double gammaEnergy_MeV ) {
99
100 MCGIDI_energy *energy = NULL;
101 xDataTOM_element *energyElement, *linearElement, *functional, *frameElement;
102 char const *nativeData;
103 double projectileMass_MeV, targetMass_MeV;
104
105 if( ( energy = MCGIDI_energy_new( smr ) ) == NULL ) goto err;
106
107 projectileMass_MeV = MCGIDI_product_getProjectileMass_MeV( smr, distribution->product );
108 targetMass_MeV = MCGIDI_product_getTargetMass_MeV( smr, distribution->product );
109 energy->e_inCOMFactor = targetMass_MeV / ( projectileMass_MeV + targetMass_MeV );
110
111 if( ( energyType == MCGIDI_energyType_primaryGamma ) || ( energyType == MCGIDI_energyType_discreteGamma ) ) {
112 energy->type = energyType;
113 energy->gammaEnergy_MeV = gammaEnergy_MeV;
114 energy->frame = xDataTOM_frame_lab; /* BRB. This should not be hardwired?????? Probably needs to be changed in GND also. */
115 if( energyType == MCGIDI_energyType_primaryGamma ) energy->primaryGammaMassFactor = energy->e_inCOMFactor; }
116 else {
117 if( ( energyElement = xDataTOME_getOneElementByName( smr, element, "energy", 1 ) ) == NULL ) goto err;
118 if( ( nativeData = xDataTOM_getAttributesValueInElement( energyElement, "nativeData" ) ) == NULL ) goto err;
119 if( ( linearElement = xDataTOME_getOneElementByName( NULL, energyElement, "linear", 0 ) ) == NULL )
120 linearElement = xDataTOME_getOneElementByName( NULL, energyElement, "pointwise", 0 );
121 if( linearElement == NULL ) {
122 if( ( functional = xDataTOME_getOneElementByName( NULL, energyElement, "generalEvaporation", 0 ) ) != NULL ) {
123 if( MCGIDI_energy_parseGeneralEvaporationFromTOM( smr, functional, energy ) ) goto err; }
124 else if( ( functional = xDataTOME_getOneElementByName( NULL, energyElement, "simpleMaxwellianFission", 0 ) ) != NULL ) {
125 if( MCGIDI_energy_parseSimpleMaxwellianFissionFromTOM( smr, functional, energy ) ) goto err; }
126 else if( ( functional = xDataTOME_getOneElementByName( NULL, energyElement, "evaporation", 0 ) ) != NULL ) {
127 if( MCGIDI_energy_parseEvaporationFromTOM( smr, functional, energy ) ) goto err; }
128 else if( ( functional = xDataTOME_getOneElementByName( NULL, energyElement, "Watt", 0 ) ) != NULL ) {
129 if( MCGIDI_energy_parseWattFromTOM( smr, functional, energy ) ) goto err; }
130 else if( ( functional = xDataTOME_getOneElementByName( NULL, energyElement, "MadlandNix", 0 ) ) != NULL ) {
131 if( MCGIDI_energy_parseMadlandNixFromTOM( smr, functional, energy ) ) goto err; }
132 else if( ( functional = xDataTOME_getOneElementByName( NULL, energyElement, "NBodyPhaseSpace", 0 ) ) != NULL ) {
133 if( MCGIDI_energy_parseNBodyPhaseSpaceFromTOM( smr, functional, energy, distribution ) ) goto err; }
134 else if( ( functional = xDataTOME_getOneElementByName( NULL, energyElement, "weightedFunctionals", 0 ) ) != NULL ) {
135 if( MCGIDI_energy_parseWeightedFunctionalsFromTOM( smr, functional, energy ) ) goto err; }
136 else {
137 smr_setReportError2( smr, smr_unknownID, 1, "unsupported energy type: nativeData = '%s'", nativeData );
138 goto err;
139 }
140 frameElement = functional; }
141 else {
142 char const *toUnits[3] = { "MeV", "MeV", "1/MeV" };
143
144 frameElement = linearElement;
145 if( MCGIDI_fromTOM_pdfsOfXGivenW( smr, linearElement, &(energy->dists), norms, toUnits ) ) goto err;
146 energy->type = MCGIDI_energyType_linear;
147 }
148 if( ( energy->frame = MCGIDI_misc_getProductFrame( smr, frameElement ) ) == xDataTOM_frame_invalid ) goto err;
149 }
150 distribution->energy = energy;
151
152 return( 0 );
153
154err:
155 if( energy != NULL ) MCGIDI_energy_free( smr, energy );
156 return( 1 );
157}
158/*
159************************************************************
160*/
161static int MCGIDI_energy_parseWeightedFunctionalsFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy ) {
162
163 int i;
164 xDataTOM_element *child;
165
166 for( i = 0, child = xDataTOME_getFirstElement( element ); child != NULL; i++, child = xDataTOME_getNextElement( child ) ) {
167 if( strcmp( child->name, "weighted" ) ) goto err;
168 if( MCGIDI_energy_parseWeightFromTOM( smr, child, &(energy->weightedFunctionals.weightedFunctional[i]) ) ) goto err;
169 energy->weightedFunctionals.numberOfWeights++;
170 }
172 return( 0 );
173
174err:
175 return( 1 );
176}
177/*
178************************************************************
179*/
180static int MCGIDI_energy_parseWeightFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energyWeightedFunctional *weightedFunctional ) {
181
182 xDataTOM_element *child;
183 MCGIDI_energy *energy = NULL;
184 ptwXYPoints *weight = NULL;
185 char const *toUnits[2] = { "MeV", "" };
186
187 if( ( energy = MCGIDI_energy_new( smr ) ) == NULL ) goto err;
188 for( child = xDataTOME_getFirstElement( element ); child != NULL; child = xDataTOME_getNextElement( child ) ) {
189 if( strcmp( child->name, "weight" ) == 0 ) {
190 if( ( weight = MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf( smr, child, toUnits ) ) == NULL ) goto err; }
191 else if( strcmp( child->name, "evaporation" ) == 0 ) {
192 if( MCGIDI_energy_parseEvaporationFromTOM( smr, child, energy ) ) goto err; }
193 else {
194 smr_setReportError2( smr, smr_unknownID, 1, "unsupported energy type = '%s' in weighted functional", child->name );
195 goto err;
196 }
197 }
198 weightedFunctional->weight = weight;
199 weightedFunctional->energy = energy;
200 return( 0 );
201
202err:
203 if( weight != NULL ) ptwXY_free( weight );
204 if( energy != NULL ) MCGIDI_energy_free( smr, energy );
205 return( 1 );
206}
207/*
208************************************************************
209*/
210static int MCGIDI_energy_parseGeneralEvaporationFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy ) {
211
212 double norm;
213 xDataTOM_element *thetaTOM, *gTOM;
214 ptwXYPoints *theta = NULL, *g = NULL;
215 char const *toUnits[2] = { "MeV", "MeV" };
216
217 if( ( thetaTOM = xDataTOME_getOneElementByName( smr, element, "theta", 1 ) ) == NULL ) goto err;
218 if( ( theta = MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf( smr, thetaTOM, toUnits ) ) == NULL ) goto err;
219
220 if( ( gTOM = xDataTOME_getOneElementByName( smr, element, "g", 1 ) ) == NULL ) goto err;
221 toUnits[0] = "";
222 toUnits[1] = "";
223 if( ( g = MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf( smr, gTOM, toUnits ) ) == NULL ) goto err;
224 if( MCGIDI_fromTOM_pdfOfX( smr, g, &(energy->g), &norm ) ) goto err;
225 energy->gInterpolation = ptwXY_getInterpolation( g );
226 g = ptwXY_free( g );
227 if( std::fabs( 1. - norm ) > 0.001 ) printf( "bad norm = %e\n", norm );
228
230 energy->theta = theta;
231 return( 0 );
232
233err:
234 if( theta != NULL ) ptwXY_free( theta );
235 if( g != NULL ) ptwXY_free( g );
236 return( 1 );
237}
238/*
239************************************************************
240*/
241static int MCGIDI_energy_parseSimpleMaxwellianFissionFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy ) {
242
243 char const *U, *toUnits[2] = { "MeV", "MeV" };
244 xDataTOM_element *thetaTOM;
245
246 if( ( U = xDataTOM_getAttributesValueInElement( element, "U" ) ) == NULL ) {
247 smr_setReportError2( smr, smr_unknownID, 1, "functional form '%s' missing 'U' attribute", element->name );
248 goto err;
249 }
250 if( MCGIDI_misc_PQUStringToDoubleInUnitOf( smr, U, "MeV", &(energy->U) ) != 0 ) goto err;
251 if( ( thetaTOM = xDataTOME_getOneElementByName( smr, element, "theta", 1 ) ) == NULL ) goto err;
252 if( ( energy->theta = MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf( smr, thetaTOM, toUnits ) ) == NULL ) goto err;
254 return( 0 );
255
256err:
257 return( 1 );
258}
259/*
260************************************************************
261*/
262static int MCGIDI_energy_parseEvaporationFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy ) {
263
264 char const *U, *toUnits[2] = { "MeV", "MeV" };
265 xDataTOM_element *thetaTOM;
266
267 if( ( U = xDataTOM_getAttributesValueInElement( element, "U" ) ) == NULL ) {
268 smr_setReportError2( smr, smr_unknownID, 1, "functional form '%s' missing 'U' attribute", element->name );
269 goto err;
270 }
271 if( MCGIDI_misc_PQUStringToDoubleInUnitOf( smr, U, "MeV", &(energy->U) ) != 0 ) goto err;
272 if( ( thetaTOM = xDataTOME_getOneElementByName( smr, element, "theta", 1 ) ) == NULL ) goto err;
273 if( ( energy->theta = MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf( smr, thetaTOM, toUnits ) ) == NULL ) goto err;
275 return( 0 );
276
277err:
278 return( 1 );
279}
280/*
281************************************************************
282*/
283static int MCGIDI_energy_parseWattFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_energy *energy ) {
284
285 char const *U, *toUnits[2] = { "MeV", "MeV" };
286 xDataTOM_element *aOrBTOM;
287
288 if( ( U = xDataTOM_getAttributesValueInElement( element, "U" ) ) == NULL ) {
289 smr_setReportError2( smr, smr_unknownID, 1, "functional form '%s' missing 'U' attribute", element->name );
290 goto err;
291 }
292 if( MCGIDI_misc_PQUStringToDoubleInUnitOf( smr, U, "MeV", &(energy->U) ) != 0 ) goto err;
293
294 if( ( aOrBTOM = xDataTOME_getOneElementByName( smr, element, "a", 1 ) ) == NULL ) goto err;
295 if( ( energy->Watt_a = MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf( smr, aOrBTOM, toUnits ) ) == NULL ) goto err;
296
297 toUnits[1] = "1/MeV";
298 if( ( aOrBTOM = xDataTOME_getOneElementByName( smr, element, "b", 1 ) ) == NULL ) goto err;
299 if( ( energy->Watt_b = MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf( smr, aOrBTOM, toUnits ) ) == NULL ) goto err;
300
302 return( 0 );
303
304err:
305 return( 1 );
306}
307/*
308************************************************************
309*/
310static int MCGIDI_energy_parseMadlandNixFromTOM( statusMessageReporting *smr, xDataTOM_element *functional, MCGIDI_energy *energy ) {
311
312 int iE, length, nXs, i1, n;
313 double E=0., T_M=0., EFL=0., EFH=0., argList[3] = { 0., 0., 0. },
314 xs[] = { 1e-5, 1e-3, 1e-1, 1e1, 1e3, 1e5, 3e7 }, norm;
315 ptwXYPoints *ptwXY_TM = NULL, *pdfXY = NULL;
316 ptwXYPoint *point;
317 ptwXPoints *cdfX = NULL;
318 nfu_status status = nfu_Okay;
319 xDataTOM_element *TM_TOM;
320 xDataTOM_XYs *XYs;
321 MCGIDI_pdfsOfXGivenW *dists = &(energy->dists);
322 MCGIDI_pdfOfX *dist;
323 char const *EF, *TMUnits[2] = { "MeV", "MeV" };
324
325 nXs = sizeof( xs ) / sizeof( xs[0] );
326
327 if( ( EF = xDataTOM_getAttributesValueInElement( functional, "EFL" ) ) == NULL ) {
328 smr_setReportError2( smr, smr_unknownID, 1, "MadlandNix '%s' missing 'EFL' attribute", functional->name );
329 goto err;
330 }
331 if( MCGIDI_misc_PQUStringToDoubleInUnitOf( smr, EF, TMUnits[0], &EFL ) != 0 ) goto err;
332 argList[0] = EFL;
333
334 if( ( EF = xDataTOM_getAttributesValueInElement( functional, "EFH" ) ) == NULL ) {
335 smr_setReportError2( smr, smr_unknownID, 1, "MadlandNix '%s' missing 'EFH' attribute", functional->name );
336 goto err;
337 }
338 if( MCGIDI_misc_PQUStringToDoubleInUnitOf( smr, EF, TMUnits[0], &EFH ) != 0 ) goto err;
339 argList[1] = EFH;
340
341 if( ( TM_TOM = xDataTOME_getOneElementByName( smr, functional, "T_M", 1 ) ) == NULL ) goto err;
342 if( ( XYs = (xDataTOM_XYs *) xDataTOME_getXDataIfID( smr, TM_TOM, "XYs" ) ) == NULL ) goto err;
343 if( ( ptwXY_TM = MCGIDI_misc_dataFromXYs2ptwXYPointsInUnitsOf( smr, XYs, ptwXY_interpolationLinLin, TMUnits ) ) == NULL ) goto err;
344
345 length = (int) ptwXY_length( ptwXY_TM );
347 dists->interpolationXY = ptwXY_interpolationLinLin; /* Ignoring what the data says as it is probably wrong. */
348 if( ( dists->Ws = (double *) smr_malloc2( smr, length * sizeof( double ), 1, "dists->Ws" ) ) == NULL ) goto err;
349 if( ( dists->dist = (MCGIDI_pdfOfX *) smr_malloc2( smr, length * sizeof( MCGIDI_pdfOfX ), 0, "dists->dist" ) ) == NULL ) goto err;
350
351 for( iE = 0; iE < length; iE++ ) {
352 ptwXY_getXYPairAtIndex( ptwXY_TM, iE, &E, &T_M );
353 argList[2] = T_M;
354 dist = &(dists->dist[iE]);
355 dists->Ws[iE] = E;
356
357 if( ( pdfXY = ptwXY_createFromFunction( nXs, xs, (ptwXY_createFromFunction_callback) MCGIDI_energy_parseMadlandNixFromTOM_callback,
358 (void *) argList, 1e-3, 0, 12, &status ) ) == NULL ) goto err;
359 if( ( status = ptwXY_normalize( pdfXY ) ) != nfu_Okay ) {
360 smr_setReportError2( smr, smr_unknownID, 1, "ptwXY_normalize err = %d: %s\n", status, nfu_statusMessage( status ) );
361 goto err;
362 }
363
364 if( ptwXY_simpleCoalescePoints( pdfXY ) != nfu_Okay ) goto err;
365 dist->numberOfXs = n = (int) ptwXY_length( pdfXY );
366
367 if( ( dist->Xs = (double *) smr_malloc2( smr, 3 * n * sizeof( double ), 0, "dist->Xs" ) ) == NULL ) goto err;
368 dists->numberOfWs++;
369 dist->pdf = &(dist->Xs[n]);
370 dist->cdf = &(dist->pdf[n]);
371
372 for( i1 = 0; i1 < n; i1++ ) {
373 point = ptwXY_getPointAtIndex_Unsafely( pdfXY, i1 );
374 dist->Xs[i1] = point->x;
375 dist->pdf[i1] = point->y;
376 }
377
378 if( ( cdfX = ptwXY_runningIntegral( pdfXY, &status ) ) == NULL ) {
379 smr_setReportError2( smr, smr_unknownID, 1, "ptwXY_runningIntegral err = %d: %s\n", status, nfu_statusMessage( status ) );
380 goto err;
381 }
382
383 norm = ptwX_getPointAtIndex_Unsafely( cdfX, n - 1 );
384 for( i1 = 0; i1 < n; i1++ ) dist->cdf[i1] = ptwX_getPointAtIndex_Unsafely( cdfX, i1 ) / norm;
385 for( i1 = 0; i1 < n; i1++ ) dist->pdf[i1] /= norm;
386 pdfXY = ptwXY_free( pdfXY );
387 cdfX = ptwX_free( cdfX );
388 }
389
391
392 ptwXY_free( ptwXY_TM );
393 return( 0 );
394
395err:
396 if( ptwXY_TM != NULL ) ptwXY_free( ptwXY_TM );
397 if( pdfXY != NULL ) ptwXY_free( pdfXY );
398 if( cdfX != NULL ) cdfX = ptwX_free( cdfX );
399
400 return( 1 );
401}
402/*
403************************************************************
404*/
405static nfu_status MCGIDI_energy_parseMadlandNixFromTOM_callback( double Ep, double *y, void *argList ) {
406
407 double *parameters = (double *) argList, EFL, EFH, T_M;
408 nfu_status status = nfu_Okay;
409
410 EFL = parameters[0];
411 EFH = parameters[1];
412 T_M = parameters[2];
413 *y = MCGIDI_energy_parseMadlandNixFromTOM_callback_g( Ep, EFL, T_M, &status );
414 if( status == nfu_Okay ) *y += MCGIDI_energy_parseMadlandNixFromTOM_callback_g( Ep, EFH, T_M, &status );
415 *y *= 0.5;
416 return( status );
417}
418/*
419************************************************************
420*/
421static double MCGIDI_energy_parseMadlandNixFromTOM_callback_g( double Ep, double E_F, double T_M, nfu_status *status ) {
422
423 double u1, u2, E1, E2 = 0., gamma1 = 0., gamma2 = 0., signG = 1;
424
425 u1 = std::sqrt( Ep ) - std::sqrt( E_F );
426 u1 *= u1 / T_M;
427 u2 = std::sqrt( Ep ) + std::sqrt( E_F );
428 u2 *= u2 / T_M;
429 E1 = 0; /* u1^3/2 * E1 is zero for u1 = 0. but E1 is infinity, whence, the next test. */
430 if( u1 != 0 ) E1 = nf_exponentialIntegral( 1, u1, status );
431 if( *status == nfu_Okay ) E2 = nf_exponentialIntegral( 1, u2, status );
432 if( *status != nfu_Okay ) return( 0. );
433 if( u1 > 2. ) {
434 signG = -1;
435 gamma1 = nf_incompleteGammaFunctionComplementary( 1.5, u1, status );
436 if( *status == nfu_Okay ) gamma2 = nf_incompleteGammaFunctionComplementary( 1.5, u2, status ); }
437 else {
438 gamma1 = nf_incompleteGammaFunction( 1.5, u1, status );
439 if( *status == nfu_Okay ) gamma2 = nf_incompleteGammaFunction( 1.5, u2, status );
440 }
441 if( *status != nfu_Okay ) return( 0. );
442 return( ( u2 * std::sqrt( u2 ) * E2 - u1 * std::sqrt( u1 ) * E1 + signG * ( gamma2 - gamma1 ) ) / ( 3 * std::sqrt( E_F * T_M ) ) );
443}
444/*
445************************************************************
446*/
447static int MCGIDI_energy_parseNBodyPhaseSpaceFromTOM( statusMessageReporting *smr, xDataTOM_element *functional, MCGIDI_energy *energy,
448 MCGIDI_distribution *distribution ) {
449
450 int argList[1];
451 double xs[2] = { 0.0, 1.0 }, productMass_MeV, norm;
452 ptwXYPoints *pdf = NULL;
453 nfu_status status;
454 char const *mass;
455
456 if( xDataTOME_convertAttributeToInteger( NULL, functional, "numberOfProducts", &(energy->NBodyPhaseSpace.numberOfProducts) ) != 0 ) goto err;
457 if( ( mass = xDataTOM_getAttributesValueInElement( functional, "mass" ) ) == NULL ) {
458 smr_setReportError2( smr, smr_unknownID, 1, "functional form '%s' missing 'mass' attribute", functional->name );
459 goto err;
460 }
461 if( MCGIDI_misc_PQUStringToDouble( smr, mass, "amu", MCGIDI_AMU2MeV, &(energy->NBodyPhaseSpace.mass) ) ) goto err;
462 argList[0] = energy->NBodyPhaseSpace.numberOfProducts;
463 if( ( pdf = ptwXY_createFromFunction( 2, xs, MCGIDI_energy_NBodyPhaseSpacePDF_callback, (void *) argList, 1e-3, 0, 16, &status ) ) == NULL ) {
464 smr_setReportError2( smr, smr_unknownID, 1, "creating NBodyPhaseSpace pdf failed with ptwXY_createFromFunction error = %d (%s)",
465 status, nfu_statusMessage( status ) );
466 goto err;
467 }
468 if( MCGIDI_fromTOM_pdfOfX( smr, pdf, &(energy->g), &norm ) ) goto err;
469 productMass_MeV = MCGIDI_product_getMass_MeV( smr, distribution->product );
470 if( !smr_isOk( smr ) ) goto err;
471 energy->NBodyPhaseSpace.massFactor = ( 1. - productMass_MeV / ( MCGIDI_AMU2MeV * energy->NBodyPhaseSpace.mass ) ); /* ??????? Hardwired MCGIDI_AMU2MeV */
472 energy->NBodyPhaseSpace.Q_MeV = MCGIDI_outputChannel_getQ_MeV( smr, distribution->product->outputChannel, 0. );
473 if( !smr_isOk( smr ) ) goto err;
474
475 ptwXY_free( pdf );
477
478 return( 0 );
479
480err:
481 if( pdf != NULL ) ptwXY_free( pdf );
482 return( 1 );
483}
484/*
485************************************************************
486*/
487static nfu_status MCGIDI_energy_NBodyPhaseSpacePDF_callback( double x, double *y, void *argList ) {
488
489 int numberOfProducts = *((int *) argList);
490 double e = 0.5 * ( 3 * numberOfProducts - 8 );
491
492 *y = std::sqrt( x ) * G4Pow::GetInstance()->powA( 1.0 - x, e );
493 return( nfu_Okay );
494}
495/*
496************************************************************
497*/
499 MCGIDI_decaySamplingInfo *decaySamplingInfo ) {
500/*
501* This function must be called before angular sampling as it sets the frame but does not test it.
502*/
503 double theta, randomEp, Watt_a, Watt_b, e_in = modes.getProjectileEnergy( );
505
506 decaySamplingInfo->frame = energy->frame;
507 switch( energy->type ) {
509 decaySamplingInfo->Ep = energy->gammaEnergy_MeV + e_in * energy->primaryGammaMassFactor;
510 break;
512 decaySamplingInfo->Ep = energy->gammaEnergy_MeV;
513 break;
515 randomEp = decaySamplingInfo->rng( decaySamplingInfo->rngState );
516 sampled.smr = smr;
517 sampled.w = e_in;
518 MCGIDI_sampling_sampleX_from_pdfsOfXGivenW( &(energy->dists), &sampled, randomEp );
519 decaySamplingInfo->Ep = sampled.x;
520 break;
522 sampled.interpolationXY = energy->gInterpolation;
523 MCGIDI_sampling_sampleX_from_pdfOfX( &(energy->g), &sampled, decaySamplingInfo->rng( decaySamplingInfo->rngState ) );
524 theta = MCGIDI_sampling_ptwXY_getValueAtX( energy->theta, e_in );
525 decaySamplingInfo->Ep = theta * sampled.x;
526 break;
528 theta = MCGIDI_sampling_ptwXY_getValueAtX( energy->theta, e_in );
529 MCGIDI_energy_sampleSimpleMaxwellianFission( smr, ( e_in - energy->U ) / theta, decaySamplingInfo );
530 decaySamplingInfo->Ep *= theta;
531 break;
533 theta = MCGIDI_sampling_ptwXY_getValueAtX( energy->theta, e_in );
534 MCGIDI_energy_sampleEvaporation( smr, ( e_in - energy->U ) / theta, decaySamplingInfo );
535 decaySamplingInfo->Ep *= theta;
536 break;
538 Watt_a = MCGIDI_sampling_ptwXY_getValueAtX( energy->Watt_a, e_in );
539 Watt_b = MCGIDI_sampling_ptwXY_getValueAtX( energy->Watt_b, e_in );
540 MCGIDI_energy_sampleWatt( smr, e_in - energy->U, Watt_a, Watt_b, decaySamplingInfo );
541 break;
543 MCGIDI_sampling_sampleX_from_pdfsOfXGivenW( &(energy->dists), &sampled, decaySamplingInfo->rng( decaySamplingInfo->rngState ) );
544 decaySamplingInfo->Ep = sampled.x;
545 break;
547 MCGIDI_sampling_sampleX_from_pdfOfX( &(energy->g), &sampled, decaySamplingInfo->rng( decaySamplingInfo->rngState ) );
548 decaySamplingInfo->Ep = ( energy->e_inCOMFactor * e_in + energy->NBodyPhaseSpace.Q_MeV ) * energy->NBodyPhaseSpace.massFactor * sampled.x;
549 break;
551 MCGIDI_energy_sampleWeightedFunctional( smr, energy, modes, decaySamplingInfo );
552 break;
553 default :
554 smr_setReportError2( smr, smr_unknownID, 1, "energy type = %d not supported", energy->type );
555 }
556
557 return( !smr_isOk( smr ) );
558}
559/*
560************************************************************
561*/
562static int MCGIDI_energy_sampleSimpleMaxwellianFission( statusMessageReporting * /*smr*/, double e_in_U_theta, MCGIDI_decaySamplingInfo *decaySamplingInfo ) {
563
564 int i1;
565 double a = e_in_U_theta, b, c, x, norm_a, xMin = 0., xMax = a, sqrt_x, sqrt_pi_2 = std::sqrt( M_PI ) / 2.;
566
567 sqrt_x = std::sqrt( a );
568 norm_a = sqrt_pi_2 * erf( sqrt_x ) - sqrt_x * G4Exp( -a );
569 b = norm_a * decaySamplingInfo->rng( decaySamplingInfo->rngState );
570 for( i1 = 0; i1 < 16; i1++ ) {
571 x = 0.5 * ( xMin + xMax );
572 sqrt_x = std::sqrt( x );
573 c = sqrt_pi_2 * erf( sqrt_x ) - sqrt_x * G4Exp( -x );
574 if( b < c ) {
575 xMax = x; }
576 else {
577 xMin = x;
578 }
579 }
580 /* To order e, the correct x is x + e where e = 1 + ( 1 - b * exp( x ) ) / x. */
581 decaySamplingInfo->Ep = x;
582
583 return( 0 );
584}
585/*
586************************************************************
587*/
588static int MCGIDI_energy_sampleEvaporation( statusMessageReporting * /*smr*/, double e_in_U_theta, MCGIDI_decaySamplingInfo *decaySamplingInfo ) {
589
590 int i1;
591 double a = e_in_U_theta, b, c, x, norm_a, xMin = 0., xMax = a;
592
593 norm_a = 1 - ( 1 + a ) * G4Exp( -a );
594 b = 1. - norm_a * decaySamplingInfo->rng( decaySamplingInfo->rngState );
595 for( i1 = 0; i1 < 16; i1++ ) {
596 x = 0.5 * ( xMin + xMax );
597 c = ( 1 + x ) * G4Exp( -x );
598 if( b > c ) {
599 xMax = x; }
600 else {
601 xMin = x;
602 }
603 }
604 /* To order e, the correct x is x + e where e = 1 + ( 1 - b * std::exp( x ) ) / x. */
605 decaySamplingInfo->Ep = x;
606
607 return( 0 );
608}
609/*
610************************************************************
611*/
612static int MCGIDI_energy_sampleWatt( statusMessageReporting * /*smr*/, double e_in_U, double Watt_a, double Watt_b, MCGIDI_decaySamplingInfo *decaySamplingInfo ) {
613/*
614* From MCAPM via Sample Watt Spectrum as in TART ( Kalos algorithm ).
615*/
616 double WattMin = 0., WattMax = e_in_U, x, y, z, energyOut = 0., rand1, rand2;
617
618 x = 1. + ( Watt_b / ( 8. * Watt_a ) );
619 y = ( x + std::sqrt( x * x - 1. ) ) / Watt_a;
620 z = Watt_a * y - 1.;
621 G4int icounter=0;
622 G4int icounter_max=1024;
623 do
624 {
625 icounter++;
626 if ( icounter > icounter_max ) {
627 G4cout << "Loop-counter exceeded the threshold value at " << __LINE__ << "th line of " << __FILE__ << "." << G4endl;
628 break;
629 }
630 rand1 = -G4Log( decaySamplingInfo->rng( decaySamplingInfo->rngState ) );
631 rand2 = -G4Log( decaySamplingInfo->rng( decaySamplingInfo->rngState ) );
632 energyOut = y * rand1;
633 }
634 while( ( ( rand2 - z * ( rand1 + 1. ) ) * ( rand2 - z * ( rand1 + 1. ) ) > Watt_b * y * rand1 ) || ( energyOut < WattMin ) || ( energyOut > WattMax ) ); // Loop checking, 11.06.2015, T. Koi
635 decaySamplingInfo->Ep = energyOut;
636
637 return( 0 );
638}
639/*
640************************************************************
641*/
642static int MCGIDI_energy_sampleWeightedFunctional( statusMessageReporting *smr, MCGIDI_energy *energy,
643 MCGIDI_quantitiesLookupModes &modes, MCGIDI_decaySamplingInfo *decaySamplingInfo ) {
644/*
645c This routine assumes that the weights sum to 1.
646*/
647 int iW;
648 double rW = decaySamplingInfo->rng( decaySamplingInfo->rngState ), cumulativeW = 0., weight;
649 MCGIDI_energyWeightedFunctional *weightedFunctional = NULL;
650
651 for( iW = 0; iW < energy->weightedFunctionals.numberOfWeights; iW++ ) {
652 weightedFunctional = &(energy->weightedFunctionals.weightedFunctional[iW]);
653 weight = MCGIDI_sampling_ptwXY_getValueAtX( weightedFunctional->weight, modes.getProjectileEnergy( ) );
654 cumulativeW += weight;
655 if( cumulativeW >= rW ) break;
656 }
657 return( MCGIDI_energy_sampleEnergy( smr, weightedFunctional->energy, modes, decaySamplingInfo ) );
658}
659
660#if defined __cplusplus
661}
662#endif
663
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double MCGIDI_sampling_ptwXY_getValueAtX(ptwXYPoints *ptwXY, double x1)
int MCGIDI_sampling_pdfsOfXGivenW_release(statusMessageReporting *smr, MCGIDI_pdfsOfXGivenW *dists)
MCGIDI_energy * MCGIDI_energy_free(statusMessageReporting *smr, MCGIDI_energy *energy)
int MCGIDI_energy_sampleEnergy(statusMessageReporting *smr, MCGIDI_energy *energy, MCGIDI_quantitiesLookupModes &modes, MCGIDI_decaySamplingInfo *decaySamplingInfo)
int MCGIDI_energy_initialize(statusMessageReporting *smr, MCGIDI_energy *energy)
int MCGIDI_sampling_pdfsOfX_release(statusMessageReporting *smr, MCGIDI_pdfOfX *dist)
double MCGIDI_outputChannel_getQ_MeV(statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel, double e_in)
MCGIDI_energy * MCGIDI_energy_new(statusMessageReporting *smr)
int MCGIDI_energy_parseFromTOM(statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_distribution *distribution, ptwXYPoints *norms, enum MCGIDI_energyType energyType, double gammaEnergy_MeV)
int MCGIDI_misc_PQUStringToDouble(statusMessageReporting *smr, char const *str, char const *unit, double conversion, double *value)
Definition: MCGIDI_misc.cc:330
int MCGIDI_sampling_sampleX_from_pdfOfX(MCGIDI_pdfOfX *dist, MCGIDI_pdfsOfXGivenW_sampled *sampled, double r)
double MCGIDI_product_getMass_MeV(statusMessageReporting *smr, MCGIDI_product *product)
int MCGIDI_sampling_sampleX_from_pdfsOfXGivenW(MCGIDI_pdfsOfXGivenW *dists, MCGIDI_pdfsOfXGivenW_sampled *sampled, double r)
#define MCGIDI_AMU2MeV
Definition: MCGIDI.h:184
int MCGIDI_misc_PQUStringToDoubleInUnitOf(statusMessageReporting *smr, char const *str, char const *toUnit, double *value)
Definition: MCGIDI_misc.cc:356
double MCGIDI_product_getTargetMass_MeV(statusMessageReporting *smr, MCGIDI_product *product)
double MCGIDI_product_getProjectileMass_MeV(statusMessageReporting *smr, MCGIDI_product *product)
int MCGIDI_energy_release(statusMessageReporting *smr, MCGIDI_energy *energy)
MCGIDI_energyType
Definition: MCGIDI.h:214
@ MCGIDI_energyType_NBodyPhaseSpace
Definition: MCGIDI.h:216
@ MCGIDI_energyType_primaryGamma
Definition: MCGIDI.h:214
@ MCGIDI_energyType_weightedFunctional
Definition: MCGIDI.h:216
@ MCGIDI_energyType_simpleMaxwellianFission
Definition: MCGIDI.h:215
@ MCGIDI_energyType_discreteGamma
Definition: MCGIDI.h:214
@ MCGIDI_energyType_generalEvaporation
Definition: MCGIDI.h:215
@ MCGIDI_energyType_MadlandNix
Definition: MCGIDI.h:216
@ MCGIDI_energyType_evaporation
Definition: MCGIDI.h:215
@ MCGIDI_energyType_Watt
Definition: MCGIDI.h:216
@ MCGIDI_energyType_linear
Definition: MCGIDI.h:215
int MCGIDI_fromTOM_pdfsOfXGivenW(statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_pdfsOfXGivenW *dists, ptwXYPoints *norms, char const *toUnits[3])
int MCGIDI_fromTOM_pdfOfX(statusMessageReporting *smr, ptwXYPoints *pdfXY, MCGIDI_pdfOfX *dist, double *norm)
ptwXYPoints * MCGIDI_misc_dataFromXYs2ptwXYPointsInUnitsOf(statusMessageReporting *smr, xDataTOM_XYs *XYs, ptwXY_interpolation interpolation, char const *units[2])
Definition: MCGIDI_misc.cc:405
ptwXYPoints * MCGIDI_misc_dataFromElement2ptwXYPointsInUnitsOf(statusMessageReporting *smr, xDataTOM_element *linear, char const *toUnits[2])
Definition: MCGIDI_misc.cc:424
enum xDataTOM_frame MCGIDI_misc_getProductFrame(statusMessageReporting *smr, xDataTOM_element *frameElement)
Definition: MCGIDI_misc.cc:315
#define M_PI
Definition: SbMath.h:33
static G4Pow * GetInstance()
Definition: G4Pow.cc:41
G4double powA(G4double A, G4double y) const
Definition: G4Pow.hh:230
double getProjectileEnergy(void) const
Definition: MCGIDI.h:97
G4double energy(const ThreeVector &p, const G4double m)
double nf_incompleteGammaFunctionComplementary(double a, double x, nfu_status *status)
double nf_incompleteGammaFunction(double a, double x, nfu_status *status)
double nf_exponentialIntegral(int n, double x, nfu_status *status)
@ nfu_Okay
Definition: nf_utilities.h:25
enum nfu_status_e nfu_status
const char * nfu_statusMessage(nfu_status status)
Definition: nf_utilities.cc:76
ptwXY_interpolation ptwXY_getInterpolation(ptwXYPoints *ptwXY)
Definition: ptwXY_core.cc:337
nfu_status ptwXY_simpleCoalescePoints(ptwXYPoints *ptwXY)
Definition: ptwXY_core.cc:529
ptwXYPoint * ptwXY_getPointAtIndex_Unsafely(ptwXYPoints *ptwXY, int64_t index)
Definition: ptwXY_core.cc:684
@ ptwXY_interpolationLinLin
Definition: ptwXY.h:35
int64_t ptwXY_length(ptwXYPoints *ptwXY)
Definition: ptwXY_core.cc:583
ptwXYPoints * ptwXY_createFromFunction(int n, double *xs, ptwXY_createFromFunction_callback func, void *argList, double accuracy, int checkForRoots, int biSectionMax, nfu_status *status)
Definition: ptwXY_misc.cc:40
ptwXPoints * ptwXY_runningIntegral(ptwXYPoints *ptwXY, nfu_status *status)
nfu_status ptwXY_normalize(ptwXYPoints *ptwXY1)
nfu_status ptwXY_getXYPairAtIndex(ptwXYPoints *ptwXY, int64_t index, double *x, double *y)
Definition: ptwXY_core.cc:698
ptwXYPoints * ptwXY_free(ptwXYPoints *ptwXY)
Definition: ptwXY_core.cc:574
nfu_status(* ptwXY_createFromFunction_callback)(double x, double *y, void *argList)
Definition: ptwXY.h:65
double ptwX_getPointAtIndex_Unsafely(ptwXPoints *ptwX, int64_t index)
Definition: ptwX_core.cc:215
ptwXPoints * ptwX_free(ptwXPoints *ptwX)
Definition: ptwX_core.cc:158
#define smr_setReportError2(smr, libraryID, code, fmt,...)
void * smr_freeMemory(void **p)
int smr_isOk(statusMessageReporting *smr)
#define smr_malloc2(smr, size, zero, forItem)
#define smr_unknownID
double(* rng)(void *)
Definition: MCGIDI.h:258
enum xDataTOM_frame frame
Definition: MCGIDI.h:256
MCGIDI_energy * energy
Definition: MCGIDI.h:384
MCGIDI_product * product
Definition: MCGIDI.h:381
double * Xs
Definition: MCGIDI.h:299
double * pdf
Definition: MCGIDI.h:300
int numberOfXs
Definition: MCGIDI.h:298
double * cdf
Definition: MCGIDI.h:301
ptwXY_interpolation interpolationXY
Definition: MCGIDI.h:306
MCGIDI_pdfOfX * dist
Definition: MCGIDI.h:308
ptwXY_interpolation interpolationWY
Definition: MCGIDI.h:306
ptwXY_interpolation interpolationXY
Definition: MCGIDI.h:313
statusMessageReporting * smr
Definition: MCGIDI.h:312
MCGIDI_outputChannel * outputChannel
Definition: MCGIDI.h:403
double y
Definition: ptwXY.h:62
double x
Definition: ptwXY.h:62
xDataTOM_element * xDataTOME_getOneElementByName(statusMessageReporting *smr, xDataTOM_element *element, char const *name, int required)
Definition: xDataTOM.cc:246
xDataTOM_element * xDataTOME_getNextElement(xDataTOM_element *element)
Definition: xDataTOM.cc:238
char const * xDataTOM_getAttributesValueInElement(xDataTOM_element *element, char const *name)
Definition: xDataTOM.cc:286
int xDataTOME_convertAttributeToInteger(statusMessageReporting *smr, xDataTOM_element *element, char const *name, int *n)
Definition: xDataTOM.cc:300
xDataTOM_element * xDataTOME_getFirstElement(xDataTOM_element *element)
Definition: xDataTOM.cc:230
@ xDataTOM_frame_invalid
Definition: xDataTOM.h:23
@ xDataTOM_frame_lab
Definition: xDataTOM.h:23
void * xDataTOME_getXDataIfID(statusMessageReporting *smr, xDataTOM_element *TE, char const *ID)
Definition: xDataTOM.cc:512