Geant4  10.03
PoPs.cc
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include "PoPs.h"
6 #include "PoPs_private.h"
7 
8 /*
9  In PoPs_addParticleIfNeeded and unitsDB_addUnitIfNeeded, smr_malloc2 and not smr_realloc2 is used so that the current database is not
10  lost if more memory cannot be allocated (not sure that this is needed, maybe should crash).
11 */
12 
13 #if defined __cplusplus
14 namespace GIDI {
15 using namespace GIDI;
16 #endif
17 
18 #define incrementalSize 1000
19 
20 #define MeV2eV 1e6
21 #define MeV2keV 1e3
22 #define AMU2MeV 931.494028
23 #define AMU2eV ( MeV2eV * 931.494028 )
24 #define K2MeV 8.6173856922566752e-11
25 #define K2eV ( MeV2eV * K2MeV )
26 
28 
30  char const *_from;
31  char const *_to;
32  double ratio;
33 };
34 
35 int PoPs_smr_ID = smr_unknownID;
36 static int referenceCount = 0;
37 static char versionStr[64] = "";
38 
39 /*
40 * For MPI the following need to be broadcasted.
41 */
42 static unitsDB unitsRoot = { 0, 0, NULL };
43 static PoPs popsRoot = { 0, 0, NULL, NULL };
44 /*
45 * End need to MPI broadcasted.
46 */
47 
48 static unitConversions conversions[] = { { "amu", "eV/c**2", AMU2eV }, { "amu", "MeV/c**2", AMU2MeV }, { "MeV/c**2", "eV/c**2", MeV2eV },
49  { "MeV", "eV", MeV2eV }, { "MeV", "keV", MeV2keV }, { "K", "MeV", K2MeV }, { "K", "eV", K2eV } };
50 
51 static char const *PoPs_genreStrings[] = { "invalid", "unknown", "alias", "photon", "lepton", "quark", "meson", "baryon", "nucleus", "atom" };
52 
53 static int PoPs_particleProperIndex( int index );
54 static int PoPs_sortedParticleIndex( char const *name );
55 static int unitsDB_release( void );
56 /*
57 ========================================================================
58 */
59 const char *PoPs_version( void ) {
60 
61  if( versionStr[0] == 0 ) sprintf( versionStr, "PoPs version %d.%d.%d", POPS_VERSION_MAJOR, POPS_VERSION_MINOR, POPS_VERSION_PATCHLEVEL );
62  return( versionStr );
63 }
64 /*
65 ========================================================================
66 */
67 int PoPs_versionMajor( void ) { return( POPS_VERSION_MAJOR ); }
68 int PoPs_versionMinor( void ) { return( POPS_VERSION_MINOR ); }
69 int PoPs_versionPatchLevel( void ) { return( POPS_VERSION_PATCHLEVEL ); }
70 /*
71 ========================================================================
72 */
73 int PoPs_register( void ) {
74 
75  if( referenceCount < 0 ) return( -1 );
76  return( ++referenceCount );
77 }
78 /*
79 ========================================================================
80 */
81 int PoPs_readDatabase( statusMessageReporting *smr, char const *fileName ) {
82 
83  return( PoPs_particleReadDatabase( smr, fileName ) );
84 }
85 /*
86 ========================================================================
87 */
88 int PoPs_release( statusMessageReporting *smr ) {
89 
90  referenceCount--;
91  if( referenceCount != 0 ) return( referenceCount );
92  PoPs_releasePrivate( smr );
93  return( 0 );
94 }
95 /*
96 ========================================================================
97 */
98 int PoPs_releasePrivate( statusMessageReporting * /*smr*/ ) {
99 
100  int i;
101 
102  for( i = 0; i < popsRoot.numberOfParticles; i++ ) PoP_free( popsRoot.pops[i] );
103  smr_freeMemory( (void **) &(popsRoot.pops) );
104  popsRoot.sorted = NULL;
105  popsRoot.numberOfParticles = 0;
106  popsRoot.allocated = 0;
107  unitsDB_release( );
108  return( 0 );
109 }
110 /*
111 ========================================================================
112 */
113 PoP *PoPs_addParticleIfNeeded( statusMessageReporting *smr, PoP *pop ) {
114 /*
115  If particle with name pop->name is already in popsRoot, returns the pointer to the existing particle.
116  A NULL is returned if adding particle to popsRoot fails.
117 */
118  int i, index = PoPs_sortedParticleIndex( pop->name );
119 
120  if( index >= 0 ) return( popsRoot.pops[PoPs_particleProperIndex( popsRoot.sorted[index]->index )] );
121  if( popsRoot.numberOfParticles == popsRoot.allocated ) {
122  int size = popsRoot.allocated + incrementalSize;
123  PoP **sorted, **pops = (PoP **) smr_malloc2( smr, 2 * size * sizeof( PoPs * ), 0, "pops" );
124 
125  if( pops == NULL ) return( NULL );
126  sorted = &(pops[size]);
127  for( i = 0; i < popsRoot.numberOfParticles; i++ ) {
128  pops[i] = popsRoot.pops[i];
129  sorted[i] = popsRoot.sorted[i];
130  }
131  smr_freeMemory( (void **) &(popsRoot.pops) );
132  popsRoot.pops = pops;
133  popsRoot.sorted = sorted;
134  popsRoot.allocated = size;
135  }
136  popsRoot.pops[popsRoot.numberOfParticles] = pop;
137  index = -index - 1;
138  for( i = popsRoot.numberOfParticles; i > index; i-- ) popsRoot.sorted[i] = popsRoot.sorted[i-1];
139  popsRoot.sorted[index] = pop;
140  pop->index = popsRoot.numberOfParticles;
141  popsRoot.numberOfParticles++;
142  if( pop->genre == PoPs_genre_alias ) { /* Add pop->index to end of list of particles aliased by pop->properIndex. */
143  PoP *pop2;
144 
145  for( pop2 = popsRoot.pops[pop->properIndex]; pop2->aliasIndex >= 0; pop2 = popsRoot.pops[pop2->aliasIndex] ) ;
146  pop2->aliasIndex = pop->index;
147  }
148  return( pop );
149 }
150 /*
151 ========================================================================
152 */
153 PoP *PoPs_copyAddParticleIfNeeded( statusMessageReporting *smr, PoP *pop ) {
154 /*
155  If particle with name pop->name is already in popsRoot, return the address of the existing particle.
156  If particle is not in popsRoot then copy particle to a new 'PoP *', add the copied PoP to popsRoot and return its address.
157  A NULL is return if particle coping fails or adding particle to popsRoot fails.
158 */
159 
160  int index = PoPs_particleIndex( pop->name );
161  PoP *newPoP;
162 
163  if( index >= 0 ) return( popsRoot.pops[index] );
164 
165  if( ( newPoP = (PoP *) smr_malloc2( smr, sizeof( PoP ), 0, "newPoP" ) ) == NULL ) return( NULL );
166  if( PoP_copyParticle( smr, newPoP, pop ) ) {
167  smr_freeMemory( (void **) &newPoP );
168  return( NULL );
169  }
170  if( PoPs_addParticleIfNeeded( smr, newPoP ) == NULL ) {
171  PoP_free( newPoP );
172  return( NULL );
173  }
174  return( newPoP );
175 }
176 /*
177 ========================================================================
178 */
179 PoP *PoPs_addAliasIfNeeded( statusMessageReporting *smr, char const *name, char const *alias ) {
180 
181  PoP *pop = PoP_makeAlias( smr, name, alias );
182 
183  if( pop != NULL ) {
184  if( pop->index < 0 ) {
185  if( PoPs_addParticleIfNeeded( smr, pop ) == NULL ) {
186  PoP_free( pop );
187  return( NULL );
188  }
189  }
190  }
191 
192  return( pop );
193 }
194 /*
195 ========================================================================
196 */
198 
199  return( popsRoot.numberOfParticles );
200 }
201 /*
202 ========================================================================
203 */
204 int PoPs_particleIndex( char const *name ) {
205 /*
206  A negative number is return if particle is not in popsRoot. Else, the Id of the real (not aliased) particle is returned.
207 */
208  int index = PoPs_sortedParticleIndex( name );
209 
210  if( index >= 0 ) index = PoPs_particleProperIndex( popsRoot.sorted[index]->index );
211  return( index );
212 }
213 /*
214 ========================================================================
215 */
216 int PoPs_particleIndex_smr( statusMessageReporting *smr, char const *name, char const *file, int line, char const *func ) {
217 
218  int index = PoPs_particleIndex( name );
219 
220  if( index < 0 )
221  smr_setReportError( smr, NULL, file, line, func, PoPs_smr_ID, PoPs_errorToken_badName, "particle '%s' not in PoPs", name );
222  return( index );
223 }
224 /*
225 ========================================================================
226 */
227 static int PoPs_particleProperIndex( int index ) {
228 
229  while( popsRoot.pops[index]->properIndex >= 0 ) index = popsRoot.pops[index]->properIndex; /* For alias particles. */ // Loop checking, 11.05.2015, T. Koi
230  return( index );
231 }
232 /*
233 ========================================================================
234 */
235 static int PoPs_sortedParticleIndex( char const *name ) {
236 /*
237  If name is a particle in popsRoot, its index in the sorted list is returned; otherwise,
238  a negative number is returned. For a particle not found, its index would be -returnValue + 1 if added;
239 */
240  int low = 0, mid, high = popsRoot.numberOfParticles, iCmp;
241 
242  if( high == 0 ) return( -1 );
243  while( ( high - low ) > 1 ) {
244  mid = ( low + high ) >> 1;
245  iCmp = strcmp( name, popsRoot.sorted[mid]->name );
246  if( iCmp == 0 ) return( mid );
247  if( iCmp > 0 ) {
248  low = mid; }
249  else {
250  high = mid;
251  }
252  } // Loop checking, 11.05.2015, T. Koi
253  if( high == 1 ) { /* First point is not checked as loop exits when ( high = 1 ) - ( low = 0 ) <= 1 ). */
254  if( !strcmp( name, popsRoot.sorted[0]->name ) ) return( 0 ); /* First name is a match. */
255  if( strcmp( name, popsRoot.sorted[0]->name ) < 0 ) return( -1 ); /* name is less than first name. */
256  }
257  if( high < popsRoot.numberOfParticles ) {
258  if( strcmp( name, popsRoot.sorted[high]->name ) == 0 ) return( high );
259  }
260  return( -high - 1 );
261 }
262 /*
263 ========================================================================
264 */
265 double PoPs_getMassInUnitOf( statusMessageReporting *smr, char const *name, char const *unit ) {
266 
267  int index = PoPs_particleIndex_smr( smr, name, __FILE__, __LINE__, __func__ );
268 
269  if( index < 0 ) return( -1. );
270  return( PoPs_getMassInUnitOf_atIndex( smr, index, unit ) );
271 }
272 /*
273 ========================================================================
274 */
275 char const *PoPs_getName_atIndex( statusMessageReporting *smr, int index ) {
276 
277  if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
278  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex, "index %d not in PoPs", index );
279  return( NULL );
280  }
281  return( popsRoot.pops[index]->name );
282 }
283 /*
284 ========================================================================
285 */
286 double PoPs_getMassInUnitOf_atIndex( statusMessageReporting *smr, int index, char const *unit ) {
287 
288  double mass = -1.;
289 
290  if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
291  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex, "index %d not in PoPs", index ); }
292  else {
293  mass = PoP_getMassInUnitOf( smr, popsRoot.pops[index], unit );
294  }
295 
296  return( mass );
297 }
298 /*
299 ========================================================================
300 */
301 enum PoPs_genre PoPs_getGenre( statusMessageReporting *smr, char const *name ) {
302 
303  int index = PoPs_particleIndex_smr( smr, name, __FILE__, __LINE__, __func__ );
304 
305  if( index < 0 ) return( PoPs_genre_invalid );
306  return( popsRoot.pops[index]->genre );
307 }
308 /*
309 ========================================================================
310 */
311 enum PoPs_genre PoPs_getGenre_atIndex( statusMessageReporting *smr, int index ) {
312 
313  enum PoPs_genre genre = PoPs_genre_invalid;
314 
315  if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
316  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex, "index %d not in PoPs", index ); }
317  else {
318  genre = popsRoot.pops[index]->genre;
319  }
320  return( genre );
321 }
322 /*
323 ========================================================================
324 */
325 int PoPs_getZ_A_l( statusMessageReporting *smr, char const *name, int *Z, int *A, int *l ) {
326 
327  int index = PoPs_particleIndex_smr( smr, name, __FILE__, __LINE__, __func__ );
328 
329  if( index < 0 ) return( -1 );
330  return( PoPs_getZ_A_l_atIndex( smr, index, Z, A, l ) );
331 }
332 /*
333 ========================================================================
334 */
335 int PoPs_getZ_A_l_atIndex( statusMessageReporting *smr, int index, int *Z, int *A, int *l ) {
336 
337  if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
338  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex, "index %d not in PoPs", index );
339  return( -1 );
340  }
341  *Z = popsRoot.pops[index]->Z;
342  *A = popsRoot.pops[index]->A;
343  *l = 0;
344  return( 0 );
345 }
346 /*
347 ========================================================================
348 */
349 int PoPs_hasNucleus( statusMessageReporting *smr, char const *name, int protonIsNucleus ) {
350 
351  int index = PoPs_particleIndex_smr( smr, name, __FILE__, __LINE__, __func__ );
352 
353  if( index < 0 ) return( -1 );
354  return( PoPs_hasNucleus_atIndex( smr, index, protonIsNucleus ) );
355 }
356 /*
357 ========================================================================
358 */
359 int PoPs_hasNucleus_atIndex( statusMessageReporting *smr, int index, int protonIsNucleus ) {
360 /*
361 * If an error is encountered, a negative value is returned. A value greater than 0 means the particle
362 * contains a nucleus (is an atom, ion or nucleus). Otherwise, a 0 is returned.
363 */
364  if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
365  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex, "index %d not in PoPs", index );
366  return( -1 );
367  }
368  if( ( popsRoot.pops[index]->genre == PoPs_genre_nucleus ) || ( popsRoot.pops[index]->genre == PoPs_genre_atom ) ) return( 1 );
369  if( protonIsNucleus ) {
370  if( strcmp( "p", popsRoot.pops[index]->name ) == 0 ) return( 1 );
371  }
372  return( 0 );
373 }
374 /*
375 ========================================================================
376 */
377 char const *PoPs_getAtomsName( statusMessageReporting *smr, char const *name ) {
378 
379  int index = PoPs_particleIndex_smr( smr, name, __FILE__, __LINE__, __func__ );
380 
381  if( index < 0 ) return( NULL );
382  return( PoPs_getAtomsName_atIndex( smr, index ) );
383 }
384 /*
385 ========================================================================
386 */
387 char const *PoPs_getAtomsName_atIndex( statusMessageReporting *smr, int index ) {
388 
389  int atomIndex = PoPs_getAtomsIndex_atIndex( smr, index );
390 
391  if( atomIndex < 0 ) return( NULL );
392  return( popsRoot.pops[atomIndex]->name );
393 }
394 /*
395 ========================================================================
396 */
397 int PoPs_getAtomsIndex( statusMessageReporting *smr, char const *name ) {
398 
399  int index = PoPs_particleIndex_smr( smr, name, __FILE__, __LINE__, __func__ );
400 
401  if( index < 0 ) return( index );
402  return( PoPs_getAtomsIndex_atIndex( smr, index ) );
403 }
404 /*
405 ========================================================================
406 */
407 int PoPs_getAtomsIndex_atIndex( statusMessageReporting *smr, int index ) {
408 
409  char const *p = NULL;
410 
411  if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
412  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex, "index %d not in PoPs", index );
413  return( -1 );
414  }
415 
416  if( popsRoot.pops[index]->genre == PoPs_genre_atom ) return( index );
417 
418  if( strcmp( "p", popsRoot.pops[index]->name ) == 0 ) {
419  p = "H1"; }
420  else {
421  if( popsRoot.pops[index]->genre != PoPs_genre_nucleus ) return( -1 );
422  else if( strcmp( "h2", popsRoot.pops[index]->name ) == 0 ) {
423  p = "H2"; }
424  else if( strcmp( "h3", popsRoot.pops[index]->name ) == 0 ) {
425  p = "H3"; }
426  else if( strcmp( "he3", popsRoot.pops[index]->name ) == 0 ) {
427  p = "He3"; }
428  else if( strcmp( "he4", popsRoot.pops[index]->name ) == 0 ) {
429  p = "He4";
430  }
431  }
432  if( p != NULL ) return( PoPs_particleIndex_smr( smr, p, __FILE__, __LINE__, __func__ ) );
433  return( -1 );
434 }
435 /*
436 ========================================================================
437 */
438 PoP *PoPs_getParticle_atIndex( int index ) {
439 
440  if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) return( NULL );
441  return( popsRoot.pops[index] );
442 }
443 /*
444 ========================================================================
445 */
446 char const *PoPs_genreTokenToString( enum PoPs_genre genre ) {
447 
448  if( genre < PoPs_genre_invalid ) return( NULL );
449  if( genre > PoPs_genre_atom ) return( NULL );
450  return( PoPs_genreStrings[genre] );
451 }
452 /*
453 ========================================================================
454 */
455 void PoPs_print( int sorted ) {
456 
457  PoPs_write( stdout, sorted );
458 }
459 /*
460 ========================================================================
461 */
462 void PoPs_write( FILE *f, int sorted ) {
463 
464  int i1, properIndex;
465  PoP *pop;
466 
467  fprintf( f, "Mass units: number of units = %d\n", unitsRoot.numberOfUnits );
468  for( i1 = 0; i1 < unitsRoot.numberOfUnits; i1++ ) {
469  fprintf( f, " %s", unitsRoot.unsorted[i1] );
470  }
471  fprintf( f, "\n\n" );
472  fprintf( f, "Particles: number of particles = %d\n", popsRoot.numberOfParticles );
473  fprintf( f, " name index genre mass hasNucleus alias info\n" );
474  fprintf( f, " Z A l\n" );
475  fprintf( f, " --------------------------------------------------------------------------------------------\n" );
476  for( i1 = 0; i1 < popsRoot.numberOfParticles; i1++ ) {
477  if( sorted ) {
478  pop = popsRoot.sorted[i1]; }
479  else {
480  pop = popsRoot.pops[i1];
481  }
482  properIndex = PoPs_particleProperIndex( pop->index );
483  fprintf( f, " %-24s %6d %-10s %15.8e %-6s", pop->name, pop->index, PoPs_genreTokenToString( pop->genre ),
484  popsRoot.pops[properIndex]->mass, popsRoot.pops[properIndex]->massUnit );
485  if( PoPs_hasNucleus( NULL, pop->name, 0 ) ) {
486  fprintf( f, " T" ); }
487  else {
488  fprintf( f, " " );
489  }
490  if( PoPs_hasNucleus( NULL, pop->name, 1 ) ) {
491  fprintf( f, " T" ); }
492  else {
493  fprintf( f, " " );
494  }
495  if( pop->Z + pop->A > 0 ) {
496  fprintf( f, " %3d %3d", pop->Z, pop->A );
497  if( pop->l > 0 ) {
498  fprintf( f, " %d", pop->l ); }
499  else {
500  fprintf( f, " " );
501  } }
502  else {
503  fprintf( f, " " );
504  }
505  if( pop->genre == PoPs_genre_alias ) {
506  fprintf( f, " %s (%d)", popsRoot.pops[properIndex]->name, popsRoot.pops[properIndex]->index ); }
507  else {
508  int aliasIndex;
509 
510  for( aliasIndex = pop->aliasIndex; aliasIndex >= 0; aliasIndex = popsRoot.pops[aliasIndex]->aliasIndex ) fprintf( f, " %d", aliasIndex );
511  }
512  fprintf( f, "\n" );
513  }
514 }
515 
516 /*
517 ========================== PoP functions ==========================
518 */
519 /*
520 ========================================================================
521 */
522 PoP *PoP_new( statusMessageReporting *smr ) {
523 
524  PoP *pop;
525 
526  if( ( pop = (PoP *) smr_malloc2( smr, sizeof( PoP ), 0, "pop" ) ) == NULL ) return( NULL );
527  if( PoP_initialize( smr, pop ) != 0 ) pop = PoP_free( pop );
528  return( pop );
529 }
530 /*
531 ========================================================================
532 */
533 int PoP_initialize( statusMessageReporting * /*smr*/, PoP *pop ) {
534 
535  pop->index = -1;
536  pop->properIndex = -1;
537  pop->aliasIndex = -1;
538  pop->genre = PoPs_genre_unknown;
539  pop->name = NULL;
540  pop->Z = 0;
541  pop->A = 0;
542  pop->mass = 0.0;
543  pop->massUnit = NULL;
544  return( 0 );
545 }
546 /*
547 ========================================================================
548 */
549 int PoP_release( PoP *pop ) {
550 
551  if( pop->name != NULL ) smr_freeMemory( (void **) &(pop->name ) );
552  PoP_initialize( NULL, pop ); /* Make it clean in case someone trys to use if. */
553  return( 0 );
554 }
555 /*
556 ========================================================================
557 */
558 PoP *PoP_free( PoP *pop ) {
559 
560  PoP_release( pop );
561  smr_freeMemory( (void **) &pop );
562  return( NULL );
563 }
564 /*
565 ========================================================================
566 */
567 int PoP_copyParticle( statusMessageReporting *smr, PoP *desc, PoP *src ) {
568 
569  desc->index = -1;
570  desc->properIndex = src->properIndex;
571  desc->aliasIndex = src->aliasIndex;
572  desc->genre = src->genre;
573  if( ( desc->name = smr_allocateCopyString2( smr, src->name, "desc->name" ) ) == NULL ) return( 1 );
574  desc->Z = src->Z;
575  desc->A = src->A;
576  desc->l = src->l;
577  desc->mass = src->mass;
578  desc->massUnit = src->massUnit;
579 
580  return( 0 );
581 }
582 /*
583 ========================================================================
584 */
585 PoP *PoP_makeParticle( statusMessageReporting *smr, enum PoPs_genre genre, char const *name, double mass, char const *massUnit ) {
586 
587  PoP *pop;
588 
589  if( ( pop = PoP_new( smr ) ) == NULL ) return( NULL );
590  if( ( pop->name = smr_allocateCopyString2( smr, name, "name" ) ) == NULL ) {
591  PoP_free( pop );
592  return( NULL );
593  }
594  pop->genre = genre;
595  pop->mass = mass;
596  if( ( pop->massUnit = unitsDB_addUnitIfNeeded( smr, massUnit ) ) == NULL ) pop = PoP_free( pop );
597  return( pop );
598 }
599 /*
600 ========================================================================
601 */
602 int PoP_setZ_A_l( statusMessageReporting * /*smr*/, PoP *pop, int Z, int A, int l ) {
603 
604  pop->Z = Z;
605  pop->A = A;
606  pop->l = l;
607  return( 0 );
608 }
609 /*
610 ========================================================================
611 */
612 int PoP_getIndex( PoP *pop ) {
613 
614  return( pop->index );
615 }
616 /*
617 ========================================================================
618 */
619 char const *PoP_getName( PoP *pop ) {
620 
621  return( pop->name );
622 }
623 /*
624 ========================================================================
625 */
626 double PoP_getMassInUnitOf( statusMessageReporting *smr, PoP *pop, char const *unit ) {
627 
628  double mass = -1., ratio;
629  /* PoP *pop_ = pop;*/
630 
631  /*if( pop->genre == PoPs_genre_alias ) pop_ = popsRoot.pops[PoPs_particleProperIndex( pop->index )];*/
632  if( PoPs_unitConversionRatio( pop->massUnit, unit, &ratio ) != 0 ) {
633  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badUnitConversion, "could not convert unit '%s' to '%s'", pop->massUnit, unit ); }
634  else {
635  mass = pop->mass * ratio;
636  }
637 
638  return( mass );
639 }
640 
641 /*
642 ========================== alias functions ==========================
643 */
644 /*
645 ========================================================================
646 */
647 PoP *PoP_makeAlias( statusMessageReporting *smr, char const *name, char const *alias ) {
648 
649  int properIndex = PoPs_particleIndex( name ), aliasIndex = PoPs_particleIndex( alias );
650  PoP *pop;
651 
652  if( properIndex < 0 ) {
653  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badName, "proper particle '%s' not in PoPs for alias '%s'", name, alias );
654  return( NULL );
655  }
656  if( aliasIndex >= 0 ) { /* alias has already been defined. */
657  PoP *truePop = popsRoot.pops[aliasIndex];
658 
659  for( pop = truePop; strcmp( alias, pop->name ); pop = popsRoot.pops[aliasIndex] ) aliasIndex = pop->aliasIndex;
660  if( pop->genre != PoPs_genre_alias ) {
661  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badName, "particle '%s' already in PoPs and not an alias", alias );
662  return( NULL );
663  }
664  if( pop->properIndex != properIndex ) {
665  smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badName, "particle '%s' already an alias for '%s', cannot re-alias to '%s'",
666  alias, truePop->name, name );
667  return( NULL );
668  } }
669  else {
670  if( ( pop = PoP_new( smr ) ) == NULL ) return( NULL );
671  if( ( pop->name = smr_allocateCopyString2( smr, alias, "name" ) ) == NULL ) {
672  PoP_free( pop );
673  return( NULL );
674  }
675  pop->properIndex = properIndex;
676  pop->genre = PoPs_genre_alias;
677  }
678  return( pop );
679 }
680 
681 /*
682 ========================== unitsDB functions =========================
683 */
684 /*
685 ========================================================================
686 */
687 static int unitsDB_release( void ) {
688 
689  int i;
690 
691  for( i = 0; i < unitsRoot.numberOfUnits; i++ ) smr_freeMemory( (void **) &(unitsRoot.unsorted[i]) );
692  smr_freeMemory( (void **) &(unitsRoot.unsorted) );
693  unitsRoot.numberOfUnits = 0;
694  unitsRoot.allocated = 0;
695  return( 0 );
696 }
697 /*
698 ========================================================================
699 */
700 char const *unitsDB_addUnitIfNeeded( statusMessageReporting *smr, char const *unit ) {
701 
702  int i;
703 
704  for( i = 0; i < unitsRoot.numberOfUnits; i++ ) {
705  if( strcmp( unit, unitsRoot.unsorted[i] ) == 0 ) return( unitsRoot.unsorted[i] );
706  }
707  if( unitsRoot.numberOfUnits == unitsRoot.allocated ) {
708  int size = unitsRoot.allocated + 20;
709  char const **unsorted = (char const **) smr_malloc2( smr, size * sizeof( char * ), 0, "unsorted" );
710 
711  if( unsorted == NULL ) return( NULL );
712  for( i = 0; i < unitsRoot.numberOfUnits; i++ ) unsorted[i] = unitsRoot.unsorted[i];
713  smr_freeMemory( (void **) &(unitsRoot.unsorted) );
714  unitsRoot.unsorted = unsorted;
715  unitsRoot.allocated = size;
716  }
717  if( ( unitsRoot.unsorted[unitsRoot.numberOfUnits] = smr_allocateCopyString2( smr, unit, "unitsRoot.unsorted[unitsRoot.numberOfUnits]" ) ) == NULL )
718  return( NULL );
719  unitsRoot.numberOfUnits++;
720  return( unitsRoot.unsorted[unitsRoot.numberOfUnits - 1] );
721 }
722 /*
723 ========================================================================
724 */
725 int unitsDB_index( statusMessageReporting * /*smr*/, char const *unit ) {
726 
727  int i;
728 
729  for( i = 0; i < unitsRoot.numberOfUnits; i++ ) {
730  if( !strcmp( unit, unitsRoot.unsorted[i] ) ) return( i );
731  }
732  return( -1 );
733 }
734 /*
735 ========================================================================
736 */
737 char const *unitsDB_stringFromIndex( statusMessageReporting *smr, int index ) {
738 
739  if( ( index < 0 ) || ( index >= unitsRoot.numberOfUnits ) ) {
740  smr_setReportError2( smr, PoPs_smr_ID, 1, "index = %d out of baounds [0 to %d)", index, unitsRoot.numberOfUnits );
741  return( NULL );
742  }
743  return( unitsRoot.unsorted[index] );
744 }
745 /*
746 ========================================================================
747 */
748 int PoPs_unitConversionRatio( char const *_from, char const *_to, double *ratio ) {
749 
750  int i, n = sizeof( conversions ) / sizeof( conversions[0] );
751 
752  *ratio = 1.;
753  if( strcmp( _from, _to ) == 0 ) return( 0 );
754  for( i = 0; i < n; i++ ) {
755  if( strcmp( conversions[i]._from, _from ) == 0 ) {
756  if( strcmp( conversions[i]._to, _to ) == 0 ) {
757  *ratio = conversions[i].ratio;
758  return( 0 );
759  } }
760  else if( strcmp( conversions[i]._to, _from ) == 0 ) {
761  if( strcmp( conversions[i]._from, _to ) == 0 ) {
762  *ratio = 1. / conversions[i].ratio;
763  return( 0 );
764  }
765  }
766  }
767  return( 1 );
768 }
769 #ifdef PoPs_MPI
770 #include "PoPs_Bcast_private.h"
771 /*
772 ========================================================================
773 */
774 int PoPs_Bcast( statusMessageReporting *smr, MPI_Comm comm, int rank ) {
775 
776  return( PoPs_Bcast2( smr, comm, rank, &unitsRoot, &popsRoot ) );
777 }
778 #endif
779 
780 #if defined __cplusplus
781 }
782 #endif
PoP * PoP_free(PoP *pop)
Definition: PoPs.cc:558
int PoPs_unitConversionRatio(char const *_from, char const *_to, double *ratio)
Definition: PoPs.cc:748
double ratio
Definition: PoPs.cc:32
PoP * PoPs_addAliasIfNeeded(statusMessageReporting *smr, char const *name, char const *alias)
Definition: PoPs.cc:179
static int referenceCount
Definition: PoPs.cc:36
char const * PoPs_genreTokenToString(enum PoPs_genre genre)
Definition: PoPs.cc:446
int PoPs_readDatabase(statusMessageReporting *smr, char const *fileName)
Definition: PoPs.cc:81
int PoPs_versionMinor(void)
Definition: PoPs.cc:68
int PoPs_particleIndex(char const *name)
Definition: PoPs.cc:204
static char versionStr[64]
Definition: PoPs.cc:37
char const * _to
Definition: PoPs.cc:31
int PoP_copyParticle(statusMessageReporting *smr, PoP *desc, PoP *src)
Definition: PoPs.cc:567
static int PoPs_particleProperIndex(int index)
Definition: PoPs.cc:227
enum PoPs_genre PoPs_getGenre(statusMessageReporting *smr, char const *name)
Definition: PoPs.cc:301
int PoPs_numberOfParticle(void)
Definition: PoPs.cc:197
static int unitsDB_release(void)
Definition: PoPs.cc:687
const char * name(G4int ptype)
int PoPs_getAtomsIndex(statusMessageReporting *smr, char const *name)
Definition: PoPs.cc:397
#define AMU2MeV
Definition: PoPs.cc:22
static int PoPs_sortedParticleIndex(char const *name)
Definition: PoPs.cc:235
#define MeV2keV
Definition: PoPs.cc:21
static unitConversions conversions[]
Definition: PoPs.cc:48
char const * _from
Definition: PoPs.cc:30
enum PoPs_genre PoPs_getGenre_atIndex(statusMessageReporting *smr, int index)
Definition: PoPs.cc:311
int PoPs_particleReadDatabase(statusMessageReporting *smr, char const *)
Definition: PoPs_data.cc:36
int PoPs_hasNucleus(statusMessageReporting *smr, char const *name, int protonIsNucleus)
Definition: PoPs.cc:349
#define incrementalSize
Definition: PoPs.cc:18
int PoPs_getAtomsIndex_atIndex(statusMessageReporting *smr, int index)
Definition: PoPs.cc:407
double PoPs_getMassInUnitOf(statusMessageReporting *smr, char const *name, char const *unit)
Definition: PoPs.cc:265
int PoPs_particleIndex_smr(statusMessageReporting *smr, char const *name, char const *file, int line, char const *func)
Definition: PoPs.cc:216
int unitsDB_index(statusMessageReporting *, char const *unit)
Definition: PoPs.cc:725
double A(double temperature)
char const * unitsDB_addUnitIfNeeded(statusMessageReporting *smr, char const *unit)
Definition: PoPs.cc:700
int smr_setReportError(statusMessageReporting *smr, void *userInterface, char const *file, int line, char const *function, int libraryID, int code, char const *fmt,...)
static char const * PoPs_genreStrings[]
Definition: PoPs.cc:51
int PoPs_register(void)
Definition: PoPs.cc:73
const char * PoPs_version(void)
Definition: PoPs.cc:59
int PoPs_getZ_A_l(statusMessageReporting *smr, char const *name, int *Z, int *A, int *l)
Definition: PoPs.cc:325
int PoP_setZ_A_l(statusMessageReporting *, PoP *pop, int Z, int A, int l)
Definition: PoPs.cc:602
int PoPs_releasePrivate(statusMessageReporting *)
Definition: PoPs.cc:98
#define MeV2eV
Definition: PoPs.cc:20
PoP * PoP_makeAlias(statusMessageReporting *smr, char const *name, char const *alias)
Definition: PoPs.cc:647
void * smr_freeMemory(void **p)
const G4int n
char const * PoPs_getName_atIndex(statusMessageReporting *smr, int index)
Definition: PoPs.cc:275
#define AMU2eV
Definition: PoPs.cc:23
char const * PoP_getName(PoP *pop)
Definition: PoPs.cc:619
#define K2eV
Definition: PoPs.cc:25
PoP * PoP_makeParticle(statusMessageReporting *smr, enum PoPs_genre genre, char const *name, double mass, char const *massUnit)
Definition: PoPs.cc:585
double PoPs_getMassInUnitOf_atIndex(statusMessageReporting *smr, int index, char const *unit)
Definition: PoPs.cc:286
PoP * PoP_new(statusMessageReporting *smr)
Definition: PoPs.cc:522
#define K2MeV
Definition: PoPs.cc:24
char const * unitsDB_stringFromIndex(statusMessageReporting *smr, int index)
Definition: PoPs.cc:737
int PoPs_hasNucleus_atIndex(statusMessageReporting *smr, int index, int protonIsNucleus)
Definition: PoPs.cc:359
int PoPs_versionMajor(void)
Definition: PoPs.cc:67
int PoPs_getZ_A_l_atIndex(statusMessageReporting *smr, int index, int *Z, int *A, int *l)
Definition: PoPs.cc:335
static unitsDB unitsRoot
Definition: PoPs.cc:42
PoP * PoPs_addParticleIfNeeded(statusMessageReporting *smr, PoP *pop)
Definition: PoPs.cc:113
PoP * PoPs_copyAddParticleIfNeeded(statusMessageReporting *smr, PoP *pop)
Definition: PoPs.cc:153
int PoPs_release(statusMessageReporting *smr)
Definition: PoPs.cc:88
int PoPs_smr_ID
Definition: PoPs.cc:35
double PoP_getMassInUnitOf(statusMessageReporting *smr, PoP *pop, char const *unit)
Definition: PoPs.cc:626
int PoPs_versionPatchLevel(void)
Definition: PoPs.cc:69
PoP * PoPs_getParticle_atIndex(int index)
Definition: PoPs.cc:438
int PoP_release(PoP *pop)
Definition: PoPs.cc:549
int PoP_getIndex(PoP *pop)
Definition: PoPs.cc:612
char const * PoPs_getAtomsName_atIndex(statusMessageReporting *smr, int index)
Definition: PoPs.cc:387
int PoP_initialize(statusMessageReporting *, PoP *pop)
Definition: PoPs.cc:533
char const * PoPs_getAtomsName(statusMessageReporting *smr, char const *name)
Definition: PoPs.cc:377
void PoPs_print(int sorted)
Definition: PoPs.cc:455
void PoPs_write(FILE *f, int sorted)
Definition: PoPs.cc:462
static PoPs popsRoot
Definition: PoPs.cc:43