6 #include "PoPs_private.h"
13 #if defined __cplusplus
18 #define incrementalSize 1000
22 #define AMU2MeV 931.494028
23 #define AMU2eV ( MeV2eV * 931.494028 )
24 #define K2MeV 8.6173856922566752e-11
25 #define K2eV ( MeV2eV * K2MeV )
49 {
"MeV",
"eV",
MeV2eV }, {
"MeV",
"keV",
MeV2keV }, {
"K",
"MeV",
K2MeV }, {
"K",
"eV",
K2eV } };
51 static char const *
PoPs_genreStrings[] = {
"invalid",
"unknown",
"alias",
"photon",
"lepton",
"quark",
"meson",
"baryon",
"nucleus",
"atom" };
61 if( versionStr[0] == 0 ) sprintf( versionStr,
"PoPs version %d.%d.%d", POPS_VERSION_MAJOR, POPS_VERSION_MINOR, POPS_VERSION_PATCHLEVEL );
75 if( referenceCount < 0 )
return( -1 );
76 return( ++referenceCount );
91 if( referenceCount != 0 )
return( referenceCount );
102 for( i = 0; i < popsRoot.numberOfParticles; i++ )
PoP_free( popsRoot.pops[i] );
104 popsRoot.sorted = NULL;
105 popsRoot.numberOfParticles = 0;
106 popsRoot.allocated = 0;
121 if( popsRoot.numberOfParticles == popsRoot.allocated ) {
123 PoP **sorted, **pops = (PoP **) smr_malloc2( smr, 2 * size *
sizeof( PoPs * ), 0,
"pops" );
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];
132 popsRoot.pops = pops;
133 popsRoot.sorted = sorted;
134 popsRoot.allocated = size;
136 popsRoot.pops[popsRoot.numberOfParticles] = pop;
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 ) {
145 for( pop2 = popsRoot.pops[pop->properIndex]; pop2->aliasIndex >= 0; pop2 = popsRoot.pops[pop2->aliasIndex] ) ;
146 pop2->aliasIndex = pop->index;
163 if( index >= 0 )
return( popsRoot.pops[index] );
165 if( ( newPoP = (PoP *) smr_malloc2( smr,
sizeof( PoP ), 0,
"newPoP" ) ) == NULL )
return( NULL );
184 if( pop->index < 0 ) {
199 return( popsRoot.numberOfParticles );
221 smr_setReportError( smr, NULL, file, line, func, PoPs_smr_ID, PoPs_errorToken_badName,
"particle '%s' not in PoPs", name );
229 while( popsRoot.pops[index]->properIndex >= 0 ) index = popsRoot.pops[index]->properIndex;
240 int low = 0, mid, high = popsRoot.numberOfParticles, iCmp;
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 );
254 if( !strcmp( name, popsRoot.sorted[0]->name ) )
return( 0 );
255 if( strcmp( name, popsRoot.sorted[0]->name ) < 0 )
return( -1 );
257 if( high < popsRoot.numberOfParticles ) {
258 if( strcmp( name, popsRoot.sorted[high]->name ) == 0 )
return( high );
269 if( index < 0 )
return( -1. );
277 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
278 smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex,
"index %d not in PoPs", index );
281 return( popsRoot.pops[index]->name );
290 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
291 smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex,
"index %d not in PoPs", index ); }
305 if( index < 0 )
return( PoPs_genre_invalid );
306 return( popsRoot.pops[index]->genre );
313 enum PoPs_genre genre = PoPs_genre_invalid;
315 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
316 smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex,
"index %d not in PoPs", index ); }
318 genre = popsRoot.pops[index]->genre;
329 if( index < 0 )
return( -1 );
337 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
338 smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex,
"index %d not in PoPs", index );
341 *Z = popsRoot.pops[index]->Z;
342 *A = popsRoot.pops[index]->A;
353 if( index < 0 )
return( -1 );
364 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
365 smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex,
"index %d not in PoPs", index );
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 );
381 if( index < 0 )
return( NULL );
391 if( atomIndex < 0 )
return( NULL );
392 return( popsRoot.pops[atomIndex]->name );
401 if( index < 0 )
return( index );
409 char const *p = NULL;
411 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) ) {
412 smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badIndex,
"index %d not in PoPs", index );
416 if( popsRoot.pops[index]->genre == PoPs_genre_atom )
return( index );
418 if( strcmp(
"p", popsRoot.pops[index]->name ) == 0 ) {
421 if( popsRoot.pops[index]->genre != PoPs_genre_nucleus )
return( -1 );
422 else if( strcmp(
"h2", popsRoot.pops[index]->name ) == 0 ) {
424 else if( strcmp(
"h3", popsRoot.pops[index]->name ) == 0 ) {
426 else if( strcmp(
"he3", popsRoot.pops[index]->name ) == 0 ) {
428 else if( strcmp(
"he4", popsRoot.pops[index]->name ) == 0 ) {
440 if( ( index < 0 ) || ( index >= popsRoot.numberOfParticles ) )
return( NULL );
441 return( popsRoot.pops[index] );
448 if( genre < PoPs_genre_invalid )
return( NULL );
449 if( genre > PoPs_genre_atom )
return( NULL );
450 return( PoPs_genreStrings[genre] );
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] );
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++ ) {
478 pop = popsRoot.sorted[i1]; }
480 pop = popsRoot.pops[i1];
484 popsRoot.pops[properIndex]->mass, popsRoot.pops[properIndex]->massUnit );
486 fprintf( f,
" T" ); }
491 fprintf( f,
" T" ); }
495 if( pop->Z + pop->A > 0 ) {
496 fprintf( f,
" %3d %3d", pop->Z, pop->A );
498 fprintf( f,
" %d", pop->l ); }
505 if( pop->genre == PoPs_genre_alias ) {
506 fprintf( f,
" %s (%d)", popsRoot.pops[properIndex]->name, popsRoot.pops[properIndex]->index ); }
510 for( aliasIndex = pop->aliasIndex; aliasIndex >= 0; aliasIndex = popsRoot.pops[aliasIndex]->aliasIndex ) fprintf( f,
" %d", aliasIndex );
526 if( ( pop = (PoP *) smr_malloc2( smr,
sizeof( PoP ), 0,
"pop" ) ) == NULL )
return( NULL );
536 pop->properIndex = -1;
537 pop->aliasIndex = -1;
538 pop->genre = PoPs_genre_unknown;
543 pop->massUnit = NULL;
551 if( pop->name != NULL )
smr_freeMemory( (
void **) &(pop->name ) );
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 );
577 desc->mass = src->mass;
578 desc->massUnit = src->massUnit;
585 PoP *
PoP_makeParticle( statusMessageReporting *smr,
enum PoPs_genre genre,
char const *
name,
double mass,
char const *massUnit ) {
589 if( ( pop =
PoP_new( smr ) ) == NULL )
return( NULL );
590 if( ( pop->name = smr_allocateCopyString2( smr, name,
"name" ) ) == NULL ) {
602 int PoP_setZ_A_l( statusMessageReporting * , PoP *pop,
int Z,
int A,
int l ) {
614 return( pop->index );
628 double mass = -1., ratio;
633 smr_setReportError2( smr, PoPs_smr_ID, PoPs_errorToken_badUnitConversion,
"could not convert unit '%s' to '%s'", pop->massUnit, unit ); }
635 mass = pop->mass * ratio;
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 );
656 if( aliasIndex >= 0 ) {
657 PoP *truePop = popsRoot.pops[aliasIndex];
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 );
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 );
670 if( ( pop =
PoP_new( smr ) ) == NULL )
return( NULL );
671 if( ( pop->name = smr_allocateCopyString2( smr, alias,
"name" ) ) == NULL ) {
675 pop->properIndex = properIndex;
676 pop->genre = PoPs_genre_alias;
691 for( i = 0; i < unitsRoot.numberOfUnits; i++ )
smr_freeMemory( (
void **) &(unitsRoot.unsorted[i]) );
693 unitsRoot.numberOfUnits = 0;
694 unitsRoot.allocated = 0;
704 for( i = 0; i < unitsRoot.numberOfUnits; i++ ) {
705 if( strcmp( unit, unitsRoot.unsorted[i] ) == 0 )
return( unitsRoot.unsorted[i] );
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" );
711 if( unsorted == NULL )
return( NULL );
712 for( i = 0; i < unitsRoot.numberOfUnits; i++ ) unsorted[i] = unitsRoot.unsorted[i];
714 unitsRoot.unsorted = unsorted;
715 unitsRoot.allocated = size;
717 if( ( unitsRoot.unsorted[unitsRoot.numberOfUnits] = smr_allocateCopyString2( smr, unit,
"unitsRoot.unsorted[unitsRoot.numberOfUnits]" ) ) == NULL )
719 unitsRoot.numberOfUnits++;
720 return( unitsRoot.unsorted[unitsRoot.numberOfUnits - 1] );
729 for( i = 0; i < unitsRoot.numberOfUnits; i++ ) {
730 if( !strcmp( unit, unitsRoot.unsorted[i] ) )
return( i );
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 );
743 return( unitsRoot.unsorted[index] );
750 int i,
n =
sizeof(
conversions ) /
sizeof( conversions[0] );
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;
760 else if( strcmp( conversions[i]._to, _from ) == 0 ) {
761 if( strcmp( conversions[i]._from, _to ) == 0 ) {
762 *ratio = 1. / conversions[i].
ratio;
770 #include "PoPs_Bcast_private.h"
774 int PoPs_Bcast( statusMessageReporting *smr, MPI_Comm comm,
int rank ) {
776 return( PoPs_Bcast2( smr, comm, rank, &unitsRoot, &popsRoot ) );
780 #if defined __cplusplus
int PoPs_unitConversionRatio(char const *_from, char const *_to, double *ratio)
PoP * PoPs_addAliasIfNeeded(statusMessageReporting *smr, char const *name, char const *alias)
static int referenceCount
char const * PoPs_genreTokenToString(enum PoPs_genre genre)
int PoPs_readDatabase(statusMessageReporting *smr, char const *fileName)
int PoPs_versionMinor(void)
int PoPs_particleIndex(char const *name)
static char versionStr[64]
int PoP_copyParticle(statusMessageReporting *smr, PoP *desc, PoP *src)
static int PoPs_particleProperIndex(int index)
enum PoPs_genre PoPs_getGenre(statusMessageReporting *smr, char const *name)
int PoPs_numberOfParticle(void)
static int unitsDB_release(void)
int PoPs_getAtomsIndex(statusMessageReporting *smr, char const *name)
static int PoPs_sortedParticleIndex(char const *name)
static unitConversions conversions[]
enum PoPs_genre PoPs_getGenre_atIndex(statusMessageReporting *smr, int index)
int PoPs_particleReadDatabase(statusMessageReporting *smr, char const *)
int PoPs_hasNucleus(statusMessageReporting *smr, char const *name, int protonIsNucleus)
int PoPs_getAtomsIndex_atIndex(statusMessageReporting *smr, int index)
double PoPs_getMassInUnitOf(statusMessageReporting *smr, char const *name, char const *unit)
int PoPs_particleIndex_smr(statusMessageReporting *smr, char const *name, char const *file, int line, char const *func)
int unitsDB_index(statusMessageReporting *, char const *unit)
double A(double temperature)
char const * unitsDB_addUnitIfNeeded(statusMessageReporting *smr, char const *unit)
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[]
const char * PoPs_version(void)
int PoPs_getZ_A_l(statusMessageReporting *smr, char const *name, int *Z, int *A, int *l)
int PoP_setZ_A_l(statusMessageReporting *, PoP *pop, int Z, int A, int l)
int PoPs_releasePrivate(statusMessageReporting *)
PoP * PoP_makeAlias(statusMessageReporting *smr, char const *name, char const *alias)
void * smr_freeMemory(void **p)
char const * PoPs_getName_atIndex(statusMessageReporting *smr, int index)
char const * PoP_getName(PoP *pop)
PoP * PoP_makeParticle(statusMessageReporting *smr, enum PoPs_genre genre, char const *name, double mass, char const *massUnit)
double PoPs_getMassInUnitOf_atIndex(statusMessageReporting *smr, int index, char const *unit)
PoP * PoP_new(statusMessageReporting *smr)
char const * unitsDB_stringFromIndex(statusMessageReporting *smr, int index)
int PoPs_hasNucleus_atIndex(statusMessageReporting *smr, int index, int protonIsNucleus)
int PoPs_versionMajor(void)
int PoPs_getZ_A_l_atIndex(statusMessageReporting *smr, int index, int *Z, int *A, int *l)
PoP * PoPs_addParticleIfNeeded(statusMessageReporting *smr, PoP *pop)
PoP * PoPs_copyAddParticleIfNeeded(statusMessageReporting *smr, PoP *pop)
int PoPs_release(statusMessageReporting *smr)
double PoP_getMassInUnitOf(statusMessageReporting *smr, PoP *pop, char const *unit)
int PoPs_versionPatchLevel(void)
PoP * PoPs_getParticle_atIndex(int index)
int PoP_release(PoP *pop)
int PoP_getIndex(PoP *pop)
char const * PoPs_getAtomsName_atIndex(statusMessageReporting *smr, int index)
int PoP_initialize(statusMessageReporting *, PoP *pop)
char const * PoPs_getAtomsName(statusMessageReporting *smr, char const *name)
void PoPs_print(int sorted)
void PoPs_write(FILE *f, int sorted)