Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/lend/src/PoPs.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /processes/hadronic/models/lend/src/PoPs.cc (Version 11.3.0) and /processes/hadronic/models/lend/src/PoPs.cc (Version 10.4.p1)


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