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