Source code for fudge.gnds.productData.multiplicity

# <<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 baseMultiplicityForm( abstractClassesModule.form ) : pass
[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( ) )