def toPointwise_withLinearXYs(self, accuracy=None, lowerEps=0, upperEps=0, invert=False): eps = 1e-6 ptw = XYs2d(XYs2d.defaultAxes(energyUnit=self.domainUnit())) if (invert): ptw.append( XYsModule.XYs1d([[-1, 2 / eps], [eps - 1, 0.]], value=self.domainMin(), accuracy=1e-6)) ptw.append( XYsModule.XYs1d([[-1, 2 / eps], [eps - 1, 0.]], value=self.domainMax(), accuracy=1e-6)) else: ptw.append( XYsModule.XYs1d([[1 - eps, 0.], [1, 2 / eps]], value=self.domainMin(), accuracy=1e-6)) ptw.append( XYsModule.XYs1d([[1 - eps, 0.], [1, 2 / eps]], value=self.domainMax(), accuracy=1e-6)) return (ptw)
def gammaDeltaDistribution(energy): deltaEnergy = float("1e%s" % ("%.0e" % (energy * energyEps)).split('e')[1]) eMin, eMax = energy - deltaEnergy, energy + deltaEnergy if (eMin < 0): return (XYsModule.XYs([[energy, 1.], [eMax, 0.]]).normalize()) return (XYsModule.XYs([[eMin, 0.], [energy, 1], [eMax, 0.]]).normalize())
def KalbachMannDataToString( KalbachMannData, energy_in_unit ) : nForm = 4 if( KalbachMannData.aSubform.data is None ) : nForm = 3 if( nForm == 4 ) : raise Exception( 'This is currently not implemented' ) fSubform = KalbachMannData.fSubform.data rSubform = KalbachMannData.rSubform.data factor = fSubform.domainUnitConversionFactor( energy_in_unit ) # Energies passed to get_transfer must be in energy_in_unit, traditionally MeV. _fSubform = multiD_XYsModule.XYs2d( ) for xys in fSubform : _xys = XYsModule.XYs1d( data = xys.scaleOffsetXAndY( xScale = factor, yScale = 1 / factor ), value = factor * xys.value ) _fSubform.append( _xys ) _rSubform = multiD_XYsModule.XYs2d( ) for xys in rSubform : _xys = XYsModule.XYs1d( data = xys.scaleOffsetXAndY( xScale = factor ), value = factor * xys.value ) _rSubform.append( _xys ) s = startOfNewData s += "Kalbach probabilities: n = %s\n" % len( _fSubform ) s += "Incident energy interpolation: %s %s\n" % ( linlin, GND2ProcessingInterpolationQualifiers[standardsModule.interpolation.unitBaseToken] ) s += "Outgoing energy interpolation: %s\n" % fSubform[0].interpolation s += threeDListToString( _fSubform ) s += "Kalbach r parameter: n = %s\n" % len( rSubform ) s += "Incident energy interpolation: %s %s\n" % ( rSubform.interpolation, GND2ProcessingInterpolationQualifiers[standardsModule.interpolation.unitBaseUnscaledToken] ) s += "Outgoing energy interpolation: %s\n" % rSubform[0].interpolation s += threeDListToString( _rSubform ) return( s )
def divideIgnoring0DividedBy0(self, other): if (isinstance(self, XYsModule.XYs1d) and isinstance(other, XYsModule.XYs1d)): d = self.union( other.domainSlice(domainMin=self.domainMin, domainMax=self.domainMax)) result = [] for p in d: vp = other.evaluate(p[0]) if (vp == 0): if (p[1] != 0): raise Exception( 'Divide non-zero number by zero at %e' % p[0]) else: p[1] = p[1] / vp result.append([p[0], p[1]]) return (XYsModule.pointwiseXY(data=result)) elif (isinstance(self, regionsModule.regions1d) and isinstance(other, regionsModule.regions1d) and len(self) == len(other)): regions = regionsModule.regions1d() for idx in range(len(self)): regions.append( XYsModule.XYs1d( data=divideIgnoring0DividedBy0(self[idx], other[idx]))) return regions else: raise NotImplementedError('Divide XYs1d by regions or vice-versa')
def toPointwise_withLinearXYs(self, **kwargs): accuracy = xDataBaseModule.getArguments(kwargs, {'accuracy': 1e-6})['accuracy'] ptw = XYs2d(defaultAxes(self.domainUnit)) ptw.append( XYsModule.XYs1d([[1 - accuracy, 0.], [1, 2 / accuracy]], value=self.domainMin)) ptw.append( XYsModule.XYs1d([[1 - accuracy, 0.], [1, 2 / accuracy]], value=self.domainMax)) return (ptw)
def averageForwardMomentum(self, sqrt_2_ProductMass): averageMu = [[pdfOfMuAtEp.value, pdfOfMuAtEp.averageMu()] for pdfOfMuAtEp in self] return (sqrt_2_ProductMass * float( XYsModule.XYs1d(averageMu, interpolation=self.interpolation). integrateWithWeight_sqrt_x()))
def calculateMomentumPoints( massInE, EMin, EMax, energyUnit, accuracy = 1e-4 ) : """ This is a temporary function (hopefully) to calculate momentum vs E. What is really needed is a function like rriint in mcfgen. """ import math momentum = [] def insertPointIfNeeded( Ep1, Ep2 ) : E1, p1 = Ep1 E2, p2 = Ep2 s = ( p2 - p1 ) / ( E2 - E1 ) Em = massInE / ( 2. * s * s ) pc = math.sqrt( 2 * massInE * Em ) pi = s * ( Em - E1 ) + p1 if( abs( pi / pc - 1 ) > accuracy ) : m = [ Em, pc ] momentum.append( m ) insertPointIfNeeded( Ep1, m ) insertPointIfNeeded( m, Ep2 ) if( massInE == 0 ) : # gammas momentum.append( [ EMin, EMin ] ) momentum.append( [ EMax, EMax ] ) else : momentum.append( [ EMin, math.sqrt( 2 * massInE * EMin ) ] ) momentum.append( [ EMax, math.sqrt( 2 * massInE * EMax ) ] ) insertPointIfNeeded( momentum[0], momentum[1] ) momentum.sort( ) axes = axesModule.axes( labelsUnits = { 0 : [ 'energy_in', energyUnit ], 1 : [ 'momentum', energyUnit + '/c' ] } ) return( XYsModule.XYs1d( data = momentum, axes = axes, accuracy = accuracy ) )
def getW_XYs(self): from xData import axes as axesModule from xData import XYs as XYsModule from xData import multiD_XYs as multiD_XYsModule xUnit, yUnit, zUnit = '', '', '' if (self.xUnit is not None): xUnit = self.xUnit if (self.yUnit is not None): yUnit = self.yUnit if (self.zUnit is not None): zUnit = self.zUnit axes_3d = axesModule.axes(3) axes_3d[0] = axesModule.axis('z', 0, zUnit) axes_3d[1] = axesModule.axis('y', 0, yUnit) axes_3d[2] = axesModule.axis('x', 0, xUnit) w_xys = multiD_XYsModule.multiD_XYs(axes=axes_3d) axes_2d = axesModule.axes() axes_2d[0] = axes_3d[0] axes_2d[1] = axes_3d[1] for ix, x in enumerate(self.x): xys = [[y, self.z[iy][ix]] for iy, y in enumerate(self.y)] w_xys[ix] = XYsModule.XYs(xys, axes=axes_2d, accuracy=1e-3, value=x) return (w_xys)
def getFluxAtLegendreOrder(self, order): axes = axesModule.axes() axes[1] = self.axes[2].copy([]) axes[0] = self.axes[0].copy([]) for LS in self: if (len(LS) > 1): raise Exception('FIXME -- next line is wrong.') return (XYsModule.XYs1d([[LS.value, LS[0]] for LS in self], axes=axes))
def averageEnergy(self): integralOfMu = [[pdfOfMuAtEp.value, pdfOfMuAtEp.integrate()] for pdfOfMuAtEp in self] return (float( XYsModule.XYs1d( integralOfMu, interpolation=self.interpolation).integrateWithWeight_x()))
def energyFunctionToString( energyData, weight = None ) : def getParameter( data, label ) : _linlin = data.toPointwise_withLinearXYs( lowerEps = lowerEps, upperEps = upperEps ) sData = [ startOfNewData, "%s: n = %d" % ( label, len( _linlin ) ) ] sData.append( 'Interpolation: %s' % linlin ) for x, y in _linlin : sData.append( '%s %s' % ( x, y ) ) return( sData ) sData = [] if( isinstance( energyData, ( energyModule.simpleMaxwellianFissionSpectrum, energyModule.evaporationSpectrum, energyModule.WattSpectrum ) ) ) : sData.append( 'U: %s' % energyData.U.getValueAs( energyData.parameter1.data.axes[-1].unit ) ) parameter1 = energyData.parameter1.data.toPointwise_withLinearXYs( accuracy = 1e-5, lowerEps = lowerEps, upperEps = upperEps ) if( energyData.parameter2 is not None ) : parameter2 = energyData.parameter2.data.toPointwise_withLinearXYs( accuracy = 1e-5, lowerEps = lowerEps, upperEps = upperEps ) if( weight is None ) : axes = axesModule.axes( ) weight = XYsModule.XYs1d( data = [ [ parameter1.domainMin, 1. ], [ parameter1.domainMax, 1. ] ], axes = axes ) else : weight = weight.weight sData += twoDToString( "weight", weight, addExtraBlankLine = False ) if( isinstance( energyData, energyModule.generalEvaporationSpectrum ) ) : sProcess = 'Process: general evaporation\n' sSpecific = '' sData += getParameter( parameter1, 'Theta' ) sData += getParameter( parameter2, 'g' ) elif( isinstance( energyData, energyModule.simpleMaxwellianFissionSpectrum ) ) : sProcess = 'Process: Maxwell spectrum\n' sSpecific = '' sData += getParameter( parameter1, 'Theta' ) elif( isinstance( energyData, energyModule.evaporationSpectrum ) ) : sProcess = 'Process: Evaporation spectrum\n' sSpecific = 'Interpolate Eout integrals: false\n' sSpecific += 'Quadrature method: Gauss6\n' sData += getParameter( parameter1, 'Theta' ) elif( isinstance( energyData, energyModule.WattSpectrum ) ) : sProcess = 'Process: Watt spectrum\n' sSpecific = 'Interpolate Eout integrals: false\n' sSpecific += 'Conserve: number\n' sData += getParameter( parameter1, 'a' ) sData += getParameter( parameter2, 'b' ) elif( isinstance( energyData, energyModule.MadlandNix ) ) : sProcess = 'Process: Madland-Nix spectrum\n' sSpecific = 'Quadrature method: adaptive\n' sSpecific += 'Interpolate Eout integrals: false\n' sSpecific += 'Conserve: number\n' sSpecific += 'EFL: %s\n' % energyData.EFL.getValueAs( energyData.parameter1.data.axes[-1].unit ) sSpecific += 'EFH: %s\n' % energyData.EFH.getValueAs( energyData.parameter1.data.axes[-1].unit ) sData += getParameter( parameter1, 'TM' ) else : raise Exception( 'Unsupport energy functional = %s' % energyData.moniker ) sData.append( '' ) return( sProcess, sSpecific, startOfNewData + '\n'.join( sData ) )
def calculateDepositionEnergyFromEpP(E, EpP): "EpP is a list of [ E', P(E') ]" axes = axesModule.axes() axes[0] = axesModule.axis('a', 0, EpP.axes[0].unit) axes[1] = axesModule.axis('b', 1, EpP.axes[1].unit) Ep = XYsModule.XYs1d(data=[[EpP[0][0], EpP[0][0]], [EpP[-1][0], EpP[-1][0]]], axes=axes) return (float(EpP.integrateTwoFunctions(Ep)))
def grouped_values_to_XYs( groupBdries, valueList, \ domainUnit='eV', domainName='energy_in', rangeUnit='b', rangeName='crossSection', \ accuracy=upperEps, domainMin=1e-5, domainMax=20.0): if len(groupBdries) != len(valueList)+1: raise ValueError("Group boundries and value lists have incompatable lengths: len(bdries)=%i, len(vals)=%i"%(len(groupBdries),len(valueList))) return XYs.XYs1d(\ data=[groupBdries, [valueList[0]]+valueList], \ dataForm="xsandys", \ interpolation=standards.interpolation.flatToken, \ axes=XYs1d.defaultAxes(labelsUnits={ \ XYs.yAxisIndex : ( rangeName, rangeUnit ), \ XYs.xAxisIndex : ( domainName, domainUnit ) }) )
def __init__(self, angularEnergy_): self.productFrame = angularEnergy_.getProductFrame() axes_ = axes.defaultAxes(3) axes_[0] = angularEnergy_.axes[0] axes_[1] = angularEnergy_.axes[1] axes_[2] = axes.axis("P(mu|energy_in)", 2, "") W_XYs.W_XYs.__init__(self, axes_) for w_xys in angularEnergy_: P_mu = [[xys.value, xys.integrate()] for xys in w_xys] self.append( XYs.XYs(XYs.XYs.defaultAxes(), P_mu, 1e-3, value=w_xys.value))
def addData( endlZA, X1, temperature, energyMin_MeV, energyMax_MeV, I0Data, I1Data, I3Data, halflife = None ) : endlFile = getEndlFile( endlZA, 0, 11, 0, 1 ) data = [ [ energy, xSec ] for energy, xSec in I0Data ] if( data[0][0] > energyMin_MeV ) : if( data[0][1] != 0 ) : data.insert( 0, [ data[0][0], 0 ] ) data.insert( 0, [ energyMin_MeV, 0 ] ) if( data[-1][0] < energyMax_MeV ) : if( data[-1][1] != 0 ) : data.append( [ data[-1][0], 0 ] ) data.append( [ energyMax_MeV, 0 ] ) endlData = endlFile.addData( data, Q = 0, X1 = X1, temperature = temperature, halflife = halflife ) endlData.setFormat( 15 ) if( I1Data[0][0] > energyMin_MeV ) : I1Data.insert( 0, [ energyMin_MeV, copy.copy( I1Data[0][1] ) ] ) if( I1Data[-1][0] < energyMax_MeV ) : I1Data.append( [ energyMax_MeV, copy.copy( I1Data[-1][1] ) ] ) _I1Data = [] for energy, PofMu in I1Data : PofMu = XYsModule.XYs1d( PofMu ).normalize( ) _I1Data.append( [ energy, [ [ P, Mu ] for P, Mu in PofMu ] ] ) endlFile = getEndlFile( endlZA, 1, 11, 1, 1 ) endlData = endlFile.addData( _I1Data, Q = 0, X1 = X1, temperature = temperature, halflife = halflife ) endlData.setFormat( 15 ) if I3Data is not None: if( I3Data[0][0] > energyMin_MeV ) : I3Data.insert( 0, [ energyMin_MeV, copy.copy( I3Data[0][1] ) ] ) if( I3Data[-1][0] < energyMax_MeV ) : I3Data.append( [ energyMax_MeV, copy.copy( I3Data[-1][1] ) ] ) _I3Data = [] for energy, PofEprimeMu in I3Data: tmp = [] for mu, PofEprime in PofEprimeMu: PofEprime = XYsModule.XYs1d( PofEprime ).normalize( ) tmp.append( [ mu, [ [ Ep, P ] for Ep, P in PofEprime ] ] ) _I3Data.append( [ energy, tmp ] ) endlFile = getEndlFile( endlZA, 1, 11, 3, 1 ) endlData = endlFile.addData( _I3Data, Q = 0, X1 = X1, temperature = temperature, halflife = halflife ) endlData.setFormat( 15 )
def uncorrelated_EMuP_EEpP_TransferMatrix( style, tempInfo, crossSection, productFrame, angularData, energyData, multiplicity, comment = None, weight = None ) : logFile = tempInfo['logFile'] workDir = tempInfo['workDir'] sSpecific = '' if( isinstance( energyData, energyModule.functionalBase ) ) : sProcess, sSpecific, sData = energyFunctionToString( energyData, weight = weight ) weight = None elif( isinstance( energyData, energyModule.weightedFunctionals ) ) : TM1s, TMEs = [], [] for weight in energyData : TM1, TME = uncorrelated_EMuP_EEpP_TransferMatrix( style, tempInfo, crossSection, productFrame, angularData, weight.functional, multiplicity, comment = comment, weight = weight ) TM1s.append( TM1 ) TMEs.append( TME ) TM1 = addTMs( TM1s ) TME = addTMs( TMEs ) return( TM1, TME ) elif( isinstance( energyData, energyModule.regions2d ) ) : TM1s, TMEs = [], [] axes = axesModule.axes( ) for i1, region in enumerate( energyData ) : weight = XYsModule.XYs1d( data = [ [ region.domainMin, 1. ], [ region.domainMax, 1. ] ], axes = axes ) tempInfo['workFile'].append( 'r%s' % i1 ) try : TM1, TME = uncorrelated_EMuP_EEpP_TransferMatrix( style, tempInfo, crossSection, productFrame, angularData, region, multiplicity, comment = comment, weight = weight ) except : del tempInfo['workFile'][-1] raise del tempInfo['workFile'][-1] TM1s.append( TM1 ) TMEs.append( TME ) TM1 = addTMs( TM1s ) TME = addTMs( TMEs ) return( TM1, TME ) elif( isinstance( energyData, energyModule.primaryGamma ) ) : return( primaryGammaAngularData( style, tempInfo, crossSection, energyData, angularData, multiplicity = multiplicity, comment = comment ) ) else : if( angularData.isIsotropic() ) : sProcess = "Process: isotropic table\n" sData = EEpPDataToString( energyData ) else: sProcess = "Process: 'Uncorrelated energy-angle data transfer matrix'\n" sData = angularToString( angularData, crossSection ) sData += EEpPDataToString( energyData ) sCommon = commonDataToString( comment, style, tempInfo, crossSection, productFrame, multiplicity = multiplicity, weight = weight ) s = versionStr + '\n' + sProcess + sSpecific + sCommon + sData return( executeCommand( logFile, transferMatrixExecute, s, workDir, tempInfo['workFile'] ) )
def getUncertaintyVector( self, theData=None, relative=True ): """ Get an XYs1d object containing uncertainty for this matrix. Convert relative/absolute if requested (if so, must also pass central values as theData) Examples: - if the covariance matrix is relative and we want relative uncertainty vector, just do: > matrix.getUncertaintyVector() - if we want the absolute matrix instead: > matrix.getUncertaintyVector( theData=<XYs1d instance>, relative=False ) """ if not self.isSymmetric(): raise ValueError("getUncertaintyVector only applies to symmetric matrices!") energies = list( self.matrix.axes[-1].values ) diag = numpy.diagonal( self.matrix.array.constructArray() ).copy() diag[ diag < 0.0 ] = 0.0 diag = list( numpy.sqrt( diag ) ) diag.append( diag[-1] ) # point corresponding to final energy bin yunit = self.matrix.axes[0].unit if yunit != '': # get square root of the unit yunit = PQU.PQU(1,yunit).sqrt().getUnitSymbol() axes_ = axesModule.axes( labelsUnits={1:('energy_in',self.matrix.axes[2].unit), 0:('uncertainty',yunit)} ) uncert = XYsModule.XYs1d( zip(energies,copy.deepcopy(diag)), axes=axes_, interpolation='flat', accuracy=0.0001, ) # what should accuracy be set to? uncert = uncert.changeInterpolation('lin-lin',None,1e-8,1e-8) # do we need to convert absolute->relative or vice versa? if (relative and self.type==tokens.absoluteToken) or (not relative and self.type==tokens.relativeToken): if theData is None: theData = self.ancestor.rowData.link.toPointwise_withLinearXYs(1e-8,1e-8) try: theData = theData.toPointwise_withLinearXYs(1e-8,1e-8) uncert, theData = uncert.mutualify(1e-8, 1e-8, False, theData, 1e-8, 1e-8, False) if relative: #convert absolute to relative uncert /= theData else: #relative to absolute uncert *= theData except Exception as err: print len( uncert ), uncert.copyDataToXYs()[0], uncert.copyDataToXYs()[-1] print len( theData ), theData.copyDataToXYs()[0], theData.copyDataToXYs()[-1] raise Exception( err.message ) return uncert
def __init__( self, angularEnergy ) : self.__productFrame = angularEnergy.productFrame axes = axesModule.defaultAxes( 3 ) axes2d[2] = angularEnergy.axes[2] axes2d[1] = angularEnergy.axes[1] axes2d[0] = axesModule.axis( "P(mu|energy_in)", 0, "" ) axes1d = XYsModule.XYs1d.defaultAxes( ) axes1d[0] = axes2d[0] axes1d[1] = axes2d[1] multiD_XYsModule.XYs2d.__init__( self, axes = axes2d ) for P_EpGivenMu in angularEnergy : P_mu = [ [ xys.value, xys.integrate( ) ] for xys in P_EpGivenMu ] self.append( XYsModule.XYs1d( data = P_mu, axes = axes1d, accuracy = 1e-3, value = P_EpGivenMu.value ) )
def makeGrouped(self, processInfo, tempInfo): projectile, target = processInfo.getProjectileName( ), processInfo.getTargetName() groups = processInfo.getParticleGroups(projectile) energyUnit = tempInfo['crossSection'].domainUnit() axes = axesModule.axes(labelsUnits={ 0: ['energy_in', energyUnit], 1: ['energy', energyUnit] }) domainMin, domainMax = tempInfo['crossSection'].domain() energy = XYsModule.XYs1d(data=[[domainMin, domainMin], [domainMax, domainMax]], axes=axes, accuracy=1e-8) axes, grouped_ = miscellaneousModule.makeGrouped( self, processInfo, tempInfo, energy) self.addForm(grouped(axes, grouped_)) axes, grouped_ = miscellaneousModule.makeGrouped( self, processInfo, tempInfo, energy, normType='groupedFlux') self.addForm(groupedWithCrossSection(axes, grouped_))
def twoBodyTransferMatrix( style, tempInfo, productFrame, crossSection, angularData, Q, weight = None, comment = None ) : """ Generate input and call processing code to generate a transfer matrix for two-body angular distribution. If the distribution is actually made up of two different forms in different energy regions, this function calls itself in the two regions and sums the result. """ if( isinstance( angularData, angularModule.isotropic ) ) : angularData = angularData.toPointwise_withLinearXYs( ) if( isinstance( angularData, angularModule.XYs2d ) ) : TM1, TME = twoBodyTransferMatrix2( style, tempInfo, crossSection, angularData, Q, productFrame, comment = comment ) elif( isinstance( angularData, angularModule.regions2d ) ) : TM1s, TMEs = [], [] lowestBound, highestBound = angularData[0].domainMin, angularData[-1].domainMax weightAxes = axesModule.axes( ) for iRegion, region in enumerate( angularData ) : if( iRegion == 0 ) : weightData = [ [ lowestBound, 1 ], [ region.domainMax, 0 ], [ highestBound, 0 ] ] elif( iRegion == len( angularData ) - 1 ) : weightData = [ [ lowestBound, 0 ], [ region.domainMin, 1 ], [ highestBound, 1 ] ] else : weightData = [ [ lowestBound, 0 ], [ region.domainMin, 1 ], [ region.domainMax, 0 ], [ highestBound, 0 ] ] _weight = XYsModule.XYs1d( data = weightData, axes = weightAxes ) tempInfo['workFile'].append( 'r%s' % iRegion ) try : TM1, TME = twoBodyTransferMatrix2( style, tempInfo, crossSection, region, Q, productFrame, weight = _weight, comment = comment ) except : del tempInfo['workFile'][-1] raise del tempInfo['workFile'][-1] TM1s.append( TM1 ) TMEs.append( TME ) TM1 = addTMs( TM1s ) TME = addTMs( TMEs ) else : raise Exception( 'Unsupported P(mu|E) = %s' % angularData.moniker ) return( TM1, TME )
def check(self, info): from fudge.gnd import warning from pqu import PQU warnings = [] axes = axesModule.axes() axes[0] = self.axes[-2] axes[1] = self.axes[-1] for index, energy_in in enumerate(self): integral = float( XYsModule.XYs1d([(eout.value, eout.coefficients[0]) for eout in energy_in], axes=axes, accuracy=0.001).integrate()) if abs(integral - 1.0) > info['normTolerance']: warnings.append( warning.unnormalizedDistribution( PQU.PQU(energy_in.value, axes[0].unit), index, integral, self.toXLink())) minProb = min([ xy.toPointwise_withLinearXYs(0.001).rangeMin() for xy in energy_in ]) if minProb < 0: warnings.append( warning.negativeProbability(PQU.PQU( energy_in.value, axes[0].unit), value=minProb, obj=energy_in)) if self.interpolationQualifier is standardsModule.interpolation.unitBaseToken: # check for more than one outgoing distribution integrating to 0 at high end of incident energies integrals = [eout.integrate() for eout in energy_in] for idx, integral in enumerate(integrals[::-1]): if integral != 0: break if idx > 1: warnings.append( warning.extraOutgoingEnergy(PQU.PQU( energy_in.value, axes[-1].unit), obj=energy_in)) return warnings
def getDistribution(self, energy, energies, numberOfGammas, zeroTotal): energy_eV = 1e6 * energy if (self.multiplicity.domainMin() <= energy <= self.multiplicity.domainMax()): domainMin_eV, domainMax_eV = self.energyForm.domain() dE = energy_eV - domainMin_eV if (dE < 0): if (abs(dE) < 1e-15 * energy_eV): energy_eV = domainMin_eV else: return (None) dE = domainMax_eV - energy_eV if (dE < 0): if (abs(dE) < 1e-15 * energy_eV): energy_eV = domainMin_eV else: return (None) energyForm = self.energyForm if (isinstance(energyForm, (energyModule.piecewise, ))): for region in energyForm: if (energy_eV < region.domainMax()): break energyForm = region energyForm = energyForm.evaluate(energy_eV, epsilon=3 * energyEps) energyForm = energyForm.toPointwise_withLinearXYs( accuracy=1e-4, lowerEps=energyEps, upperEps=energyEps) lowerEps = energyEps if (energyForm.domainMin() == 0): lowerEps = 0 energyForm = energyForm.scaleOffsetXAndY( xScale=eV2MeV, yScale=1 / eV2MeV).dullEdges(lowerEps=lowerEps, upperEps=energyEps) energyForm = XYsModule.XYs(energyForm) multiplicity = getMultiplicityForDistributionSum( self, energy, energies, numberOfGammas, zeroTotal) distribution = multiplicity * energyForm return (distribution) else: return (None)
def addContinuumSpectrum(decayModes, RTYP_key, decayParticleIndex, regions, covariance): decayParticleID = decayParticles[decayParticleIndex] if (decayParticleID is None): raise Exception('decayParticleID is None, what is to be done?') decayParticleLabel = STYPProduct[decayParticleIndex] spectra = decayModes[RTYP_key].spectra if (decayParticleLabel not in spectra): spectrum = spectrumModule.spectrum(decayParticleLabel, decayParticleID) spectra.add(spectrum) else: spectrum = spectra[decayParticleLabel] if (len(regions) == 1): data = XYsModule.XYs1d( regions[0], axes=spectrumModule.continuum.defaultAxes(energyUnit)) else: print("len( regions ) > 1") return continuum = spectrumModule.continuum(data) spectrum.append(continuum)
def get_ENDF_flux(file, mat, mf, mt): import fudge.legacy.converting.ENDFToGND.endfFileToGNDMisc as endfFileToGNDMiscModule import xData.axes as axesModule import xData.XYs as XYsModule # Grab the data corresponding to the spectrum MF3Data = [ line.strip('\r\n') for line in open(file).readlines() if int(line[67:70]) == int(mat) and int(line[70:72]) == int(mf) and int(line[72:75]) == int(mt) ] # Define the axes spectrumAxes = axesModule.axes(rank=2) spectrumAxes[0] = axesModule.axis('spectrum', 0, '1/eV') spectrumAxes[1] = axesModule.axis('energy_in', 1, 'eV') # Now make the spectrum as an XYs1d dataLine, TAB1, spectrumRegions = endfFileToGNDMiscModule.getTAB1Regions( 1, MF3Data, allowInterpolation6=True, logFile=None, #info.logs, axes=spectrumAxes, cls=XYsModule.XYs1d) if (len(spectrumRegions) == 1): # Store as XYs1d. spectrumForm = XYsModule.XYs1d( data=spectrumRegions[0], label=None, axes=spectrumAxes, interpolation=spectrumRegions[0].interpolation) else: raise NotImplementedError( "Fluxes with multiple regions for %s/%s/%s/%s" % (file, mat, mf, mt)) spectrumForm = crossSectionModule.regions1d(label=None, axes=spectrumAxes) for region in spectrumRegions: if (len(region) > 1): spectrumForm.append(region) return (spectrumForm)
def toENDL(coherentElastic, energyMin_MeV, energyMax_MeV, temperature_MeV, accuracy=0.001, epsilon=1e-6): S_table = coherentElastic.S_table gridded2d = S_table.gridded2d array = gridded2d.array.constructArray() energyGrid = gridded2d.axes[1].copy([]) temperatureGrid = gridded2d.axes[2].copy([]) temperatureGrid.convertToUnit('MeV/k') for index2, temperature2 in enumerate(temperatureGrid.values): if (temperature2 >= temperature_MeV): break if (temperature_MeV > temperature2): SofE = XYsModule.XYs1d((energyGrid.values, array[-1]), dataForm='XsAndYs', interpolation=energyGrid.interpolation) elif ((index2 == 0) or (temperature2 == temperature_MeV)): SofE = XYsModule.XYs1d((energyGrid.values, array[index2]), dataForm='XsAndYs', interpolation=energyGrid.interpolation) else: index1 = index2 - 1 temperature1 = temperatureGrid.values[index1] fraction = (temperature_MeV - temperature1) / (temperature2 - temperature1) SofE1 = XYsModule.XYs1d((energyGrid.values, array[index1]), dataForm='XsAndYs', interpolation=energyGrid.interpolation) SofE2 = XYsModule.XYs1d((energyGrid.values, array[index2]), dataForm='XsAndYs', interpolation=energyGrid.interpolation) SofE = (1 - fraction) * SofE1 + fraction * SofE2 axes = axesModule.axes() axes[0].label = gridded2d.axes[0].label axes[0].unit = gridded2d.axes[0].unit axes[1].label = energyGrid.label axes[1].unit = energyGrid.unit SofE.axes = axes SofE.convertUnits({"eV": "MeV"}) _SofE = SofE SofE = [] for energy, S2 in _SofE: if (energy > energyMax_MeV): break SofE.append([energy, S2]) if ((SofE[-1][0] < energyMax_MeV) and (SofE[-1][0] < _SofE[-1][0])): eMax = _SofE[-1][0] if (energyMax_MeV < eMax): eMax = energyMax_MeV SofE.append([eMax, SofE[-1][1]]) S1 = 0 I0 = [] I1 = [] n_minus1 = len(SofE) - 1 for index, energyS in enumerate(SofE): energy, S2 = energyS energy1 = (1 - epsilon) * energy if (index == 0): S1 = S2 energy1 = energy energy2 = (1 + epsilon) * energy if (index == n_minus1): energy2 = energy if (energy >= energyMax_MeV): energy = energyMax_MeV energy2 = energyMax_MeV if (energy2 > energyMax_MeV): energy2 = energyMax_MeV I0.append([energy1, S1 / energy]) if (energy != energy1): I0.append([energy2, S2 / energy]) PofMu = calculatePofMu(energy1, index, SofE, epsilon) if (len(PofMu) > 0): I1.append([energy1, PofMu]) if (energy != energy1): PofMu = calculatePofMu(energy2, index + 1, SofE, epsilon) if (len(PofMu) > 0): I1.append([energy2, PofMu]) S1 = S2 if (energy == energyMax_MeV): break accuracy = min(0.1, max(1e-5, accuracy)) I0Fine = [I0.pop(0)] x1, y1 = I0Fine[0] for x2, y2 in I0: if ((x2 - x1) > (2 * epsilon * x1)): bisectionTest(I0Fine, x1, y1, x2, y2, accuracy) I0Fine.append([x2, y2]) x1, y1 = x2, y2 return (I0Fine, I1, None)
def calculate_a( self, energy_in, energy_out_cmMin, energy_out_cmMax, accuracy = 1e-6 ) : from fudge.core.math import fudgemath from fudge.particles import nuclear def getParticleData( particle ) : Z, A, suffix, ZA = particle.getZ_A_SuffixAndZA( ) return( particle.name, Z, max( 0, A - Z ), A, particle.getMass( 'MeV/c**2' ) ) energyFactor = PQU.PQU( 1, 'MeV' ).getValueAs( self.fSubform.data.axes[-1].unit ) projectile = self.findAttributeInAncestry( 'projectile' ) target = self.findAttributeInAncestry( 'target' ) product = self.findClassInAncestry( fudge.gnd.product.product ).particle name_a, Z_a, N_a, A_a, AWRa = getParticleData( projectile ) name_A, Z_A, N_A, A_A, AWRA = getParticleData( target ) name_b, Z_b, N_b, A_b, AWRb = getParticleData( product ) Z_C, N_C = Z_a + Z_A, N_a + N_A if( N_A == 0 ) : N_C = 0 Z_B, N_B = Z_C - Z_b, max( 0, N_C - N_b ) A_B = Z_B + N_B if( N_B == 0 ) : A_B = 0 particles = self.findClassInAncestry( fudge.gnd.reactionSuite.reactionSuite ).particles residual = particles.getParticle( nuclear.nucleusNameFromZA( 1000 * Z_B + A_B ) ) AWRB = residual.getMass( 'MeV/c**2' ) Ma, Ia = self.KalbachMann_a_parameters[name_a]['M'], self.KalbachMann_a_parameters[name_a]['I'] mb, Ib = self.KalbachMann_a_parameters[name_b]['m'], self.KalbachMann_a_parameters[name_b]['I'] Sa, Sb = energyFactor * self.calculate_S_ab_MeV( Z_A, N_A, Z_C, N_C, Ia ), energyFactor * self.calculate_S_ab_MeV( Z_B, N_B, Z_C, N_C, Ib ) C1, C2, C3 = 0.04 / energyFactor, 1.8e-6 / energyFactor**3, 6.7e-7 / energyFactor**4 ea = energy_in * AWRA / ( AWRa + AWRA ) + Sa R1, R3 = 130 * energyFactor, 41 * energyFactor # MeV to self's energy units. if( ea < R1 ) : R1 = ea if( ea < R3 ) : R3 = ea def calculate_a2( energy_out_cm ) : eb = energy_out_cm * ( AWRb + AWRB ) / AWRB + Sb X1, X3 = R1 * eb / ea, R3 * eb / ea return( X1 * ( C1 + C2 * X1 * X1 ) + C3 * Ma * mb * X3**4 ) class thicken_a : def __init__( self, calculate_a2, relativeTolerance, absoluteTolerance ) : self.calculate_a2 = calculate_a2 self.relativeTolerance = relativeTolerance self.absoluteTolerance = absoluteTolerance def evaluateAtX( self, x ) : return( self.calculate_a2( x ) ) a = [ [ energy_out_cmMin, calculate_a2( energy_out_cmMin ) ], [ energy_out_cmMax, calculate_a2( energy_out_cmMax ) ] ] a = fudgemath.thickenXYList( a, thicken_a( calculate_a2, accuracy, 1e-10 ) ) axes = axesModule.axes( ) axes[0] = axesModule.axis( 'a', 0, '' ) axes[1] = self.fSubform.data.axes[1].copy( ) return( XYsModule.XYs1d( data = a, axes = axes, accuracy = accuracy ) )
def toACE(self, fileName, evaluationId, temperature, productData, addAnnotation): massUnit = 'eV/c**2' projectile, target = self.projectile, self.target targetZ, targetA, targetSuffix, targetZA = target.getZ_A_SuffixAndZA() neutronMass = projectile.getMass(massUnit) targetMass = target.getMass(massUnit) target2NeutronMass = targetMass / neutronMass if (not (isinstance(temperature, PQU.PQU))): temperature = PQU.PQU(temperature) if (temperature.isTemperature()): temperature_MeV = temperature.getValueAs('MeV / k') temperature_K = temperature.getValueAs('K') else: temperature_MeV = temperature.getValueAs('MeV') temperature_K = temperature.getValueAs('k * K') processingTime = time.localtime() strRecords = [ "%6d.%.2dc%12.7f %11.5E %.2d/%.2d/%.2d" % (targetZA, evaluationId, target2NeutronMass, temperature_MeV, processingTime[1], processingTime[2], processingTime[0]) ] nonFissionEnergyDependentNeutronMultiplicities = [] nonFissionEnergyDependentNeutronMultiplicitiesIndex = 100 MAT = endf_endl.ZAAndMATFromParticleName(target.name)[1] MAT_ID = ' mat %d' % MAT HK = '%2d-%s at %.1fK from %s-%s Fudge.toACE' % \ ( targetZ, target.name, temperature_K, self.styles['evaluated'].attributes['library'], self.styles['evaluated'].attributes['version'] ) HK = "%-70s" % HK[:70] strRecords.append(HK + MAT_ID) for i in xrange(4): strRecords.append( ' 0 0.000000 0 0.000000 0 0.000000 0 0.000000' ) NXS = 16 * [0] JXS = 32 * [0] MRT, NU_prompt, NU_total, LQR, TYP, SigData, neutronAngular, neutronEnergies = [], None, None, [], [], {}, [], [] NXS[2 - 1] = targetZA for MT, MTData in productData: if (MT == 2): # Elastic (MT = 2) must always be present in ACE file. EMin = MTData['ESZ'].domainMin(unitTo='MeV') break totalXSec = XYs.XYs( axes.defaultAxes(labelsUnits={ 0: ('', 'MeV'), 1: ('', 'b') }), [], 1e-3) absorptionXSec = XYs.XYs( axes.defaultAxes(labelsUnits={ 0: ('', 'MeV'), 1: ('', 'b') }), [], 1e-3) sortedMTs = sorted([[MTData[0], i1] for i1, MTData in enumerate(productData) ]) # Sort MTs like NJOY. for MT, i1 in sortedMTs: MT_, MTData = productData[i1] XSec = MTData['ESZ'] XSec = XSec.convertAxisToUnit(0, 'MeV') XSec = XSec.convertAxisToUnit(1, 'b') neutronDatas = MTData['n'] multiplicity = 0 if (MT == 2): elasticXSec = XSec if (len(neutronDatas) > 1): raise Exception( 'Only one type of neutron data is support for the elastic reaction.' ) if (len(neutronDatas) > 0): neutronAngular.append((MT, neutronDatas[0]['angularData'])) else: MRT.append(MT) LQR.append(MTData['Q']) if (XSec[0][0] != 0): if (XSec[0][0] > EMin): XSec = XSec.dullEdges(lowerEps=1e-8) SigData[MT] = XSec totalXSec = totalXSec + XSec if (len(neutronDatas) == 0): absorptionXSec = absorptionXSec + XSec neutronMultiplicity = 0 else: NXS[5 - 1] += 1 product = neutronDatas[0]['product'] frame = neutronDatas[0]['frame'] angularData = neutronDatas[0]['angularData'] energyData = neutronDatas[0]['energyData'] if (MTData['isFission']): neutronMultiplicity = 19 totalPresent = False for neutronData in neutronDatas: product = neutronData['product'] if ((product.attributes['emissionMode'] == tokens.promptToken) or (product.attributes['emissionMode'] == 'total')): totalPresent = product.attributes[ 'emissionMode'] == 'total' NU_prompt = neutronData['multiplicity'] break if (NU_prompt is None): raise Exception('Missing prompt neutron') if (len(neutronDatas) > 1): if (totalPresent): raise Exception( 'Total nu_bar present and delayed neutron data.' ) NU_total = NU_prompt for neutronData in neutronDatas: product = neutronData['product'] if (product.attributes['emissionMode'] == 'delayed' ): NU_delayed = neutronData['multiplicity'] if (NU_delayed.domainMax() < NU_total.domainMax()): NU_delayed = NU_delayed.dullEdges( upperEps=1e-8) NU_total = NU_total + NU_delayed else: if (len(neutronDatas) == 1): neutronMultiplicity = neutronDatas[0]['multiplicity'] else: neutronMultiplicity, angularData, energyData = specialMF6.neutrons( neutronDatas) if (not (isinstance(neutronMultiplicity, int))): nonFissionEnergyDependentNeutronMultiplicitiesIndex += 1 nonFissionEnergyDependentNeutronMultiplicities.append([ MT, nonFissionEnergyDependentNeutronMultiplicitiesIndex, neutronMultiplicity ]) neutronMultiplicity = nonFissionEnergyDependentNeutronMultiplicitiesIndex if (frame == axes.centerOfMassToken): neutronMultiplicity *= -1 # Negative for COM frame. if (energyData is None): if (50 <= MT <= 91): energyData = n_nPrimeEnergyData( MT, target2NeutronMass, MTData['Q']) else: raise 'hell: but first implement energy for MT =' % MT else: if (isinstance(energyData, distributions.energy.NBodyPhaseSpace)): angularData = None neutronAngular.append((MT, angularData)) neutronEnergies.append( [MT, XSec.xMin(), XSec.xMax(), energyData]) TYP.append(neutronMultiplicity) totalXSec = elasticXSec + totalXSec annotates, XSS, energyGrid, totalSigma = [], [], [], [] for E, sigma in totalXSec: energyGrid.append(E) totalSigma.append(sigma) # 1) Add the ESZ block. NXS[3 - 1] = len(energyGrid) updateXSSInfo('energyGrid', annotates, XSS, energyGrid) updateXSSInfo('totalSigma', annotates, XSS, totalSigma) if (len(absorptionXSec) == 0): updateXSSInfo('absorption cross section', annotates, XSS, len(energyGrid) * [0.]) else: updateXSSInfo('absorption cross section', annotates, XSS, mapEnergyToTotal(totalXSec, absorptionXSec)) updateXSSInfo('elastic cross section', annotates, XSS, mapEnergyToTotal(totalXSec, elasticXSec)) averageHeating = len(energyGrid) * [0.] updateXSSInfo('average heating', annotates, XSS, averageHeating) # 2) Add the NU block. if (NU_prompt is not None): JXS[2 - 1] = len(XSS) + 1 NU_prompt = NU_prompt.toACE() if (NU_total is not None): NU_prompt.insert(0, -len(NU_prompt)) updateXSSInfo('NU', annotates, XSS, NU_prompt) if (NU_total is not None): NU_total = NU_total.toACE() updateXSSInfo('NU(total)', annotates, XSS, NU_total) # 3) Add the MRT block. NXS[4 - 1] = len(MRT) JXS[3 - 1] = len(XSS) + 1 updateXSSInfo('MRT', annotates, XSS, MRT) # 4) Add the LQR block. JXS[4 - 1] = len(XSS) + 1 updateXSSInfo('LQR', annotates, XSS, LQR) # 5) Add the TYP block. JXS[5 - 1] = len(XSS) + 1 updateXSSInfo('TYP', annotates, XSS, TYP) # 6 and 7) Add the LSIG and SIG blocks. SIG = [] for MT, MTData in productData: if (MT not in [2]): addSigData(MT, SIG, energyGrid, SigData[MT]) JXS[6 - 1] = len(XSS) + 1 LSIG = [1] for MT, firstNonZero, reactionSIG in SIG[:-1]: LSIG.append(LSIG[-1] + len(reactionSIG) + 2) updateXSSInfo('LSIG', annotates, XSS, LSIG) JXS[7 - 1] = len(XSS) + 1 for MT, firstNonZero, reactionSIG in SIG: reactionSIG_ = [firstNonZero + 1, len(reactionSIG)] + reactionSIG updateXSSInfo('SIG(MT=%s)' % MT, annotates, XSS, reactionSIG_) # 8 and 9) Add the LAND and AND blocks. LAND, MT_AND, length = [], [], 0 for MT, angular in neutronAngular: if (angular is None): LAND.append(-1) elif (angular.isIsotropic()): LAND.append(0) elif (isinstance(angular, (distributions.angular.linear, angularEnergy.angularFor_angularEnergy))): LAND.append(length + 1) length += 2 * len(angular) + 1 energies_in = [len(angular)] LCs, Ps = [], [] for xys in angular: energy_in = PQU.PQU( xys.value, angular.axes[0].getUnit()).getValueAs('MeV') energies_in.append(energy_in) LCs.append(-length - 1) xys = xys.normalize() mus, pdf = [], [] for x, y in xys: mus.append(x) pdf.append(y) cdf = xys.runningIntegral() cdf[-1] = 1. # Make sure last point is really 1. Ps += [2, len(mus)] + mus + pdf + cdf length += 3 * len(xys) + 2 MT_AND.append((MT, energies_in + LCs + Ps)) else: raise Exception( 'Unsupport neutron angular distribution type = %s' % type(angular)) JXS[8 - 1] = len(XSS) + 1 updateXSSInfo('LAND', annotates, XSS, LAND) JXS[9 - 1] = len(XSS) + 1 for MT, AND in MT_AND: updateXSSInfo('AND(MT=%s)' % MT, annotates, XSS, AND) # 10 and 11) Add the LDLW and DLW blocks. LDLW, MT_DLW = processEnergyData(massUnit, neutronMass, neutronEnergies) JXS[10 - 1] = len(XSS) + 1 updateXSSInfo('LDLW', annotates, XSS, LDLW) JXS[11 - 1] = len(XSS) + 1 for MT, DLW in MT_DLW: updateXSSInfo('DLW(MT=%s)' % MT, annotates, XSS, DLW) # Now fixup the TYP data whose abs( value ) is greater than 100. for MT, index, multiplicity in nonFissionEnergyDependentNeutronMultiplicities: i1, found = JXS[5 - 1], False for i2 in range(NXS[4 - 1]): if (abs(XSS[i1 + i2 - 1]) == index): n_multiplicity = multiplicity.toACE() LNU, n_multiplicity = n_multiplicity[0], n_multiplicity[1:] if (LNU != 2): raise Exception( 'Only tabular neutron multiplicity is allowed, not LNU = %d' % LNU) offset = len(XSS) - JXS[11 - 1] + 101 + 1 if (XSS[i1 + i2 - 1] < 0): offset *= -1 XSS[i1 + i2 - 1] = offset updateXSSInfo('Neutron Yields(MT=%s)' % MT, annotates, XSS, n_multiplicity) found = True break if (not (found)): raise Exception( 'Neutron multiplicity for index %s not found in TYP table' % index) # Time to wrap it all up. NXS[1 - 1] = len(XSS) JXS[1 - 1] = 1 JXS[22 - 1] = len( XSS) + 1 # Location of the last word of XSS (i.e., its length). strRecords += intArrayToRecords(NXS) strRecords += intArrayToRecords(JXS) strRecords += XSSToStrings(annotates, XSS, addAnnotation) strRecords.append('') fOut = open(fileName, 'w') fOut.write('\n'.join(strRecords)) fOut.close()
def plotTests(tests=11 * [False]): from fudge import fudgeParameters fudgeParameters.VerboseMode = 0 from fudge.legacy.endl.endlProject import endlProject from fudge.legacy.endl.endl3dmathClasses import endl3dmath from fudge import __path__ from xData import axes as axesModule from xData import XYs as XYsModule from xData import multiD_XYs as multiD_XYsModule testData = ''' # Authors: T.S.Suzuki, Y.Nagai, T.Shima, T.Kikuchi, H.Sato, T.Kii, M.Igashira # Title: First Measurement Of A P(N,Gamma)D Reaction Cross Section Between 10 And 80 Kev # Year: 1995 # Institute: Tokyo Inst.of Technology, Tokyo # Reference: Astrophysical Journal 439, (L), 59 (1995) # Subent: 22310002 # Reaction: Cross section for 1H(n,gamma)2H # Note: the d(Energy) errorbars are fake and are used for plot testing # Energy Data d(Energy) d(Data) # MeV barns MeV barns 0.02 0.000353 0.001 2.6e-05 0.02 0.000329 0.001 2.6e-05 0.02 0.000287 0.0 2.2e-05 0.02 0.000304 0.0 1.8e-05 0.04 0.00023 0.001 1.5e-05 0.04 0.000198 0.001 1.2e-05 0.04 0.000177 0.0015 1e-05 0.04 0.000207 0.0 1.3e-05 0.064 0.000156 0.0 1.1e-05 0.064 0.00015 0.0 7e-06 0.064 0.000158 0.0 1.1e-05 0.064 0.00014 0.0 9e-06 ''' e = endlProject(__path__[0] + "/legacy/endl/test/testdb") za = e.readZA(1001) za.read() xAxis = AxisSettings(isLog=True, label='$E_n$', axisMin=0.5e-2, axisMax=1.5e-1, gridOn=True, autoscale=False, unit='MeV') yAxis = AxisSettings(isLog=True, label='$\sigma(E_n)$', gridOn=True, unit='b') d = [] u = [] for line in testData.split('\n'): if line.strip().startswith('#'): continue sline = map(float, line.split()) if len(sline) != 0: d.append(sline[0:2]) u.append(sline[2:4]) xyAxes = axesModule.axes(labelsUnits={ 1: (xAxis.label, xAxis.unit), 0: (yAxis.label, yAxis.unit) }) # Simple test, here we make a plot of one set if tests[0]: xSec = za.findData(I=0, C=46) makePlot2d([xSec], xAxisSettings=xAxis, yAxisSettings=yAxis, title='$^1$H$(n,\gamma)$ Cross Section', outFile=None) xys = XYsModule.XYs(xSec.data, axes=xyAxes, accuracy=1e-3) makePlot2d((xys), xAxisSettings=xAxis, yAxisSettings=yAxis, title='$^1$H$(n,\gamma)$ Cross Section', outFile=None) dataset = DataSet2d(xys, xUnit=xAxis.unit, yUnit=yAxis.unit) dataset.convertUnits('eV', 'mb') makePlot2d((dataset), xAxisSettings=xAxis, yAxisSettings=yAxis, title='$^1$H$(n,\gamma)$ Cross Section', outFile=None) # Plot all the cross section data in the fudge2 test library, but unthemed! if tests[1]: makePlot2d(za.findDatas(I=0), outFile=None) # Plot all the cross section data in the fudge2 test library if tests[2]: xSecs = za.findDatas(I=0) makePlot2d(xSecs, xAxisSettings=xAxis, yAxisSettings=yAxis, title='$^1$H$(n,*)$ Cross Sections', outFile=None) xySecs = [ XYsModule.XYs(xSec.data, axes=xyAxes, accuracy=1e-3) for xSec in xSecs ] xySecs = (xySecs[0], xySecs[1], xySecs[2]) makePlot2d(xySecs, xAxisSettings=xAxis, yAxisSettings=yAxis, title='$^1$H$(n,*)$ Cross Sections', outFile=None) # Fancy test, here we make a plot of one dataset (the testData above) if tests[3]: endfData = za.findData(I=0, C=46) #.slicex(domainMin=1e-2,domainMax=1e-1) endfUnc = 0.1 * endfData # 10% error bars makePlot2d( [ \ DataSet2d( data = endfData, uncertainty = endfUnc, legend = 'ENDF/B-VII.0', color='g', lineStyle = '-' ), DataSet2d( data = d, uncertainty = u, legend = 'T.S.Suzuki, et al. (1995) EXFOR entry # 22310002', color='g', symbol = 'o' ), ], xAxisSettings = xAxis, yAxisSettings = yAxis, title = '$^1$H$(n,\gamma)$ Cross Section', legendOn = True, outFile = None ) # Contour test if tests[ 4]: # Contour plots are meaningful if there is only one dataset plotted, how do we enforce this? endfData = za.findData(yo=1, I=1, C=10) EAxis = AxisSettings(isLog=False, label='$E_n$ (MeV)', axisMin=1.0, axisMax=20.0, gridOn=True, autoscale=False, unit='MeV') muAxis = AxisSettings(isLog=False, label='$\mu$ = cos( $\\theta$ )', axisMin=-1.0, axisMax=1.0, autoscale=False, gridOn=True) makePlot2dContour(DataSet3d(data=endfData, legend='ENDF/B-VII.0', xUnit=EAxis.unit, yUnit=muAxis.unit), xAxisSettings=EAxis, yAxisSettings=muAxis, title='$^1$H$(n,el)$ Angular Distribution', outFile=None) w_xys = multiD_XYsModule.multiD_XYs( axes=axesModule.axes(rank=3, labelsUnits={2: ('$E_n$', 'MeV')})) for w, xy in endfData.data: w_xys.append( XYsModule.XYs(xy, axes=axesModule.axes(), accuracy=1e-3, value=w)) dataset = DataSet3d(data=w_xys, legend='ENDF/B-VII.0') dataset.convertUnits('eV', None, None) makePlot2dContour(dataset, xAxisSettings=EAxis, yAxisSettings=muAxis, title='$^1$H$(n,el)$ Angular Distribution', outFile=None) # Slice tests if (tests[5] or tests[6] or tests[7] or tests[8] or tests[9]): endfDataI0 = za.findData(yo=0, I=0, C=10).slicex(1.0, 20.0) # simplify the plot endfDataI1 = za.findData(yo=1, I=1, C=10) Es = [p[0] for p in endfDataI0.data] # in [MeV] mus = [] # in [mu] for t in endfDataI1.data: mus += [p[0] for p in t[1]] mus = sorted(uniquify(mus)) table = [] for E in Es: muDist = [] for mu in mus: muDist.append( [mu, endfDataI0.getValue(E) * endfDataI1.getValue(E, mu)]) table.append([E, muDist]) endfDataCombined = endl3dmath(data=table) EAxis = AxisSettings(isLog=True, label='$E_n$ (MeV)', axisMin=1.0, axisMax=20.0, gridOn=True, autoscale=False) muAxis = AxisSettings(isLog=False, label='$\mu = \cos{( \\theta )}$', axisMin=-1.0, axisMax=1.0, autoscale=False, gridOn=True) zAxis = AxisSettings(isLog=True, label='$d\sigma(E)/d\mu$ (b)', axisMin=0.0, axisMax=5.0, autoscale=False, gridOn=True) # unthemed slice tests if tests[5]: makePlot2dSlice( endfDataCombined, xyAxisSettings=EAxis, zAxisSettings=zAxis, sliceXCoords=None, sliceYCoords=[-1.0, -0.75, -0.5, -.25, 0.0, .25, .5, .75, 1.0], title='', outFile=None) dataSet3d = DataSet3d(data=endfDataCombined, legend='ENDF/B-VII.0') makePlot2dSlice( dataSet3d.getW_XYs(), xyAxisSettings=EAxis, zAxisSettings=zAxis, sliceXCoords=None, sliceYCoords=[-1.0, -0.75, -0.5, -.25, 0.0, .25, .5, .75, 1.0], title='', outFile=None) if tests[6]: makePlot2dSlice(endfDataCombined, xyAxisSettings=muAxis, zAxisSettings=zAxis, sliceXCoords=[1.0, 5.0, 10.0, 15.0, 20.0], sliceYCoords=None, title='', outFile=None) # themed slice test and contour test if tests[7]: makePlot2dContour(DataSet3d(data=endfDataCombined, legend='ENDF/B-VII.0'), xAxisSettings=EAxis, yAxisSettings=muAxis, numContours=10, title='$d\sigma(E)/d\mu$ for $^1$H$(n,el)$', outFile=None) if tests[8]: makePlot2dSlice( DataSet3d(data=endfDataCombined, legend='ENDF/B-VII.0'), xyAxisSettings=EAxis, zAxisSettings=zAxis, sliceXCoords=None, sliceYCoords=[-1.0, -0.75, -0.5, -.25, 0.0, .25, .5, .75, 1.0], title='', outFile=None) # themed slice test, with test 2d experimental data if tests[9]: makePlot2dSlice( [ \ DataSet3d( data = endfDataCombined, legend = 'ENDF/B-VII.0' ), \ DataSet2d( data = d, uncertainty = u, legend = 'T.S.Suzuki, et al. (1995) EXFOR entry # 22310002', color='g', symbol = 'o' ),\ ], xyAxisSettings = muAxis, zAxisSettings = zAxis, sliceXCoords = [ 1.0, 5.0, 10.0, 15.0, 20.0 ], sliceYCoords = None, sliceUnits = 'MeV', title = 'Slice test', outFile = None )
def primaryGammaAngularData( style, tempInfo, crossSection, energyData, angularData, multiplicity = 1, comment = None ) : """ Currently, only isotropic (i.e., l = 0) data are returned. That is, lMax and angularData are ignored. massRatio is the target mass divide by the sum of the projectile and target masses. This function perform the integration TM = \int_g dE \int_h dE' S(E) M(E) f(E) P(E -> E') / \int_g dE f(E) where \int_g is the integral of E from E_i to E_{i+1}, \int_g is the integral of E' from E'_j to E'_{j+1}, S(E) is the cross section, M(E) is the products multiplicity, f(E) is the flux weighting and P(E -> E') is the probability for a projectile of energy E producing a primary gamma of energy E' for binding energy bindingEnergy. This function assumes that M(E) is a constant. For primary gamma's captured into binding energy bindingEnergy P(E -> E') = deltaFunction( E' - ( bindingEnergy + massRatio E ) ) where massRatio = mt / ( mp + mt ), mp is the projectile's mass and mt is the target's mass. Note, this formula is from the ENDF manual which ignores the recoil of the residual nucleus. """ reactionSuite = tempInfo['reactionSuite'] projectileName = reactionSuite.projectile projectileGroupBoundaries = style.transportables[projectileName].group.boundaries productName = tempInfo['productName'] productGroupBoundaries = style.transportables[productName].group.boundaries flux0 = style.flux.getFluxAtLegendreOrder( 0 ) groupedFlux = tempInfo['groupedFlux'] bindingEnergy = energyData.value * energyData.axes[1].unitConversionFactor( tempInfo['incidentEnergyUnit'] ) massRatio = energyData.massRatio nProj = len( projectileGroupBoundaries.values ) - 1 nProd = len( productGroupBoundaries.values ) - 1 TM_1, TM_E = {}, {} for i1 in range( nProj ) : TM_1[i1] = {} TM_E[i1] = {} for i2 in range( nProd ) : TM_1[i1][i2] = [ 0. ] TM_E[i1][i2] = [ 0. ] Eg2 = bindingEnergy + massRatio * projectileGroupBoundaries.values[0] for indexEo, Eo in enumerate( productGroupBoundaries.values ) : if( Eg2 <= Eo ) : break indexEo = min( max( indexEo - 1, 0 ), nProd - 1 ) EMin, EMax = crossSection.domainMin, crossSection.domainMax axes = axesModule.axes( labelsUnits = { 0 : ( 'energy_out', tempInfo['incidentEnergyUnit'] ), 1 : ( crossSection.axes[1].label, crossSection.axes[1].unit ) } ) Egp = XYsModule.XYs1d( data = [ [ EMin, bindingEnergy + massRatio * EMin ], [ EMax, bindingEnergy + massRatio * EMax ] ], axes = axes ) for indexEi in range( nProj ) : Ei2 = projectileGroupBoundaries.values[indexEi + 1] Eg2 = bindingEnergy + massRatio * Ei2 EiMin = projectileGroupBoundaries.values[indexEi] while( True ) : incrementIndexEo, EiMax = 0, Ei2 if( indexEo < ( nProd - 1 ) ) : if( Eg2 > productGroupBoundaries.values[indexEo + 1] ) : incrementIndexEo = 1 EiMax = ( productGroupBoundaries.values[indexEo + 1] - bindingEnergy ) / massRatio TM_1[indexEi][indexEo][0] = float( crossSection.integrateTwoFunctions( flux0, domainMin = EiMin, domainMax = EiMax ) / groupedFlux[indexEi] ) TM_E[indexEi][indexEo][0] = float( crossSection.integrateThreeFunctions( flux0, Egp, domainMin = EiMin, domainMax = EiMax ) / groupedFlux[indexEi] ) if( incrementIndexEo == 0 ) : break EiMin = EiMax if( indexEo < ( nProd - 1 ) ) : indexEo += 1 return( TM_1, TM_E )
def group( self, groupBoundaries = ( None, None ), groupUnit = ( None, None ) ): ''' Group the matrix in self :param groupBoundaries: a 2 element list containing the group boundaries for the rows and columns (respectively) of the covariance to be regrouped rows go in the first element, columns in the second :param groupUnit: a 2 element list containing the units in which group boundaries are specified for the rows and columns (respectively) of the covariance to be regrouped :returns: the regrouped matrix (an xData.array.full as the array in a gridded2d.matrix) .. note:: We still need to do flux weighting .. rubric:: Regrouping Theory Given a function :math:`f(E)`, we write the grouped data using fudge's ``flat`` interpolation scheme. We note that we could write this scheme as an expansion over basis functions: .. math:: f(E) = \sum_{i=0}^{N+1} w_i(E) * f_i where the weight functions :math:`w_i(E)` are .. math:: w_i(E) = 1 \;\\text{for}\; E_i <= E <= E_{i+1}; \;\; 0 \;\\textrm{otherwise} These weights are an orthogonal (bot not orthonormal) basis, with .. math:: (E_{i+1}-E_i) \delta_{ij} = \int dE w_i(E) * w_j(E) So, to transform from basis :math:`w_i(E)` to :math:`v_i(E)` (which has group boundaries :math:`[ E'_0, ... ]`), do: .. math:: f'_j = \sum_i m_{ji} f_i where :math:`f'` is the regrouped function coefficients and :math:`m_{ji}` is the matrix .. math:: m_{ij} = (E'_{i+1}-E'_i)^{-1} \int dE v_i(E) w_j(E) .. rubric:: Applying regrouping theory to covariance matrices When we are given a covariance matrix :math:`c_{ij}` in ENDF, it is meant to be interpreted as a grouped covariance in both the direction of the matrix rows and the matrix columns. Therefore, we must regroup in both the row direction and the column direction. The ENDF format gives both the group boundaries for the rows and columns. In other words, ENDF gives us the following rule for evaluating the continuous row- column covariance: .. math:: c( E1, E2 ) = \sum_{ij} w_i(E1) w_j(E2) c_{ij} Computing :math:`m_{ij}` as before, .. math:: cc_{ij} = \sum_{i',j'} m_{ii'} c_{i'j'} m_{j'j} It is straightforward to generalize to the case where the row and column bases are different. In the routine below, we abuse :py:class:`xData.XYs1d` to specify the functions :math:`w_i(E)` and use the :py:func:`XYs1d.groupOneFunction()` method to perform the integrals to get the regrouping matrix. We do this separately for the rows and the columns. The matrix multiplication that converts a covariance from one pair of bases (group structures) to another is accomplished using numpy. .. rubric:: An explanation of fudge's 'flat' interpolation Suppose we have a function :math:`f(E)` specified using fudge's `'flat'` interpolation. Then we have :math:`N` entries :math:`[f_0, f_1, ..., f_{N-1}]` and a set of group boundaries :math:`[E_0, E_1, ..., E_N]` and the following rule for interpolation: * Below :math:`E_0`, :math:`f(E)` evaluates to :math:`0.0` * From :math:`E_0 \\rightarrow E_1`, :math:`f(E)` evaluates to :math:`f_0` * From :math:`E_1 \\rightarrow E_2`, :math:`f(E)` evaluates to :math:`f_1` * ... * From :math:`E_{i} \\rightarrow E_{i+1}`, :math:`f(E)` evaluates to :math:`f_i` * ... * From :math:`E_{N-1} \\rightarrow E_N`, :math:`f(E)` evaluates to :math:`f_{N-1}` * Above :math:`E_N`, :math:`f(E)` evaluates to :math:`0.0` ''' # determine where to get the settings for the potentially mirrored second axis if self.matrix.axes[1].style == 'link': axis1index = 2 else: axis1index = 1 # setup the old axes in a form we can (ab)use in the XYs1d class axes2_ = axesModule.axes( labelsUnits={1:( self.matrix.axes[2].label, self.matrix.axes[2].unit ),0:( 'dummy', '' )} ) axes1_ = axesModule.axes( labelsUnits={1:( self.matrix.axes[axis1index].label, self.matrix.axes[axis1index].unit ),0:( 'dummy', '' )} ) # define basis functions for the rows and columns basis2 = XYsModule.XYs1d( axes=axes2_, data=[ ( x, 0.0 ) for x in self.matrix.axes[2].values ], interpolation='flat' ) basis1 = XYsModule.XYs1d( axes=axes1_, data=[ ( x, 0.0 ) for x in self.matrix.axes[axis1index].values ], interpolation='flat' ) basis2 = basis2.convertAxisToUnit( 1, groupUnit[0] ) basis1 = basis1.convertAxisToUnit( 1, groupUnit[1] ) # build the regrouping matrices for the two bases w0 = [] for idx in range( self.matrix.array.shape[0] ): basis2[idx] = ( basis2[idx][0], 1.0 ) w0.append( basis2.groupOneFunction( groupBoundaries[0], norm = 'dx' ) ) basis2[idx] = ( basis2[idx][0], 0.0 ) w0 = numpy.mat( w0 ) w1 = [] for j in range( self.matrix.array.shape[1] ): basis1[j] = ( basis1[j][0], 1.0 ) w1.append( basis1.groupOneFunction( groupBoundaries[1], norm = 'dx' ) ) basis1[j] = ( basis1[j][0], 0.0 ) w1 = numpy.mat( w1 ) # set up the regrouped covariance matrix grouped = copy.copy( self ) grouped.matrix.axes[2].data = groupBoundaries[0] grouped.matrix.axes[1].data = groupBoundaries[1] grouped.matrix.axes[2].unit = groupUnit[0] grouped.matrix.axes[1].unit = groupUnit[1] odata = numpy.mat( self.matrix.array.constructArray() ) gdata = w0.T * odata * w1 trigdata = gdata[numpy.tri(gdata.shape[0])==1.0].tolist()[0] grouped.matrix.array = arrayModule.full(shape=gdata.shape,data=trigdata,symmetry=arrayModule.symmetryLowerToken) return grouped