Geant4 Cross Reference |
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