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