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)