# <<BEGIN-copyright>>
# <<END-copyright>>
try :
from numericalFunctions import pointwiseXY_C as pointwiseXY_CModule
floatToShortestString = pointwiseXY_CModule.floatToShortestString
except :
from pqu import PQU as PQUModule
floatToShortestString = PQUModule.floatToShortestString
from PoPs import IDs as IDsPoPsModule
from xData import standards as standardsModule
from xData import axes as axesModule
from xData import constant as constantModule
from xData import XYs as XYsModule
from xData import series1d as series1dModule
from xData import regions as regionsModule
from xData import gridded as griddedModule
from xData import link as linkModule
from fudge.core.utilities import brb
from fudge.gnds import tokens as tokensModule
from fudge.gnds import abstractClasses as abstractClassesModule
from fudge.gnds.reactions import base as reactionBaseModule
__metaclass__ = type
energyDependentToken = 'energyDependent'
[docs]def defaultAxes( energyUnit ) :
axes = axesModule.axes( rank = 2 )
axes[0] = axesModule.axis( 'multiplicity', 0, '' )
axes[1] = axesModule.axis( 'energy_in', 1, energyUnit )
return( axes )
[docs]class unspecified( baseMultiplicityForm ) :
moniker = 'unspecified'
def __init__( self, label ) :
baseMultiplicityForm.__init__( self )
if( label is not None ) :
if( not( isinstance( label, str ) ) ) : raise TypeError( 'label must be a string' )
self.__label = label
[docs] def convertUnits( self, unitMap ) :
pass
[docs] def evaluate( self, E ) :
return( 0. )
[docs] def getXMLAttribute( self ) :
return( self.moniker )
@property
def label( self ) :
return( self.__label )
[docs] def toPointwise_withLinearXYs( self, **kwargs ) :
raise Exception( 'Linear-linear XYs1d data for multiplicity form %s does not make sense' % self.moniker )
[docs] def toXMLList( self, indent = '', **kwargs ) :
attributeStr = ''
if( self.label is not None ) : attributeStr += ' label="%s"' % self.label
return( [ '%s<%s%s/>' % ( indent, self.moniker, attributeStr ) ] )
[docs] @classmethod
def parseXMLNode( cls, element, xPath, linkData ):
xPath.append( element.tag )
val = cls( element.get('label') )
xPath.pop()
return val
[docs]class constant1d( baseMultiplicityForm, constantModule.constant1d ) :
def __init__( self, multiplicity, domainMin, domainMax, axes, label = None ) :
baseMultiplicityForm.__init__( self )
constantModule.constant1d.__init__( self, multiplicity, domainMin, domainMax, axes = axes, label = label )
[docs] def getEnergyLimits( self, EMin, EMax ) :
return( [ EMin, EMax ] )
[docs] def getXMLAttribute( self ) :
integer = int( self.constant )
if( self.constant == integer ) : return( integer )
return( floatToShortestString( self.constant ) )
[docs] def isConstant( self ) :
return( True )
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
return( self.toPointwise_withLinearXYs( accuracy = 1e-5, upperEps = 1e-8 ).processMultiGroup( style, tempInfo, indent ) )
[docs] def toPointwise_withLinearXYs( self, **kwargs ) :
"""This method returns the multiplicity as linear-linear XYs1d data which spans self's domain."""
return( XYs1d( data = [ [ self.domainMin, self.constant ], [ self.domainMax, self.constant ] ], axes = self.axes ) )
[docs]class XYs1d( baseMultiplicityForm, XYsModule.XYs1d ) :
def __init__( self, **kwargs ) :
baseMultiplicityForm.__init__( self )
XYsModule.XYs1d.__init__( self, **kwargs )
[docs] def getEnergyLimits( self, EMin, EMax ) :
return( self.domainMin, self.domainMax )
[docs] def evaluate( self, E ) :
if( E < self[0][0] ) : E = self[0][0]
if( E > self[-1][0] ) : E = self[-1][0]
return( XYsModule.XYs1d.evaluate( self, E ) )
[docs] def getXMLAttribute( self ) :
return( energyDependentToken )
[docs] def isConstant( self ) :
return self.rangeMin == self.rangeMax
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
from fudge.processing import miscellaneous as miscellaneousModule
if( tempInfo['verbosity'] > 2 ) : print('%sMulti-grouping XYs1d mutiplicity' % indent)
return( miscellaneousModule.groupFunctionCrossSectionAndFlux( gridded1d, style, tempInfo, self ) )
[docs]class regions1d( baseMultiplicityForm, regionsModule.regions1d ) :
def __init__( self, **kwargs ) :
baseMultiplicityForm.__init__( self )
regionsModule.regions1d.__init__( self, **kwargs )
[docs] def getEnergyLimits( self, EMin, EMax ) :
return( [ self[0][0][0], self[-1][-1][0] ] )
[docs] def evaluate( self, E ) :
if( E < self[0][0][0] ) : E = self[0][0][0]
for region in self :
if( E < region[-1][0] ) : break
return( region.evaluate( E ) )
[docs] def getXMLAttribute( self ) :
return( energyDependentToken )
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
return( self.toPointwise_withLinearXYs( accuracy = 1e-5, upperEps = 1e-8 ).processMultiGroup( style, tempInfo, indent ) )
[docs] def toPointwise_withLinearXYs( self, **kwargs ) :
"""See regionsXYs.toPointwise_withLinearXYs on the use of lowerEps, upperEps."""
kwargs['removeOverAdjustedPoints'] = True
xys = regionsModule.regions1d.toPointwise_withLinearXYs( self, **kwargs )
return( XYs1d( data = xys, axes = xys.axes ) )
[docs]class reference( linkModule.link, baseMultiplicityForm ) :
moniker = tokensModule.referenceFormToken
def __init__( self, link = None, root = None, path = None, label = None, relative = False ) :
linkModule.link.__init__( self, link = link, root = root, path = path, label = label, relative = relative )
baseMultiplicityForm.__init__( self )
@property
def reference( self ):
if self.link is None:
raise Exception("Unresolved link!")
return self.link
@property
def domainMin( self ) :
return( self.reference.domainMin )
@property
def domainMax( self ) :
return( self.reference.domainMax )
@property
def domainUnit( self ) :
return( self.reference.domainUnit )
[docs] def convertUnits( self, unitMap ) :
pass
[docs] def getEnergyLimits( self, EMin, EMax ) :
return( self.reference.getEnergyLimits( EMin, EMax ) )
[docs] def evaluate( self, E ) :
return( self.reference.evaluate( E ) )
[docs] def toPointwise_withLinearXYs( self, **kwargs ) :
return( self.reference.toPointwise_withLinearXYs( **kwargs ) )
[docs] def getXMLAttribute( self ) :
return( self.reference.getXMLAttribute( ) )
[docs]class polynomial( baseMultiplicityForm, series1dModule.polynomial1d ) :
def __init__( self, **kwargs ) :
baseMultiplicityForm.__init__( self )
series1dModule.polynomial1d.__init__( self, **kwargs )
@property
def domainUnit( self ) :
return( self.findClassInAncestry( reactionBaseModule.base_reaction ).domainUnit )
[docs] def getEnergyLimits( self, EMin, EMax ) :
return( [ EMin, EMax ] )
[docs] def getXMLAttribute( self ) :
return( energyDependentToken )
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
return( self.toPointwise_withLinearXYs( accuracy = 1e-5, upperEps = 1e-8 ).processMultiGroup( style, tempInfo, indent ) )
[docs] def toPointwise_withLinearXYs( self, **kwargs ) :
xys = series1dModule.polynomial1d.toPointwise_withLinearXYs( self, accuracy = 1e-6 )
return( XYs1d( data = xys, axes = self.axes ) )
[docs]class partialProduction( baseMultiplicityForm ) :
moniker = tokensModule.partialProductionFormToken
def __init__( self, label, data = 1 ) :
baseMultiplicityForm.__init__( self )
self.data = data
if( label is not None ) :
if( not( isinstance( label, str ) ) ) : raise TypeError( 'label must be a string' )
self.__label = label
[docs] def evaluate( self, E ) :
return( self.data )
[docs] def getXMLAttribute( self ) :
return( tokensModule.partialProductionFormToken )
@property
def label( self ) :
return( self.__label )
[docs] def toPointwise_withLinearXYs( self, **kwargs ) :
brb.objectoutline( self.data )
raise 'Hell'
[docs] def toXMLList( self, indent = '', **kwargs ) :
attributeStr = ''
if( self.label is not None ) : attributeStr += ' label="%s"' % self.label
return( [ '%s<%s%s value="%s"/>' % ( indent, self.moniker, attributeStr, self.data ) ] )
[docs] @staticmethod
def parseXMLNode( element, xPath, linkData ) :
xPath.append( element.tag )
label = element.get( 'label' )
mult = float( element.get( 'value' ) )
if( mult.is_integer( ) ) : mult = int( mult )
multiplicity = partialProduction( label, mult )
xPath.pop( )
return( multiplicity )
[docs]class gridded1d( baseMultiplicityForm, griddedModule.gridded1d ) :
def __init__( self, **kwargs ) :
baseMultiplicityForm.__init__( self )
griddedModule.gridded1d.__init__( self, **kwargs )
[docs] def getXMLAttribute( self ) :
return( energyDependentToken )
[docs]class branching1d( baseMultiplicityForm ) :
moniker = 'branching1d'
def __init__( self, label ) :
baseMultiplicityForm.__init__( self )
self.__label = label
@property
def label( self ) :
return( self.__label )
[docs] def convertUnits( self, unitMap ) :
pass
[docs] def processMultiGroup( self, style, tempInfo, indent ) :
def countGammas( product, probability ) :
count = 0.0
for decayMode in product.decayData.decayModes :
branchingRatio = decayMode.probability[0].value * probability
count += branchingRatio
decayPath = decayMode.decayPath[0]
residual = decayPath.products[0].pid
if( residual == IDsPoPsModule.photon ) : residual = decayPath.products[1].pid
count += countGammas( PoPs[residual], branchingRatio )
return( count )
verbosity = tempInfo['verbosity']
indent2 = indent + tempInfo['incrementalIndent']
productLabel = tempInfo['productLabel']
crossSection = tempInfo['crossSection']
domainMin = crossSection.domainMin
domainMax = crossSection.domainMax
PoPs = tempInfo['reactionSuite'].PoPs
distribution = self.ancestor.ancestor.distribution[0]
nuclide = PoPs[distribution.pids.initial]
multipliticy = countGammas( nuclide, 1.0 )
multipliticy = XYs1d( data = [ [ domainMin, multipliticy ], [ domainMax, multipliticy ] ], axes = defaultAxes( tempInfo['incidentEnergyUnit'] ) )
return( multipliticy.processMultiGroup( style, tempInfo, indent ) )
[docs] def toXMLList( self, indent = '', **kwargs ) :
attributeStr = ''
if( self.label is not None ) : attributeStr += ' label="%s"' % self.label
return( [ '%s<%s%s/>' % ( indent, self.moniker, attributeStr ) ] )
[docs] @staticmethod
def parseXMLNode( element, xPath, linkData ) :
xPath.append( element.tag )
multiplicity = branching1d( element.get( 'label' ) )
xPath.pop( )
return( multiplicity )
[docs]def parseXMLNode( multElement, xPath, linkData ) :
"""Translate an xml <multiplicity> element into fudge."""
xPath.append( multElement.tag )
multiplicityComponent = component( )
formClasses = {}
for formClass in [ unspecified, constant1d, XYs1d, regions1d, reference, polynomial, partialProduction, gridded1d, branching1d ] :
formClasses[formClass.moniker] = formClasses
for form in multElement :
formClass = formClasses.get( form.tag )
if( formClass is None ) : raise Exception( "encountered unknown multiplicity form: %s" % form.tag )
newForm = formClass.parseXMLNode( form, xPath, linkData )
multiplicityComponent.add( newForm )
xPath.pop( )
return( multiplicityComponent )
#
# multiplicity component
#
[docs]class component( abstractClassesModule.component ) :
moniker = 'multiplicity'
def __init__( self ) :
abstractClassesModule.component.__init__( self, ( unspecified, constant1d, XYs1d, regions1d, reference, polynomial,
partialProduction, gridded1d, branching1d ) )
[docs] def isConstant( self ) :
return( isinstance( self.evaluated, constant1d ) )
[docs] def getConstant( self ) :
if( self.isConstant() ) : return( self.evaluated.evaluate( 0 ) )
raise Exception( 'multiplicity type = "%s" is not single valued' % self.evaluated.moniker )
@property
def domainMin( self ) :
return( self.evaluated.domainMin )
@property
def domainMax( self ) :
return( self.evaluated.domainMax )
@property
def domainUnit( self ) :
return( self.evaluated.domainUnit )
[docs] def getEnergyLimits( self, EMin, EMax ) :
return( self.evaluated.getEnergyLimits( EMin, EMax ) )
[docs] def evaluate( self, E ) :
return( self.evaluated.evaluate( E ) )
[docs] def check( self, info ):
from fudge.gnds import warning
warnings = []
if self.isConstant():
if self.getConstant() < 1:
warnings.append( warning.negativeMultiplicity( self.getConstant(), self ) )
else: # energy-dependent mult.
for form in self :
domain = None
if hasattr(form, 'domain') :
domain = form.domainMin, form.domainMax
if( ( domain is not None ) and ( domain != info['crossSectionDomain'] ) ) :
# photon multiplicities can start above cross section domainMin, but domainMax should agree:
if( self.ancestor.id == IDsPoPsModule.photon ) :
startRatio = domain[0] / info['crossSectionDomain'][0]
endRatio = domain[1] / info['crossSectionDomain'][1]
if (startRatio < 1 - standardsModule.floats.epsilon or endRatio < 1 - standardsModule.floats.epsilon
or endRatio > 1 + standardsModule.floats.epsilon):
warnings.append(warning.domain_mismatch(
*(domain + info['crossSectionDomain']), obj=self))
# For all other products, both domainMin and domainMax should agree within epsilon
else:
for idx, (e1, e2) in enumerate(zip(domain, info['crossSectionDomain'])):
ratio = e1 / e2
if (ratio < 1 - standardsModule.floats.epsilon or ratio > 1 + standardsModule.floats.epsilon):
if ( idx==0 and domain[0] > info['crossSectionDomain'][0] and form.evaluate( domain[0] ) == 0 ):
continue # multiplicity starting after xsc is ok if first multiplicity point == 0
warnings.append(warning.domain_mismatch( *(domain + info['crossSectionDomain']), obj=self))
break
if hasattr(form, 'rangeMin') and form.rangeMin < 0:
warnings.append( warning.negativeMultiplicity( form.rangeMin, obj=form ) )
return warnings
[docs] def getXMLAttribute( self ) :
return( self.evaluated.getXMLAttribute( ) )