Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
14namespace GIDI {
15using 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
36static int referenceCount = 0;
37static char versionStr[64] = "";
38
39/*
40* For MPI the following need to be broadcasted.
41*/
42static unitsDB unitsRoot = { 0, 0, NULL };
43static PoPs popsRoot = { 0, 0, NULL, NULL };
44/*
45* End need to MPI broadcasted.
46*/
47
48static 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
51static char const *PoPs_genreStrings[] = { "invalid", "unknown", "alias", "photon", "lepton", "quark", "meson", "baryon", "nucleus", "atom" };
52
53static int PoPs_particleProperIndex( int index );
54static int PoPs_sortedParticleIndex( char const *name );
55static int unitsDB_release( void );
56/*
57========================================================================
58*/
59const char *PoPs_version( void ) {
60
61 if( versionStr[0] == 0 ) snprintf( versionStr, sizeof versionStr, "PoPs version %d.%d.%d", POPS_VERSION_MAJOR, POPS_VERSION_MINOR, POPS_VERSION_PATCHLEVEL );
62 return( versionStr );
63}
64/*
65========================================================================
66*/
67int PoPs_versionMajor( void ) { return( POPS_VERSION_MAJOR ); }
68int PoPs_versionMinor( void ) { return( POPS_VERSION_MINOR ); }
70/*
71========================================================================
72*/
73int PoPs_register( void ) {
74
75 if( referenceCount < 0 ) return( -1 );
76 return( ++referenceCount );
77}
78/*
79========================================================================
80*/
81int PoPs_readDatabase( statusMessageReporting *smr, char const *fileName ) {
82
83 return( PoPs_particleReadDatabase( smr, fileName ) );
84}
85/*
86========================================================================
87*/
89
90 referenceCount--;
91 if( referenceCount != 0 ) return( referenceCount );
93 return( 0 );
94}
95/*
96========================================================================
97*/
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*/
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*/
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*/
179PoP *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*/
204int 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*/
216int 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*/
227static 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*/
235static 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*/
265double 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*/
275char 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*/
286double 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*/
301enum 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*/
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*/
325int 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*/
335int 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*/
349int 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*/
359int 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*/
377char 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*/
387char 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*/
397int 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*/
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*/
439
440 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) return( NULL );
441 return( popsRoot.pops[index] );
442}
443/*
444========================================================================
445*/
446char 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*/
455void PoPs_print( int sorted ) {
456
457 PoPs_write( stdout, sorted );
458}
459/*
460========================================================================
461*/
462void 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*/
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*/
534
535 pop->index = -1;
536 pop->properIndex = -1;
537 pop->aliasIndex = -1;
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*/
549int 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*/
558PoP *PoP_free( PoP *pop ) {
559
560 PoP_release( pop );
561 smr_freeMemory( (void **) &pop );
562 return( NULL );
563}
564/*
565========================================================================
566*/
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*/
585PoP *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*/
602int 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*/
612int PoP_getIndex( PoP *pop ) {
613
614 return( pop->index );
615}
616/*
617========================================================================
618*/
619char const *PoP_getName( PoP *pop ) {
620
621 return( pop->name );
622}
623/*
624========================================================================
625*/
626double 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*/
647PoP *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*/
687static 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*/
700char 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*/
725int 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*/
737char 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*/
748int 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*/
774int 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
const G4double A[17]
#define incrementalSize
Definition PoPs.cc:18
#define AMU2eV
Definition PoPs.cc:23
#define K2MeV
Definition PoPs.cc:24
#define AMU2MeV
Definition PoPs.cc:22
#define MeV2keV
Definition PoPs.cc:21
#define K2eV
Definition PoPs.cc:25
#define MeV2eV
Definition PoPs.cc:20
#define POPS_VERSION_MAJOR
Definition PoPs.h:27
char const * PoPs_getAtomsName_atIndex(statusMessageReporting *smr, int index)
Definition PoPs.cc:387
int PoPs_particleIndex_smr(statusMessageReporting *smr, char const *name, char const *file, int line, char const *func)
Definition PoPs.cc:216
void PoPs_write(FILE *f, int sorted)
Definition PoPs.cc:462
PoP * PoP_new(statusMessageReporting *smr)
Definition PoPs.cc:522
int PoPs_getAtomsIndex_atIndex(statusMessageReporting *smr, int index)
Definition PoPs.cc:407
int PoPs_getZ_A_l(statusMessageReporting *smr, char const *name, int *Z, int *A, int *l)
Definition PoPs.cc:325
@ PoPs_errorToken_badIndex
Definition PoPs.h:35
@ PoPs_errorToken_badName
Definition PoPs.h:35
@ PoPs_errorToken_badUnitConversion
Definition PoPs.h:35
int PoP_getIndex(PoP *pop)
Definition PoPs.cc:612
char const * PoPs_getName_atIndex(statusMessageReporting *smr, int index)
Definition PoPs.cc:275
int PoPs_release(statusMessageReporting *smr)
Definition PoPs.cc:88
int PoPs_particleIndex(char const *name)
Definition PoPs.cc:204
int PoPs_versionMajor(void)
Definition PoPs.cc:67
#define POPS_VERSION_MINOR
Definition PoPs.h:28
int PoP_release(PoP *pop)
Definition PoPs.cc:549
char const * PoPs_genreTokenToString(enum PoPs_genre genre)
Definition PoPs.cc:446
enum PoPs_genre PoPs_getGenre(statusMessageReporting *smr, char const *name)
Definition PoPs.cc:301
int PoP_copyParticle(statusMessageReporting *smr, PoP *desc, PoP *src)
Definition PoPs.cc:567
int PoPs_getAtomsIndex(statusMessageReporting *smr, char const *name)
Definition PoPs.cc:397
double PoPs_getMassInUnitOf_atIndex(statusMessageReporting *smr, int index, char const *unit)
Definition PoPs.cc:286
PoP * PoP_makeAlias(statusMessageReporting *smr, char const *name, char const *alias)
Definition PoPs.cc:647
int PoPs_readDatabase(statusMessageReporting *smr, char const *fileName)
Definition PoPs.cc:81
int PoP_setZ_A_l(statusMessageReporting *smr, PoP *pop, int Z, int A, int l)
Definition PoPs.cc:602
int PoPs_versionMinor(void)
Definition PoPs.cc:68
PoP * PoPs_addAliasIfNeeded(statusMessageReporting *smr, char const *name, char const *alias)
Definition PoPs.cc:179
int PoPs_versionPatchLevel(void)
Definition PoPs.cc:69
int PoPs_getZ_A_l_atIndex(statusMessageReporting *smr, int index, int *Z, int *A, int *l)
Definition PoPs.cc:335
int PoPs_numberOfParticle(void)
Definition PoPs.cc:197
int PoPs_smr_ID
Definition PoPs.cc:35
char const * PoPs_getAtomsName(statusMessageReporting *smr, char const *name)
Definition PoPs.cc:377
PoP * PoPs_copyAddParticleIfNeeded(statusMessageReporting *smr, PoP *pop)
Definition PoPs.cc:153
int PoPs_hasNucleus(statusMessageReporting *smr, char const *name, int protonIsNucleus)
Definition PoPs.cc:349
int PoPs_register(void)
Definition PoPs.cc:73
double PoP_getMassInUnitOf(statusMessageReporting *smr, PoP *pop, char const *unit)
Definition PoPs.cc:626
int PoP_initialize(statusMessageReporting *smr, PoP *pop)
Definition PoPs.cc:533
const char * PoPs_version(void)
Definition PoPs.cc:59
int PoPs_particleReadDatabase(statusMessageReporting *smr, char const *name)
Definition PoPs_data.cc:36
PoP * PoPs_addParticleIfNeeded(statusMessageReporting *smr, PoP *pop)
Definition PoPs.cc:113
int PoPs_unitConversionRatio(char const *_from, char const *_to, double *ratio)
Definition PoPs.cc:748
#define POPS_VERSION_PATCHLEVEL
Definition PoPs.h:29
enum PoPs_genre PoPs_getGenre_atIndex(statusMessageReporting *smr, int index)
Definition PoPs.cc:311
PoP * PoPs_getParticle_atIndex(int index)
Definition PoPs.cc:438
char const * PoP_getName(PoP *pop)
Definition PoPs.cc:619
PoP * PoP_makeParticle(statusMessageReporting *smr, enum PoPs_genre genre, char const *name, double mass, char const *massUnit)
Definition PoPs.cc:585
PoPs_genre
Definition PoPs.h:36
@ PoPs_genre_atom
Definition PoPs.h:37
@ PoPs_genre_nucleus
Definition PoPs.h:37
@ PoPs_genre_alias
Definition PoPs.h:36
@ PoPs_genre_unknown
Definition PoPs.h:36
@ PoPs_genre_invalid
Definition PoPs.h:36
double PoPs_getMassInUnitOf(statusMessageReporting *smr, char const *name, char const *unit)
Definition PoPs.cc:265
int PoPs_hasNucleus_atIndex(statusMessageReporting *smr, int index, int protonIsNucleus)
Definition PoPs.cc:359
PoP * PoP_free(PoP *pop)
Definition PoPs.cc:558
void PoPs_print(int sorted)
Definition PoPs.cc:455
int PoPs_Bcast2(statusMessageReporting *smr, MPI_Comm comm, int bossRank, unitsDB *unitsRoot, PoPs *popsRoot)
int PoPs_releasePrivate(statusMessageReporting *smr)
Definition PoPs.cc:98
char const * unitsDB_stringFromIndex(statusMessageReporting *smr, int index)
Definition PoPs.cc:737
int unitsDB_index(statusMessageReporting *smr, char const *unit)
Definition PoPs.cc:725
char const * unitsDB_addUnitIfNeeded(statusMessageReporting *smr, char const *unit)
Definition PoPs.cc:700
#define smr_setReportError2(smr, libraryID, code, fmt,...)
#define smr_allocateCopyString2(smr, s, forItem)
void * smr_freeMemory(void **p)
int smr_setReportError(statusMessageReporting *smr, void *userInterface, char const *file, int line, char const *function, int libraryID, int code, char const *fmt,...)
#define smr_malloc2(smr, size, zero, forItem)
#define smr_unknownID
Definition PoPs.h:45
int aliasIndex
Definition PoPs.h:46
int Z
Definition PoPs.h:49
int properIndex
Definition PoPs.h:46
char const * massUnit
Definition PoPs.h:51
enum PoPs_genre genre
Definition PoPs.h:47
char const * name
Definition PoPs.h:48
double mass
Definition PoPs.h:50
int l
Definition PoPs.h:49
int index
Definition PoPs.h:46
int A
Definition PoPs.h:49
int allocated
PoP ** pops
int numberOfParticles
PoP ** sorted
char const * _from
Definition PoPs.cc:30
char const * _to
Definition PoPs.cc:31
double ratio
Definition PoPs.cc:32
int numberOfUnits
char const ** unsorted