330 lines
16 KiB
C++
330 lines
16 KiB
C++
/*
|
|
# <<BEGIN-copyright>>
|
|
# <<END-copyright>>
|
|
*/
|
|
#include <string.h>
|
|
#include <cmath>
|
|
|
|
#include "MCGIDI.h"
|
|
#include "MCGIDI_misc.h"
|
|
|
|
#if defined __cplusplus
|
|
#include "G4Log.hh"
|
|
namespace GIDI {
|
|
using namespace GIDI;
|
|
#endif
|
|
|
|
/*
|
|
************************************************************
|
|
*/
|
|
MCGIDI_outputChannel *MCGIDI_outputChannel_new( statusMessageReporting *smr ) {
|
|
|
|
MCGIDI_outputChannel *outputChannel;
|
|
|
|
if( ( outputChannel = (MCGIDI_outputChannel *) smr_malloc2( smr, sizeof( MCGIDI_outputChannel ), 0, "outputChannel" ) ) == NULL ) return( NULL );
|
|
if( MCGIDI_outputChannel_initialize( smr, outputChannel ) ) outputChannel = MCGIDI_outputChannel_free( smr, outputChannel );
|
|
return( outputChannel );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
int MCGIDI_outputChannel_initialize( statusMessageReporting * /*smr*/, MCGIDI_outputChannel *outputChannel ) {
|
|
|
|
memset( outputChannel, 0, sizeof( MCGIDI_outputChannel ) );
|
|
return( 0 );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
MCGIDI_outputChannel *MCGIDI_outputChannel_free( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel ) {
|
|
|
|
MCGIDI_outputChannel_release( smr, outputChannel );
|
|
smr_freeMemory( (void **) &outputChannel );
|
|
return( NULL );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
int MCGIDI_outputChannel_release( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel ) {
|
|
|
|
int i;
|
|
|
|
for( i = 0; i < outputChannel->numberOfProducts; i++ ) MCGIDI_product_release( smr, &(outputChannel->products[i]) );
|
|
smr_freeMemory( (void **) &(outputChannel->products) );
|
|
MCGIDI_outputChannel_initialize( smr, outputChannel );
|
|
|
|
return( 0 );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
int MCGIDI_outputChannel_parseFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_POPs *pops, MCGIDI_outputChannel *outputChannel,
|
|
MCGIDI_reaction *reaction, MCGIDI_product *parent ) {
|
|
|
|
int n, delayedNeutronIndex = 0;
|
|
char const *genre, *Q;
|
|
xDataTOM_element *child;
|
|
|
|
MCGIDI_outputChannel_initialize( smr, outputChannel );
|
|
|
|
outputChannel->reaction = reaction;
|
|
outputChannel->parent = parent;
|
|
if( ( genre = xDataTOM_getAttributesValueInElement( element, "genre" ) ) == NULL ) goto err;
|
|
if( ( parent != NULL ) && ( strcmp( genre, "NBody" ) ) ) {
|
|
smr_setReportError2( smr, smr_unknownID, 1, "decay channel's genre can only be 'uncorreclated' (a.k.a. 'NBody') and not '%s'", genre );
|
|
goto err;
|
|
}
|
|
if( strcmp( genre, "twoBody" ) == 0 ) {
|
|
outputChannel->genre = MCGIDI_channelGenre_twoBody_e; }
|
|
else if( strcmp( genre, "NBody" ) == 0 ) {
|
|
outputChannel->genre = MCGIDI_channelGenre_uncorrelated_e; }
|
|
else if( strcmp( genre, "sumOfRemainingOutputChannels" ) == 0 ) {
|
|
outputChannel->genre = MCGIDI_channelGenre_sumOfRemaining_e; }
|
|
else {
|
|
smr_setReportError2( smr, smr_unknownID, 1, "unsupported genre = '%s'", genre );
|
|
goto err;
|
|
}
|
|
if( ( Q = xDataTOM_getAttributesValueInElement( element, "Q" ) ) == NULL ) goto err;
|
|
outputChannel->QIsFloat = !MCGIDI_misc_PQUStringToDoubleInUnitOf( smr, Q, "MeV", &(outputChannel->Q) );
|
|
|
|
if( ( n = xDataTOM_numberOfElementsByName( smr, element, "product" ) ) == 0 ) {
|
|
smr_setReportError2p( smr, smr_unknownID, 1, "outputChannel does not have any products" );
|
|
goto err;
|
|
}
|
|
if( ( outputChannel->products = (MCGIDI_product *) smr_malloc2( smr, n * sizeof( MCGIDI_product ), 0, "outputChannel->products" ) ) == NULL ) goto err;
|
|
|
|
for( child = xDataTOME_getFirstElement( element ); child != NULL; child = xDataTOME_getNextElement( child ) ) {
|
|
if( strcmp( child->name, "product" ) == 0 ) {
|
|
if( MCGIDI_product_parseFromTOM( smr, child, outputChannel, pops, &(outputChannel->products[outputChannel->numberOfProducts]),
|
|
&delayedNeutronIndex ) ) goto err;
|
|
outputChannel->numberOfProducts++; }
|
|
else if( strcmp( child->name, "fissionEnergyReleased" ) == 0 ) { /* ????????? Need to support. */
|
|
continue; }
|
|
else {
|
|
printf( "outputChannel child not currently supported = %s\n", child->name );
|
|
}
|
|
}
|
|
if( outputChannel->genre == MCGIDI_channelGenre_twoBody_e ) {
|
|
double projectileMass_MeV, targetMass_MeV, productMass_MeV, residualMass_MeV;
|
|
|
|
projectileMass_MeV = MCGIDI_reaction_getProjectileMass_MeV( smr, reaction );
|
|
targetMass_MeV = MCGIDI_reaction_getTargetMass_MeV( smr, reaction );
|
|
productMass_MeV = MCGIDI_product_getMass_MeV( smr, &(outputChannel->products[0]) );
|
|
residualMass_MeV = MCGIDI_product_getMass_MeV( smr, &(outputChannel->products[1]) );
|
|
|
|
//TK 17-11-10 for v1.3
|
|
//A temporary fix for emission of gamma(2.2MeV) from n captured by H
|
|
// capture gamma D
|
|
if ( reaction->ENDF_MT == 102 && productMass_MeV == 0 && ( outputChannel->products[1].pop->A == 2 && outputChannel->products[1].pop->Z == 1 ) ) {
|
|
//include/PoPs_data.h:#define e_Mass 5.4857990943e-4 /* electron mass in AMU */
|
|
residualMass_MeV += 5.4857990943e-4*MCGIDI_AMU2MeV;
|
|
}
|
|
|
|
MCGIDI_product_setTwoBodyMasses( smr, &(outputChannel->products[0]), projectileMass_MeV, targetMass_MeV, productMass_MeV, residualMass_MeV );
|
|
}
|
|
|
|
return( 0 );
|
|
|
|
err:
|
|
MCGIDI_outputChannel_release( smr, outputChannel );
|
|
return( 1 );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
int MCGIDI_outputChannel_numberOfProducts( MCGIDI_outputChannel *outputChannel ) {
|
|
|
|
return( outputChannel->numberOfProducts );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
MCGIDI_product *MCGIDI_outputChannel_getProductAtIndex( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel, int i ) {
|
|
|
|
if( ( i < 0 ) || ( i >= outputChannel->numberOfProducts ) ) {
|
|
smr_setReportError2( smr, smr_unknownID, 1, "bad product index = %d: outputChannel as only %d products", i, outputChannel->numberOfProducts );
|
|
return( NULL );
|
|
}
|
|
return( &(outputChannel->products[i]) );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
int MCGIDI_outputChannel_getDomain( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel, double *EMin, double *EMax ) {
|
|
|
|
if( outputChannel->reaction != NULL ) return( MCGIDI_reaction_getDomain( smr, outputChannel->reaction, EMin, EMax ) );
|
|
return( MCGIDI_product_getDomain( smr, outputChannel->parent, EMin, EMax ) );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
MCGIDI_target_heated *MCGIDI_outputChannel_getTargetHeated( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel ) {
|
|
|
|
if( outputChannel->reaction != NULL ) return( MCGIDI_reaction_getTargetHeated( smr, outputChannel->reaction ) );
|
|
return( MCGIDI_product_getTargetHeated( smr, outputChannel->parent ) );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
double MCGIDI_outputChannel_getProjectileMass_MeV( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel ) {
|
|
|
|
if( outputChannel->reaction != NULL ) return( MCGIDI_reaction_getProjectileMass_MeV( smr, outputChannel->reaction ) );
|
|
return( MCGIDI_product_getProjectileMass_MeV( smr, outputChannel->parent ) );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
double MCGIDI_outputChannel_getTargetMass_MeV( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel ) {
|
|
|
|
if( outputChannel->reaction != NULL ) return( MCGIDI_reaction_getTargetMass_MeV( smr, outputChannel->reaction ) );
|
|
return( MCGIDI_product_getTargetMass_MeV( smr, outputChannel->parent ) );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
double MCGIDI_outputChannel_getQ_MeV( statusMessageReporting * /*smr*/, MCGIDI_outputChannel *outputChannel, double /*e_in*/ ) {
|
|
|
|
return( outputChannel->Q );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
double MCGIDI_outputChannel_getFinalQ( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel, double e_in ) {
|
|
|
|
int iProduct;
|
|
double Q = outputChannel->Q;
|
|
MCGIDI_product *product;
|
|
|
|
for( iProduct = 0; iProduct < outputChannel->numberOfProducts; iProduct++ ) {
|
|
product = &(outputChannel->products[iProduct]);
|
|
if( product->decayChannel.genre != MCGIDI_channelGenre_undefined_e ) Q += MCGIDI_outputChannel_getFinalQ( smr, &(product->decayChannel), e_in );
|
|
if( !smr_isOk( smr ) ) break;
|
|
}
|
|
return( Q );
|
|
}
|
|
/*
|
|
************************************************************
|
|
*/
|
|
int MCGIDI_outputChannel_sampleProductsAtE( statusMessageReporting *smr, MCGIDI_outputChannel *outputChannel, MCGIDI_quantitiesLookupModes &modes,
|
|
MCGIDI_decaySamplingInfo *decaySamplingInfo, MCGIDI_sampledProductsDatas *productDatas, double *masses_ ) {
|
|
|
|
int i1, multiplicity, secondTwoBody = 0, isDecayChannel = ( outputChannel->reaction == NULL );
|
|
double e_in = modes.getProjectileEnergy( );
|
|
MCGIDI_product *product;
|
|
double phi, p, masses[3];
|
|
MCGIDI_distribution *distribution;
|
|
MCGIDI_sampledProductsData productData[2];
|
|
|
|
if( isDecayChannel ) {
|
|
masses[0] = masses_[0]; /* More work may be needed here. */
|
|
masses[1] = masses_[1]; }
|
|
else {
|
|
masses[0] = MCGIDI_reaction_getProjectileMass_MeV( smr, outputChannel->reaction );
|
|
masses[1] = MCGIDI_reaction_getTargetMass_MeV( smr, outputChannel->reaction );
|
|
}
|
|
|
|
for( i1 = 0; i1 < outputChannel->numberOfProducts; i1++ ) {
|
|
product = &(outputChannel->products[i1]);
|
|
if( product->decayChannel.genre != MCGIDI_channelGenre_undefined_e ) {
|
|
if( MCGIDI_outputChannel_sampleProductsAtE( smr, &(product->decayChannel), modes, decaySamplingInfo, productDatas, masses ) < 0 ) return( -1 ); }
|
|
else {
|
|
distribution = &(product->distribution);
|
|
if( distribution->type == MCGIDI_distributionType_none_e ) continue;
|
|
if( !secondTwoBody ) {
|
|
if( ( multiplicity = product->multiplicity ) == 0 ) multiplicity = MCGIDI_product_sampleMultiplicity( smr, product, e_in,
|
|
decaySamplingInfo->rng( decaySamplingInfo->rngState ) );
|
|
while( multiplicity > 0 ) {
|
|
|
|
multiplicity--;
|
|
decaySamplingInfo->pop = product->pop;
|
|
decaySamplingInfo->mu = 0;
|
|
decaySamplingInfo->Ep = 0;
|
|
productData[0].isVelocity = decaySamplingInfo->isVelocity;
|
|
productData[0].pop = product->pop;
|
|
productData[0].delayedNeutronIndex = product->delayedNeutronIndex;
|
|
productData[0].delayedNeutronRate = product->delayedNeutronRate;
|
|
productData[0].birthTimeSec = 0;
|
|
if( product->delayedNeutronRate > 0 ) {
|
|
productData[0].birthTimeSec = -G4Log( decaySamplingInfo->rng( decaySamplingInfo->rngState ) ) / product->delayedNeutronRate;
|
|
}
|
|
|
|
switch( outputChannel->genre ) {
|
|
case MCGIDI_channelGenre_twoBody_e :
|
|
secondTwoBody = 1;
|
|
MCGIDI_angular_sampleMu( smr, distribution->angular, modes, decaySamplingInfo );
|
|
if( smr_isOk( smr ) ) {
|
|
phi = 2. * M_PI * decaySamplingInfo->rng( decaySamplingInfo->rngState );
|
|
MCGIDI_kinetics_2BodyReaction( smr, distribution->angular, e_in, decaySamplingInfo->mu, phi, productData );
|
|
if( !smr_isOk( smr ) ) return( -1 );
|
|
productData[1].pop = product[1].pop;
|
|
productData[1].delayedNeutronIndex = product[1].delayedNeutronIndex;
|
|
productData[1].delayedNeutronRate = product->delayedNeutronRate;
|
|
productData[1].birthTimeSec = 0;
|
|
MCGIDI_sampledProducts_addProduct( smr, productDatas, productData );
|
|
if( !smr_isOk( smr ) ) return( -1 );
|
|
MCGIDI_sampledProducts_addProduct( smr, productDatas, &(productData[1]) );
|
|
if( !smr_isOk( smr ) ) return( -1 );
|
|
}
|
|
break;
|
|
case MCGIDI_channelGenre_uncorrelated_e :
|
|
case MCGIDI_channelGenre_sumOfRemaining_e :
|
|
masses[2] = MCGIDI_product_getMass_MeV( smr, product );
|
|
switch( distribution->type ) {
|
|
case MCGIDI_distributionType_uncorrelated_e :
|
|
MCGIDI_uncorrelated_sampleDistribution( smr, distribution, modes, decaySamplingInfo );
|
|
break;
|
|
case MCGIDI_distributionType_energyAngular_e :
|
|
MCGIDI_energyAngular_sampleDistribution( smr, distribution, modes, decaySamplingInfo );
|
|
break;
|
|
case MCGIDI_distributionType_KalbachMann_e :
|
|
MCGIDI_KalbachMann_sampleEp( smr, distribution->KalbachMann, modes, decaySamplingInfo );
|
|
break;
|
|
case MCGIDI_distributionType_angularEnergy_e :
|
|
MCGIDI_angularEnergy_sampleDistribution( smr, distribution->angularEnergy, modes, decaySamplingInfo );
|
|
break;
|
|
default :
|
|
printf( "Unknown spectral data form product name = %s, channel genre = %d\n", product->pop->name, outputChannel->genre );
|
|
break;
|
|
}
|
|
break;
|
|
case MCGIDI_channelGenre_undefined_e :
|
|
printf( "Channel is undefined\n" );
|
|
break;
|
|
case MCGIDI_channelGenre_twoBodyDecay_e :
|
|
printf( "Channel is twoBodyDecay\n" );
|
|
break;
|
|
case MCGIDI_channelGenre_uncorrelatedDecay_e :
|
|
printf( "Channel is uncorrelatedDecay\n" );
|
|
break;
|
|
default :
|
|
printf( "Unsupported channel genre = %d\n", outputChannel->genre );
|
|
break;
|
|
}
|
|
if( !smr_isOk( smr ) ) return( -1 );
|
|
if( !secondTwoBody ) {
|
|
if( decaySamplingInfo->frame == xDataTOM_frame_centerOfMass ) {
|
|
if( MCGIDI_kinetics_COM2Lab( smr, modes, decaySamplingInfo, masses ) != 0 ) return( -1 );
|
|
}
|
|
productData[0].kineticEnergy = decaySamplingInfo->Ep;
|
|
p = std::sqrt( decaySamplingInfo->Ep * ( decaySamplingInfo->Ep + 2. * product->pop->mass_MeV ) );
|
|
if( productData[0].isVelocity ) p *= MCGIDI_speedOfLight_cm_sec / std::sqrt( p * p + product->pop->mass_MeV * product->pop->mass_MeV );
|
|
productData[0].pz_vz = p * decaySamplingInfo->mu;
|
|
p = std::sqrt( 1. - decaySamplingInfo->mu * decaySamplingInfo->mu ) * p;
|
|
phi = 2. * M_PI * decaySamplingInfo->rng( decaySamplingInfo->rngState );
|
|
productData[0].px_vx = p * std::sin( phi );
|
|
productData[0].py_vy = p * std::cos( phi );
|
|
MCGIDI_sampledProducts_addProduct( smr, productDatas, productData );
|
|
if( !smr_isOk( smr ) ) return( -1 );
|
|
}
|
|
} // Loop checking, 11.06.2015, T. Koi
|
|
}
|
|
}
|
|
}
|
|
return( productDatas->numberOfProducts );
|
|
}
|
|
|
|
#if defined __cplusplus
|
|
}
|
|
#endif
|
|
|