Geant4 11.1.1
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 G4int Z[17]
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
Definition: PoPs_private.h:25
PoP ** pops
Definition: PoPs_private.h:26
int numberOfParticles
Definition: PoPs_private.h:24
PoP ** sorted
Definition: PoPs_private.h:27
char const * _from
Definition: PoPs.cc:30
char const * _to
Definition: PoPs.cc:31
double ratio
Definition: PoPs.cc:32
int allocated
Definition: PoPs_private.h:19
int numberOfUnits
Definition: PoPs_private.h:18
char const ** unsorted
Definition: PoPs_private.h:20