Source code for fudge.gnds.productData.distributions.angularEnergy
# <<BEGIN-copyright>>
# <<END-copyright>>
from __future__ import print_function
"""Angular/energy double differential distribution classes."""
import math
from PoPs import IDs as IDsPoPsModule
from xData import standards as standardsModule
from xData import axes as axesModule
from xData import XYs as XYsModule
from xData import multiD_XYs as multiD_XYsModule
from fudge.processing import group as groupModule
from fudge.gnds.productData import momentumDeposition as momentumDepositionModule
from . import miscellaneous as miscellaneousModule
from . import base as baseModule
from . import angular as angularModule
from . import angularEnergyMC as angularEnergyMCModule
__metaclass__ = type
[docs]def defaultAxes( energyUnit, probabilityLabel = 'P(mu,energy_out|energy_in)' ) :
axes = axesModule.axes( rank = 4 )
axes[3] = axesModule.axis( 'energy_in', 3, energyUnit )
axes[2] = axesModule.axis( 'mu', 2, '' )
axes[1] = axesModule.axis( 'energy_out', 1, energyUnit )
axes[0] = axesModule.axis( probabilityLabel, 0, '1/' + energyUnit )
return( axes )
[docs]class XYs2d( multiD_XYsModule.XYs2d ) :
[docs] def averageEnergy( self ) :
EpOfMu = [ [ pdfOfEpAtMu.value, pdfOfEpAtMu.averageEnergy( ) ] for pdfOfEpAtMu in self ]
return( float( XYsModule.XYs1d( EpOfMu ).integrate( ) ) )
[docs] def averageMomentum( self ) :
MpOfMu = [ [ pdfOfMpAtMu.value, pdfOfMpAtMu.averageMomentum( ) ] for pdfOfMpAtMu in self ]
return( float( XYsModule.XYs1d( MpOfMu ).integrate( ) ) )
[docs]class XYs3d( subform, multiD_XYsModule.XYs3d ) :
def __init__( self, **kwargs ) :
multiD_XYsModule.XYs3d.__init__( self, **kwargs )
subform.__init__( self )
[docs] def check( self, info ) :
"""
Check for incomplete angular distributions + any negative probabilities.
Ignore normalization for this double-differential distribution.
"""
from fudge.gnds import warning
from pqu import PQU
warnings = []
for index, energy_in in enumerate(self):
integral = energy_in.integrate()
if abs(integral - 1.0) > info['normTolerance']:
warnings.append( warning.unnormalizedDistribution( PQU.PQU(energy_in.value, self.axes[0].unit),
index, integral, self.toXLink() ) )
if( energy_in.domainMin != -1 ) or ( energy_in.domainMax != 1 ) :
warnings.append( warning.incompleteDistribution( PQU.PQU(energy_in.value, self.axes[0].unit),
energy_in.domainMin, energy_in.domainMax, energy_in ) )
for mu in energy_in:
if( mu.domainMin < 0 ) :
warnings.append( warning.valueOutOfRange("Negative outgoing energy for energy_in=%s!"
% PQU.PQU(energy_in.value, self.axes[0].unit), mu.domainMin, 0, 'inf', self.toXLink() ) )
if( mu.rangeMin < 0 ) :
warnings.append( warning.negativeProbability( PQU.PQU(energy_in.value, self.axes[-1].unit),
mu=mu.value, obj=mu ) )
return warnings
[docs] def calculateAverageProductData( self, style, indent = '', **kwargs ) :
multiplicity = kwargs['multiplicity']
productMass = kwargs['productMass']
aveEnergy = []
for pdfOfMuEpAtE in self :
energy = pdfOfMuEpAtE.value
aveEnergy.append( [ energy, multiplicity.evaluate( energy ) * pdfOfMuEpAtE.averageEnergy( ) ] )
const = math.sqrt( 2. * productMass )
aveMomentum = []
for pdfOfMuEpAtE in self :
energy = pdfOfMuEpAtE.value
momemtum = const * multiplicity.evaluate( energy ) * pdfOfMuEpAtE.averageMomentum( )
if( momemtum < 1e-12 ) : momemtum = 0. # This should be less arbitrary????????
aveMomentum.append( [ energy, momemtum ] )
return( aveEnergy, aveMomentum )
[docs] def normalize( self, insitu = True ) :
n = self
if( not( insitu ) ) : n = self.copy( )
for E_MuEpPs in n :
sum = E_MuEpPs.integrate( )
for muEpPs in E_MuEpPs : muEpPs.setData( muEpPs / sum )
return( n )
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
from fudge.processing.deterministic import transferMatrices as transferMatricesModule
verbosity = tempInfo['verbosity']
productFrame = tempInfo['productFrame']
if( verbosity > 2 ) : print('%sGrouping %s' % (indent, self.moniker))
TM_1, TM_E = transferMatricesModule.ENDFEMuEpP_TransferMatrix( style, tempInfo, productFrame, tempInfo['crossSection'], self,
tempInfo['multiplicity'], comment = tempInfo['transferMatrixComment'] + ' outgoing data for %s' % tempInfo['productLabel'] )
return( groupModule.TMs2Form( style, tempInfo, TM_1, TM_E ) )
[docs] def to_xs_pdf_cdf1d( self, style, tempInfo, indent ) :
angular = angularModule.XYs2d( axes = self.axes )
for PofEpGivenMu in self :
data = angularModule.XYs1d( [ [ PofEp.value, float( PofEp.integrate( ) ) ] for PofEp in PofEpGivenMu ] )
angular.append( angularModule.xs_pdf_cdf1d.fromXYs( angularModule.XYs1d( data ),
value = PofEpGivenMu.value ) )
xys3d = angularEnergyMCModule.XYs3d( axes = self.axes )
for PofEpGivenMu in self :
xys2d = angularEnergyMCModule.XYs2d( value = PofEpGivenMu.value )
for PofEp in PofEpGivenMu :
_PofEp = PofEp.toPointwise_withLinearXYs( accuracy = 1e-3, upperEps = 1e-8 )
xys2d.append( angularEnergyMCModule.xs_pdf_cdf1d.fromXYs( _PofEp, PofEp.value ) )
xys3d.append( xys2d )
return( angularEnergyMCModule.angular( angular ), angularEnergyMCModule.angularEnergy( xys3d ) )
[docs]class LLNLAngularOfAngularEnergySubform( baseModule.subform ) :
moniker = 'LLNLAngularOfAngularEnergy'
def __init__( self, data ) :
if( not( isinstance( data, angularModule.XYs2d ) ) ) : raise TypeError( 'instance is not an angular.XYs2d' )
baseModule.subform.__init__( self )
self.data = data
[docs] def convertUnits( self, unitMap ) :
"See documentation for reactionSuite.convertUnits."
self.data.convertUnits( unitMap )
[docs] def to_xs_pdf_cdf1d( self, style, tempInfo, indent ) :
return( angularEnergyMCModule.angular( self.data.to_xs_pdf_cdf1d( style, tempInfo, indent ) ) )
[docs] def toXMLList( self, indent = "", **kwargs ) :
indent2 = indent + kwargs.get( 'incrementalIndent', ' ' )
xmlStringList = [ '%s<%s>' % ( indent, self.moniker ) ]
xmlStringList += self.data.toXMLList( indent = indent2, **kwargs )
xmlStringList[-1] += '</%s>' % self.moniker
return( xmlStringList )
[docs] @staticmethod
def parseXMLNode( element, xPath, linkData ) :
xPath.append( element.tag )
data = angularModule.XYs2d.parseXMLNode( element[0], xPath, linkData )
result = LLNLAngularOfAngularEnergySubform( data )
xPath.pop( )
return( result )
[docs]class LLNLAngularEnergyOfAngularEnergySubform( baseModule.subform ) :
moniker = 'LLNLAngularEnergyOfAngularEnergy'
def __init__( self, data ) :
if( not( isinstance( data, XYs3d ) ) ) : raise TypeError( 'instance is not an angularEnergy.XYs3d' )
baseModule.subform.__init__( self )
self.data = data
[docs] def convertUnits( self, unitMap ) :
"See documentation for reactionSuite.convertUnits."
self.data.convertUnits( unitMap )
[docs] def to_xs_pdf_cdf1d( self, style, tempInfo, indent ) :
return( self.data.to_xs_pdf_cdf1d( style, tempInfo, indent ) )
[docs] def toXMLList( self, indent = "", **kwargs ) :
indent2 = indent + kwargs.get( 'incrementalIndent', ' ' )
xmlStringList = [ '%s<%s>' % ( indent, self.moniker ) ]
xmlStringList += self.data.toXMLList( indent = indent2, **kwargs )
xmlStringList[-1] += '</%s>' % self.moniker
return( xmlStringList )
[docs] @staticmethod
def parseXMLNode( element, xPath, linkData ) :
xPath.append( element.tag )
data = XYs3d.parseXMLNode( element[0], xPath, linkData )
result = LLNLAngularEnergyOfAngularEnergySubform( data )
xPath.pop( )
return( result )
[docs]class LLNLAngularEnergyForm( baseModule.form ) :
"""This class is for legacy LLNL ENDL I = 1 and 3 data and is deprecated. Only use for the legacy ENDL data."""
moniker = 'LLNLAngularEnergy'
subformAttributes = ( 'angularSubform', 'angularEnergySubform' )
def __init__( self, label, productFrame, angularSubform, angularEnergySubform ) :
if( not( isinstance( angularSubform, LLNLAngularOfAngularEnergySubform ) ) ) :
raise TypeError( 'instance is not an LLNLAngularOfAngularEnergySubform subform' )
if( not( isinstance( angularEnergySubform, LLNLAngularEnergyOfAngularEnergySubform ) ) ) :
raise TypeError( 'instance is not an LLNLAngularEnergyOfAngularEnergySubform subform' )
baseModule.form.__init__( self, label, productFrame, ( angularSubform, angularEnergySubform ) )
[docs] def calculateAverageProductData( self, style, indent = '', **kwargs ) :
def calculateDepositionMomentumAtMu( mu, parameters ) :
f = ( mu - parameters.mu1 ) / ( parameters.mu2 - parameters.mu1 )
P_mu = ( 1 - f ) * parameters.P1 + f * parameters.P2
EpP = parameters.muEpPs.interpolateAtValue( mu, unitBase = True, extrapolation = standardsModule.flatExtrapolationToken )
Ep = EpP.integrateWithWeight_sqrt_x( )
return( mu * P_mu * Ep )
def calculateDepositionMomentum( muPs, muEpPs ) :
class LLNLAngular_angularEnergy_MomentumParameters :
def __init__( self, mu1, P1, mu2, P2, muEpPs ) :
self.mu1, self.P1, self.mu2, self.P2, self.muEpPs = mu1, P1, mu2, P2, muEpPs
def nextMu( self, m2, P2 ) :
self.mu1, self.P1 = self.mu2, self.P2
self.mu2, self.P2 = mu2, P2
parameters = LLNLAngular_angularEnergy_MomentumParameters( 0, 0, 0, 0, muEpPs )
mu1, p = None, 0
for mu2, P2 in muPs :
parameters.nextMu( mu2, P2 )
if( mu1 is not None ) :
p += miscellaneousModule.GnG_adaptiveQuadrature( calculateDepositionMomentumAtMu, mu1, mu2, parameters,
miscellaneousModule.GaussQuadrature2, tolerance = 1e-4 )[0]
mu1 = mu2
return( p )
class calculateDepositionMomentumThicken :
def __init__( self, angularSubform, angularEnergySubform, relativeTolerance, absoluteTolerance ) :
self.angularSubform = angularSubform
self.angularEnergySubform = angularEnergySubform
self.relativeTolerance = relativeTolerance
self.absoluteTolerance = absoluteTolerance
def evaluateAtX( self, E ) :
muPs = self.angularSubform.getAtEnergy( E )
muEpPs = self.angularEnergySubform.interpolateAtV( E, unitBase = True )
return( calculateDepositionMomentum( muPs, muEpPs ) )
energyUnit = kwargs['incidentEnergyUnit']
momentumDepositionUnit = kwargs['momentumDepositionUnit']
multiplicity = kwargs['multiplicity']
energyAccuracy = kwargs['energyAccuracy']
momentumAccuracy = kwargs['momentumAccuracy']
product = kwargs['product']
productMass = kwargs['productMass']
angularSubform = self.angularSubform.data
angularEnergySubform = self.angularEnergySubform.data
depEnergy = miscellaneousModule.calculateDepositionEnergyFromAngular_angularEnergy( style,
angularSubform, angularEnergySubform, multiplicity, accuracy = energyAccuracy )
if( product.id == IDsPoPsModule.photon ) :
depMomentum = miscellaneousModule.calculateDepositionEnergyFromAngular_angularEnergy( style,
angularSubform, angularEnergySubform, multiplicity, True, accuracy = momentumAccuracy )
else :
depMomentum = []
for indexE, muPs in enumerate( angularSubform ) :
depMomentum.append( [ muPs.value, calculateDepositionMomentum( muPs, angularEnergySubform[indexE] ) ] )
const = math.sqrt( 2. * productMass )
for EMomenutem in depMomentum : EMomenutem[1] *= const * multiplicity.evaluate( EMomenutem[0] )
axes = momentumDepositionModule.defaultAxes( energyUnit = energyUnit, momentumDepositionUnit = momentumDepositionUnit )
depMomentum = momentumDepositionModule.XYs1d( data = depMomentum, axes = axes,
label = style.label )
return( [ depEnergy ], [ depMomentum ] )
[docs] def convertUnits( self, unitMap ) :
"See documentation for reactionSuite.convertUnits."
self.angularSubform.convertUnits( unitMap )
self.angularEnergySubform.convertUnits( unitMap )
[docs] def processMC_cdf( self, style, tempInfo, indent ) :
angular = self.angularSubform.to_xs_pdf_cdf1d( style, tempInfo, indent )
dummy, angularEnergy = self.angularEnergySubform.to_xs_pdf_cdf1d( style, tempInfo, indent )
return( angularEnergyMCModule.form( style.label, self.productFrame, angular, angularEnergy ) )
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
from fudge.processing.deterministic import transferMatrices as transferMatricesModule
verbosity = tempInfo['verbosity']
if( verbosity > 2 ) : print('%sGrouping %s' % (indent, self.moniker))
angularSubform = self.angularSubform.data
angularEnergySubform = self.angularEnergySubform.data
TM_1, TM_E = transferMatricesModule.ENDLEMuEpP_TransferMatrix( style, tempInfo, tempInfo['crossSection'], self.productFrame,
angularSubform, angularEnergySubform, tempInfo['multiplicity'],
comment = tempInfo['transferMatrixComment'] + ' outgoing data for %s' % tempInfo['productLabel'] )
return( groupModule.TMs2Form( style, tempInfo, TM_1, TM_E ) )
[docs] def toXMLList( self, indent = "", **kwargs ) :
indent2 = indent + kwargs.get( 'incrementalIndent', ' ' )
indent3 = indent + kwargs.get( 'incrementalIndent', ' ' )
attributeStr = ''
if( self.label is not None ) : attributeStr += ' label="%s"' % self.label
if( self.productFrame is not None ) : attributeStr += ' productFrame="%s"' % self.productFrame
xmlString = [ '%s<%s%s>' % ( indent, self.moniker, attributeStr ) ]
xmlString += self.angularSubform.toXMLList( indent3, **kwargs )
xmlString += self.angularEnergySubform.toXMLList( indent3, **kwargs )
xmlString[-1] += '</%s>' % self.moniker
return( xmlString )
[docs] @staticmethod
def parseXMLNode( element, xPath, linkData ) :
xPath.append( element.tag )
for child in element :
if( child.tag == LLNLAngularOfAngularEnergySubform.moniker ) :
angularSubform = LLNLAngularOfAngularEnergySubform.parseXMLNode( child, xPath, linkData )
elif( child.tag == LLNLAngularEnergyOfAngularEnergySubform.moniker ) :
angularEnergySubform = LLNLAngularEnergyOfAngularEnergySubform.parseXMLNode( child, xPath, linkData )
else :
raise ValueError( 'Encountered unexpected child element "%s"' % child.tag )
component = LLNLAngularEnergyForm( element.get( 'label' ), element.get( 'productFrame' ),
angularSubform, angularEnergySubform )
xPath.pop( )
return( component )
[docs]class form( baseModule.form ) :
moniker = 'angularEnergy'
subformAttributes = ( 'angularEnergySubform', )
ancestryMembers = subformAttributes
def __init__( self, label, productFrame, angularEnergySubform ) :
if( not( isinstance( angularEnergySubform, subform ) ) ) : raise TypeError( 'instance is not an angularEnergy subform' )
baseModule.form.__init__( self, label, productFrame, ( angularEnergySubform, ) )
[docs] def calculateAverageProductData( self, style, indent = '', **kwargs ) :
if( self.productFrame == standardsModule.frames.centerOfMassToken ) :
raise Exception( 'center of mass calculation not supported for %s' % self.moniker )
kwargs['productFrame'] = self.productFrame
aveEnergy, aveMomentum = self.angularEnergySubform.calculateAverageProductData( style, indent = indent, **kwargs )
return( [ aveEnergy ], [ aveMomentum ] )
[docs] def convertUnits( self, unitMap ) :
"See documentation for reactionSuite.convertUnits."
self.angularEnergySubform.convertUnits( unitMap )
[docs] def processMC_cdf( self, style, tempInfo, indent ) :
angular, angularEnergy = self.angularEnergySubform.to_xs_pdf_cdf1d( style, tempInfo, indent )
return( angularEnergyMCModule.form( style.label, self.productFrame, angular, angularEnergy ) )
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
tempInfo['productFrame'] = self.productFrame
return( self.angularEnergySubform.processMultiGroup( style, tempInfo, indent ) )
[docs] @staticmethod
def parseXMLNode( element, xPath, linkData ):
xPath.append( element.tag )
formElement = element[0]
subformClass = {
XYs3d.moniker : XYs3d,
}[ formElement.tag ]
if subformClass is None: raise Exception("encountered unknown angularEnergy subform: %s" % formElement.tag)
subform = XYs3d.parseXMLNode( formElement, xPath, linkData )
AEC = form( element.get( 'label' ), element.get('productFrame'), subform )
xPath.pop()
return AEC