00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <ctype.h>
00038
00039 #include <gString.h>
00040 #include <tpia_target.h>
00041 #include <tpia_misc.h>
00042
00043 #if defined __cplusplus
00044 namespace GIDI {
00045 using namespace GIDI;
00046 #endif
00047
00048 static const int tpia_b_unknown = 0,
00049 tpia_b_twoBody_angular = tpia_m_angular,
00050 tpia_b_twoBody_formFactor = 0,
00051 tpia_b_NBody_Legendre = tpia_m_Legendre,
00052 tpia_b_NBody_angular_energy = tpia_m_angular | tpia_m_angular_energy,
00053 tpia_b_NBody_uncorrelate_Legendre = tpia_m_angular | tpia_m_Legendre,
00054 tpia_b_NBody_pairProduction = 0;
00055
00056 const char *tpia_productGenre_unknown = "unknown",
00057 *tpia_productGenre_twoBody_angular = "twoBody_angular",
00058 *tpia_productGenre_twoBody_formFactor = "twoBody_formFactor",
00059 *tpia_productGenre_NBody_Legendre = "NBody_Legendre",
00060 *tpia_productGenre_NBody_angular_energy = "NBody_angular_energy",
00061 *tpia_productGenre_NBody_uncorrelate_Legendre = "NBody_uncorrelate_Legendre",
00062 *tpia_productGenre_NBody_pairProduction = "NBody_pairProduction";
00063
00064 static int _tpia_product_getProductOutgoingData( statusMessageReporting *smr, xData_element *productElement, tpia_product *product );
00065 static int _tpia_product_checkRequiredData( statusMessageReporting *smr, int allowMany, int m, xData_element *productElement, tpia_product *product, char *str );
00066 static int _tpia_product_getDepositionEnergy( statusMessageReporting *smr, xData_element *depositionEnergy, tpia_product *product );
00067 static int _tpia_product_getMultiplicityFromElement( statusMessageReporting *smr, xData_element *data, tpia_product *product );
00068
00069
00070
00071 tpia_product *tpia_product_create( statusMessageReporting *smr ) {
00072
00073 tpia_product *product;
00074
00075
00076 if( ( product = (tpia_product*) xData_malloc2( smr, sizeof( tpia_product ), 0, "product" ) ) == NULL ) return( NULL );
00077 if( tpia_product_initialize( smr, product ) ) product = tpia_product_free( smr, product );
00078 return( product );
00079 }
00080
00081
00082
00083 int tpia_product_initialize( statusMessageReporting *smr, tpia_product *product ) {
00084
00085 memset( product, 0, sizeof( tpia_product ) );
00086 if( tpia_angular_initialize( smr, &(product->angular) ) ) return( 1 );
00087 if( tpia_Legendre_initialize( smr, &(product->Legendre) ) ) return( 1 );
00088 return( 0 );
00089 }
00090
00091
00092
00093 tpia_product *tpia_product_createGetFromElement( statusMessageReporting *smr, tpia_channel *channel, tpia_product *parentProduct,
00094 xData_element *productElement ) {
00095
00096 tpia_product *product;
00097
00098 if( ( product = tpia_product_create( smr ) ) == NULL ) return( NULL );
00099 if( tpia_product_getFromElement( smr, channel, parentProduct, productElement, product ) != 0 ) product = tpia_product_free( smr, product );
00100 return( product );
00101 }
00102
00103
00104
00105 tpia_product *tpia_product_free( statusMessageReporting *smr, tpia_product *product ) {
00106
00107 tpia_product_release( smr, product );
00108 xData_free( smr, product );
00109 return( NULL );
00110 }
00111
00112
00113
00114 int tpia_product_release( statusMessageReporting *smr, tpia_product *product) {
00115
00116 tpia_multiplicity *multiplicity, *multiplicity_next;
00117 tpia_product *decayProduct, *nextProduct;
00118
00119 xData_releaseAttributionList( smr, &(product->attributes) );
00120
00121 product->depositionEnergyGrouped.data = (double*) xData_free( smr, product->depositionEnergyGrouped.data );
00122
00123 if( product->multiplicityVsEnergy != NULL ) tpia_multiplicity_free( smr, product->multiplicityVsEnergy );
00124 for( multiplicity = product->delayedNeutronMultiplicityVsEnergy; multiplicity != NULL; multiplicity = multiplicity_next ) {
00125 multiplicity_next = multiplicity->next;
00126 tpia_multiplicity_free( smr, multiplicity );
00127 }
00128 tpia_angular_release( smr, &(product->angular) );
00129 tpia_Legendre_release( smr, &(product->Legendre ) );
00130 tpia_angularEnergy_release( smr, &(product->angularEnergy) );
00131 for( decayProduct = product->decayChannel.products; decayProduct != NULL; decayProduct = nextProduct ) {
00132 nextProduct = decayProduct->next;
00133 tpia_product_free( smr, decayProduct );
00134 }
00135 product->decayChannel.numberOfProducts = 0;
00136 product->decayChannel.products = NULL;
00137 return( 0 );
00138 }
00139
00140
00141
00142 int tpia_product_getFromElement( statusMessageReporting *smr, tpia_channel *channel, tpia_product *parentProduct, xData_element *productElement,
00143 tpia_product *product ) {
00144
00145 char const *productGenre;
00146 char *name, *multiplicity, *e;
00147
00148 xData_addToAccessed( smr, productElement, 1 );
00149 product->channel = channel;
00150 product->parentProduct = parentProduct;
00151 if( xData_copyAttributionList( smr, &(product->attributes), &(productElement->attributes) ) != 0 ) return( 0 );
00152 name = tpia_misc_pointerToAttributeIfAllOk2( smr, productElement, 1, &(product->attributes), "particle" );
00153 if( name != NULL ) {
00154 product->productID = tpia_particle_getInternalID( smr, name );
00155 multiplicity = tpia_misc_pointerToAttributeIfAllOk2( smr, productElement, 1, &(product->attributes), "multiplicity" );
00156 if( multiplicity != NULL ) {
00157 if( strcmp( multiplicity, "energyDependent" ) && strcmp( multiplicity, "partialProduction" ) ) {
00158 product->multiplicity = strtol( multiplicity, &e, 10 );
00159 while( isspace( *e ) ) e++;
00160 if( *e != 0 ) tpia_misc_setMessageError_Element( smr, NULL, productElement, __FILE__, __LINE__, 1, "bad multiplicity = %s", multiplicity );
00161 }
00162 }
00163 }
00164 if( ( productGenre = tpia_misc_pointerToAttributeIfAllOk2( smr, productElement, 1, &(product->attributes), "genre" ) ) != NULL ) {
00165 if( strcmp( productGenre, tpia_productGenre_unknown ) == 0 ) {
00166 product->b_dataRequired = 0;
00167 product->genre = tpia_productGenre_unknown; }
00168 else if( strcmp( productGenre, tpia_productGenre_twoBody_angular ) == 0 ) {
00169 product->b_dataRequired = tpia_b_twoBody_angular;
00170 product->genre = tpia_productGenre_twoBody_angular; }
00171 else if( strcmp( productGenre, tpia_productGenre_twoBody_formFactor ) == 0 ) {
00172 product->b_dataRequired = tpia_b_twoBody_formFactor;
00173 product->genre = tpia_productGenre_twoBody_formFactor; }
00174 else if( strcmp( productGenre, tpia_productGenre_NBody_Legendre ) == 0 ) {
00175 product->b_dataRequired = tpia_b_NBody_Legendre;
00176 product->genre = tpia_productGenre_NBody_Legendre; }
00177 else if( strcmp( productGenre, tpia_productGenre_NBody_angular_energy ) == 0 ) {
00178 product->b_dataRequired = tpia_b_NBody_angular_energy;
00179 product->genre = tpia_productGenre_NBody_angular_energy; }
00180 else if( strcmp( productGenre, tpia_productGenre_NBody_uncorrelate_Legendre ) == 0 ) {
00181 product->b_dataRequired = tpia_b_NBody_uncorrelate_Legendre;
00182 product->genre = tpia_productGenre_NBody_uncorrelate_Legendre; }
00183 else if( strcmp( productGenre, tpia_productGenre_NBody_pairProduction ) == 0 ) {
00184 product->b_dataRequired = tpia_b_NBody_pairProduction;
00185 product->genre = tpia_productGenre_NBody_pairProduction; }
00186 else {
00187 tpia_misc_setMessageError_Element( smr, NULL, productElement, __FILE__, __LINE__, 1, "unsupported product genre = %s", productGenre );
00188 }
00189 if( smr_isOk( smr ) ) _tpia_product_getProductOutgoingData( smr, productElement, product );
00190 }
00191 return( !smr_isOk( smr ) );
00192 }
00193
00194
00195
00196 static int _tpia_product_getProductOutgoingData( statusMessageReporting *smr, xData_element *productElement, tpia_product *product ) {
00197
00198 xData_element *data;
00199 int allowMany = 0;
00200
00201 for( data = xData_getFirstElement( productElement ); data != NULL; data = xData_getNextElement( data ) ) {
00202 if( strcmp( data->name, "depositionEnergy" ) == 0 ) {
00203
00204 if( _tpia_product_checkRequiredData( smr, allowMany, tpia_m_depositionEnergy, productElement, product, (char*)"deposition energy" ) ) return( 1 );
00205 if( _tpia_product_getDepositionEnergy( smr, data, product ) != 0 ) return( 1 ); }
00206 else if( strcmp( data->name, "multiplicity" ) == 0 ) {
00207 allowMany = ( product->channel->fission != NULL ) && ( strcmp( product->productID->name, "n_1" ) == 0 );
00208
00209 if( _tpia_product_checkRequiredData( smr, allowMany, tpia_m_multiplicity, productElement, product, (char*) "multiplicity" ) ) return( 1 );
00210 if( _tpia_product_getMultiplicityFromElement( smr, data, product ) != 0 ) return( 1 ); }
00211 else if( strcmp( data->name, "angular" ) == 0 ) {
00212
00213 if( _tpia_product_checkRequiredData( smr, allowMany, tpia_m_angular, productElement, product, (char*) "angular" ) ) return( 1 );
00214 if( tpia_angular_getFromElement( smr, data, &(product->angular) ) != 0 ) return( 1 ); }
00215 else if( strcmp( data->name, "Legendre" ) == 0 ) {
00216
00217 if( _tpia_product_checkRequiredData( smr, allowMany, tpia_m_Legendre, productElement, product, (char*) "Legendre" ) ) return( 1 );
00218 if( tpia_Legendre_getFromElement( smr, data, &(product->Legendre) ) != 0 ) return( 1 ); }
00219 else if( strcmp( data->name, "angularEnergy" ) == 0 ) {
00220 if( _tpia_product_checkRequiredData( smr, allowMany, tpia_m_angular_energy, productElement, product, (char*) "angularEnergy" ) ) return( 1 );
00221 if( tpia_angularEnergy_getFromElement( smr, data, &(product->angularEnergy) ) != 0 ) return( 1 ); }
00222 else if( strcmp( data->name, "decayChannel" ) == 0 ) {
00223 xData_addToAccessed( smr, data, 1 );
00224 if( tpia_product_getDecayChannelFromElement( smr, data, product->channel, product, &(product->decayChannel.products) ) ) return( 1 ); }
00225 else {
00226 printf( " %s\n", data->name );
00227 }
00228 }
00229 if( ( product->b_dataPresent >> tpia_m_commonShift ) != ( product->b_dataRequired >> tpia_m_commonShift ) ) {
00230 gString gStr;
00231 int missing = ~product->b_dataPresent & product->b_dataRequired;
00232 char const *str = "";
00233 if( gString_initialize( NULL, &gStr, 100, 100 ) == 0 ) {
00234 if( missing & tpia_m_angular ) gString_addTo( NULL, &gStr, "angular " );
00235 if( missing & tpia_m_formFactor ) gString_addTo( NULL, &gStr, "formFactor " );
00236 if( missing & tpia_m_Legendre ) gString_addTo( NULL, &gStr, "Legendre " );
00237 if( missing & tpia_m_angular_energy ) gString_addTo( NULL, &gStr, "angular_energy " );
00238 str = gString_string( NULL, &gStr );
00239 }
00240 tpia_misc_setMessageError_Element( smr, NULL, productElement, __FILE__, __LINE__, 1, "missing data %s for product %s", str,
00241 product->productID->name );
00242 gString_release( NULL, &gStr );
00243 return( 1 );
00244 }
00245 return( 0 );
00246 }
00247
00248
00249
00250 static int _tpia_product_checkRequiredData(statusMessageReporting *smr, int allowMany, int m, xData_element *productElement, tpia_product *product, char *str) {
00251
00252 if( !allowMany && ( product->b_dataPresent & m ) ) {
00253 tpia_misc_setMessageError_Element( smr, NULL, productElement, __FILE__, __LINE__, 1, "multiple %s", str );
00254 return( 1 );
00255 }
00256 if( ( m & ( tpia_m_depositionEnergy | tpia_m_multiplicity | tpia_m_decayChannel ) ) == 0 ) {
00257 if( ( product->b_dataRequired & m ) == 0 ) {
00258 tpia_misc_setMessageError_Element( smr, NULL, productElement, __FILE__, __LINE__, 1, "extra product data %s", str );
00259 return( 1 );
00260 }
00261 }
00262 product->b_dataPresent += m;
00263 return( 0 );
00264 }
00265
00266
00267
00268 int tpia_product_getDecayChannelFromElement( statusMessageReporting *smr, xData_element *parentElement, tpia_channel *channel, tpia_product *parentProduct,
00269 tpia_product **priorProductNext ) {
00270
00271 xData_elementList *list;
00272 tpia_product *product;
00273 int i, status = 0;
00274
00275 list = xData_getElementsByTagName( smr, parentElement, "product" );
00276 for( i = 0; i < list->n; i++ ) {
00277 if( ( product = tpia_product_createGetFromElement( smr, channel, parentProduct, list->items[i].element ) ) == NULL ) {
00278 status = 1;
00279 break;
00280 }
00281 if( parentProduct == NULL ) {
00282 channel->decayChannel.m1_fullMass_MeV = channel->target->projectileID->fullMass_MeV;
00283 channel->decayChannel.m2_fullMass_MeV = channel->target->targetID->fullMass_MeV;
00284 channel->decayChannel.numberOfProducts++; }
00285 else {
00286 channel->decayChannel.m1_fullMass_MeV = parentProduct->productID->fullMass_MeV;
00287 channel->decayChannel.m2_fullMass_MeV = 0.;
00288 parentProduct->decayChannel.numberOfProducts++;
00289 }
00290 *priorProductNext = product;
00291 priorProductNext = &(product->next);
00292 }
00293 xData_freeElementList( smr, list );
00294 return( status );
00295 }
00296
00297
00298
00299 static int _tpia_product_getDepositionEnergy( statusMessageReporting *smr, xData_element *depositionEnergy, tpia_product *product ) {
00300
00301 xData_element *data;
00302
00303 xData_addToAccessed( smr, depositionEnergy, 1 );
00304 for( data = xData_getFirstElement( depositionEnergy ); data != NULL; data = xData_getNextElement( data ) ) {
00305 if( strcmp( data->name, "grouped" ) == 0 ) {
00306 if( tpia_misc_get2d_xShared_yHistogram_data_Grouped( smr, data, &(product->depositionEnergyGrouped) ) ) return( 1 ); }
00307 else {
00308 tpia_misc_setMessageError_Element( smr, NULL, depositionEnergy, __FILE__, __LINE__, 1, "unsupported deposition energy type = %s", data->name );
00309 return( 1 );
00310 }
00311 }
00312 return( 0 );
00313 }
00314
00315
00316
00317 static int _tpia_product_getMultiplicityFromElement( statusMessageReporting *smr, xData_element *data, tpia_product *product ) {
00318
00319 tpia_multiplicity *multiplicity, *prior, *current;
00320 const char *timeScale;
00321 int isDelayedNeutrons;
00322 double dTimeScale;
00323
00324 if( tpia_multiplicity_getTimeScaleFromElement( smr, data, &timeScale, &isDelayedNeutrons, &dTimeScale ) ) return( 1 );
00325 if( ( isDelayedNeutrons == 0 ) && ( product->multiplicityVsEnergy != NULL ) ) {
00326 tpia_misc_setMessageError_Element( smr, NULL, data, __FILE__, __LINE__, 1, "extra product multiplicity data" );
00327 return( 1 );
00328 }
00329 if( ( multiplicity = tpia_multiplicity_createGetFromElement( smr, data, product->channel->target->nGroups ) ) == NULL ) return( 1 );
00330 if( isDelayedNeutrons == 0 ) {
00331 product->multiplicityVsEnergy = multiplicity; }
00332 else {
00333 if( product->delayedNeutronMultiplicityVsEnergy == NULL ) {
00334 product->delayedNeutronMultiplicityVsEnergy = multiplicity; }
00335 else {
00336 if( product->delayedNeutronMultiplicityVsEnergy->timeScale > multiplicity->timeScale ) {
00337 multiplicity->next = product->delayedNeutronMultiplicityVsEnergy;
00338 product->delayedNeutronMultiplicityVsEnergy = multiplicity; }
00339 else {
00340 for( current = product->delayedNeutronMultiplicityVsEnergy->next, prior = product->delayedNeutronMultiplicityVsEnergy; current != NULL;
00341 current = current->next ) {
00342 if( current->timeScale > multiplicity->timeScale ) {
00343 multiplicity->next = current;
00344 prior->next = multiplicity;
00345 break;
00346 }
00347 prior = current;
00348 }
00349 if( current == NULL ) prior->next = multiplicity;
00350 }
00351 }
00352 }
00353 return( 0 );
00354 }
00355
00356
00357
00358
00359 long tpia_product_dataRequired( statusMessageReporting *, tpia_product *product ) {
00360
00361 return( product->b_dataRequired );
00362 }
00363
00364
00365
00366 tpia_product *tpia_product_getFirstProduct( tpia_product *product ) {
00367
00368 return( tpia_decayChannel_getFirstProduct( &(product->decayChannel) ) );
00369 }
00370
00371
00372
00373
00374 tpia_product *tpia_product_getProductByIndex( statusMessageReporting *, tpia_product *product, int index ) {
00375
00376 int i = 0;
00377 tpia_product *p;
00378
00379 if( index < 0 ) return( NULL );
00380 for( p = tpia_product_getFirstProduct( product ); ( p != NULL ) && ( i < index ); p = tpia_decayChannel_getNextProduct( p ), i++ ) ;
00381 return( p );
00382 }
00383
00384
00385
00386
00387 int tpia_product_doesDecay( statusMessageReporting *, tpia_product *product ) {
00388
00389 return( product->decayChannel.products != NULL );
00390 }
00391
00392
00393
00394
00395 int tpia_product_numberOfProducts( statusMessageReporting *, tpia_product *product ) {
00396
00397 return( product->decayChannel.numberOfProducts );
00398 }
00399
00400
00401
00402
00403 int tpia_product_isDataPresent( statusMessageReporting *, tpia_product *product, int b_data ) {
00404
00405 return( product->b_dataPresent && b_data );
00406 }
00407
00408
00409
00410
00411 int tpia_product_sampleMultiplicity( statusMessageReporting *, tpia_product *product, double e_in, double r ) {
00412
00413 int i, multiplicity;
00414 tpia_multiplicity *multiplicityVsEnergy = product->multiplicityVsEnergy;
00415 double *p = multiplicityVsEnergy->pointwise, dMult;
00416
00417 if( e_in <= p[0] ) {
00418 dMult = p[1]; }
00419 else if( e_in >= p[2 * ( multiplicityVsEnergy->numberOfPointwise - 1 )] ) {
00420 dMult = p[2 * multiplicityVsEnergy->numberOfPointwise - 1]; }
00421 else {
00422 for( i = 0; i < multiplicityVsEnergy->numberOfPointwise - 1; i++, p += 2 ) if( e_in < p[2] ) break;
00423 dMult = ( e_in - p[0] ) / ( p[2] - p[0] );
00424 dMult = dMult * p[3] + ( 1. - dMult ) * p[1];
00425 }
00426 multiplicity = (int) dMult;
00427 if( r < ( dMult - multiplicity ) ) multiplicity++;
00428
00429 return( multiplicity );
00430 }
00431
00432 #if defined __cplusplus
00433 }
00434 #endif