def toENDF6(self, endfMFList, flags, targetInfo, verbosityIndent=''): """ go back to ENDF format """ ZAM, AWT = targetInfo['ZA'], targetInfo['mass'] NIS, ABN = 1, 1.0 ZAI = ZAM # assuming one isotope/file MTL = 0 # mtl=1 sections are handled in lumpedCovariance for section_ in self.modelParameterCovariances: section_.toENDF6(endfMFList, flags, targetInfo, verbosityIndent) sections = self.sections[:] # sort covariances by MF/MT: mfmts = [] for section_ in sections: mfmts.append(map(int, section_.rowData['ENDF_MFMT'].split(','))) if len(mfmts) == 0: return mfs, mts = zip(*mfmts) zipList = zip(mfs, mts, sections) idx = 0 while idx < len(zipList): mf, mt, covar = zipList[idx] thisMFMT = [a[2] for a in zipList if a[:2] == (mf, mt)] idx += len(thisMFMT) if mf in (31, 33): endf = [ endfFormats.endfHeadLine(ZAM, AWT, 0, MTL, 0, len(thisMFMT)) ] elif mf == 34: if isinstance(thisMFMT[0][targetInfo['style']], distributionsModule.LegendreOrderCovarianceForm): LTT = 1 NMT1 = len(thisMFMT) endf = [endfFormats.endfHeadLine(ZAM, AWT, 0, LTT, 0, NMT1)] elif mf == 35: endf = [ endfFormats.endfHeadLine(ZAM, AWT, 0, MTL, len(thisMFMT), 0) ] elif mf == 40: endf = [endfFormats.endfHeadLine(ZAM, AWT, 0, 0, len(thisMFMT), 0)] for section_ in thisMFMT: MAT1 = 0 form = section_[targetInfo['style']] if section_.columnData and isinstance( section_.columnData.link, sectionModule.externalReaction): otherTarget = section_.columnData.link.target from fudge.legacy.converting import endf_endl ZA, MAT1 = endf_endl.ZAAndMATFromParticleName(otherTarget) if mf == 34: L1s = [subsec.L1 for subsec in form] L2s = [subsec.L2 for subsec in form] NL = len(set(L1s)) NL1 = len(set(L2s)) if section_.columnData: raise NotImplemented # cross-reaction or cross-material MT1 = mt endf += [ endfFormats.endfHeadLine(0.0, 0.0, MAT1, MT1, NL, NL1) ] if mf == 40: rowData = section_.rowData if type(rowData) is str: raise Exception("Don't string me along!") # FIXME else: quant = rowData.link if isinstance(quant, sectionModule.reactionSum): quant = quant.reactions[0].link product = quant.findAttributeInAncestry('outputChannel')[0] QI = quant.findAttributeInAncestry('getQ')('eV') LFS, level = 0, 0. if (hasattr(product.particle, 'getLevelIndex')): LFS = product.particle.getLevelIndex() level = product.getLevelAsFloat('eV') QM = QI + level IZAP = product.particle.getZ_A_SuffixAndZA()[-1] NL = 1 endf += [ endfFormats.endfHeadLine(QM, QI, IZAP, LFS, 0, NL) ] XMF1, XLFS1, NC, NI = 10, LFS, 0, 1 endf += [ endfFormats.endfHeadLine(XMF1, XLFS1, MAT1, mt, NC, NI) ] targetInfo['MAT1'] = MAT1 targetInfo['dataPointer'] = [section_.rowData, section_.columnData] endf += form.toENDF6(flags, targetInfo) targetInfo.dict.pop('dataPointer') targetInfo.dict.pop('MAT1') endf.append(endfFormats.endfSENDLineNumber()) if mt not in endfMFList[mf]: endfMFList[mf][mt] = [] endfMFList[mf][mt] += endf # also add ENDF-style pointers for lumped covariance data: for reactionSum in self.reactionSums: MT1 = reactionSum.ENDF_MFMT[1] if MT1 not in range(850, 872): continue for link in reactionSum.reactions: mf, mt = map(int, link['ENDF_MFMT'].split(',')) endfMFList[mf][mt] = [ endfFormats.endfHeadLine(ZAM, AWT, 0, MT1, 0, 0), endfFormats.endfSENDLineNumber() ] return
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 toENDF6( self, style, flags, verbosityIndent = '', covarianceSuite = None ) : evaluatedStyle = self.styles.getEvaluatedStyle( ) if( evaluatedStyle is None ) : raise ValueError( 'no evaluation style found' ) if( flags['verbosity'] >= 10 ) : print '%s%s' % ( verbosityIndent, self.inputParticlesToReactionString( suffix = " -->" ) ) verbosityIndent2 = verbosityIndent + ' ' * ( len( self.inputParticlesToReactionString( suffix = " -->" ) ) + 1 ) projectile, target = self.projectile, self.target projectileZA = projectile.getZ_A_SuffixAndZA( )[-1] IPART = projectileZA if( projectile.name == 'e-' ) : IPART = 11 targetZA, MAT = endf_endl.ZAAndMATFromParticleName( target.name ) targetZ, targetA = divmod( targetZA, 1000 ) targetInfo = processingInfoModule.tempInfo( ) targetInfo['style'] = style targetInfo['reactionSuite'] = self targetInfo['ZA'] = targetZA if( self.particles.hasID( 'n' ) ) : # Need neutron mass in eV/c**2, but it may not be in the particle list. targetInfo['neutronMass'] = self.getParticle( 'n' ).getMass( 'eV/c**2' ) else : neutronAmu = masses.getMassFromZA( 1 ) targetInfo['neutronMass'] = PQU.PQU( neutronAmu, 'amu' ).getValueAs('eV/c**2') if( isinstance( target, fudge.gnd.xParticle.element ) ) : targetInfo['mass'] = elementalMass[targetZA] else : targetInfo['mass'] = target.getMass( 'eV/c**2' ) / targetInfo['neutronMass'] try : targetInfo['LIS'] = target['levelIndex'] except : targetInfo['LIS'] = 0 targetInfo['metastables'] = [] targetInfo['LISO'] = 0 for key, alias in self.aliases.items( ) : if( alias.hasAttribute( 'nuclearMetaStable' ) ) : targetInfo['metastables'].append( alias.getValue() ) if( alias.getValue() == target.name ) : targetInfo['LISO'] = int( alias.getAttribute( 'nuclearMetaStable' ) ) MAT += targetInfo['LISO'] if( self.MAT is not None ) : MAT = self.MAT ITYPE = 0 # Other ITYPE sublibraries not yet supported. BRB is this still true for reaction in self.reactions : if( 500 <= reaction.ENDF_MT < 573 ) : ITYPE = 3 targetInfo['crossSectionMF'] = { 0 : 3, 3 : 23 }[ITYPE] targetInfo['delayedRates'] = [] targetInfo['totalDelayedNubar'] = None targetInfo['MTs'], targetInfo['MF8'], targetInfo['LRs'] = {}, {}, {} endfMFList = { 1 : { 451 : [] }, 2 : {}, 3 : {}, 4 : {}, 5 : {}, 6 : {}, 8 : {}, 9 : {}, 10 : {}, 12 : {}, 13 : {}, 14 : {}, 15 : {}, 23 : {}, 26 : {}, 27 : {}, 31 : {}, 32 : {}, 33 : {}, 34 : {}, 35 : {}, 40 : {} } if( self.resonances is not None ) : # Add resonances, independent of reaction channels self.resonances.toENDF6( endfMFList, flags, targetInfo, verbosityIndent=verbosityIndent2 ) targetInfo['production_gammas'] = {} for reaction in self : reaction.toENDF6( endfMFList, flags, targetInfo, verbosityIndent = verbosityIndent2 ) gndToENDF6Module.upDateENDFMF8Data( endfMFList, targetInfo ) for MT, production_gammas in targetInfo['production_gammas'].items( ) : MF, production_gammas = production_gammas[0], production_gammas[1:] for productionReaction in production_gammas : gammas = [ gamma for gamma in productionReaction.outputChannel ] targetInfo['crossSection'] = productionReaction.crossSection[targetInfo['style']] gndToENDF6Module.gammasToENDF6_MF12_13( MT, MF, endfMFList, flags, targetInfo, gammas ) for particle in self.particles : # gamma decay data. if( isinstance( particle, fudge.gnd.xParticle.isotope ) ) : for level in particle : if( level.gammas ) : # non-empty gamma information for baseMT in [ 50, 600, 650, 700, 750, 800 ] : residualZA = endf_endl.ENDF_MTZAEquation( projectileZA, targetZA, baseMT )[0][-1] if( nuclear.nucleusNameFromZA( residualZA ) == particle.name ) : break level.toENDF6( baseMT, endfMFList, flags, targetInfo ) MFs = sorted( endfMFList.keys( ) ) endfList = [] totalNubar = None totalDelayedNubar = targetInfo['totalDelayedNubar'] if( 455 in endfMFList[5] ) : MF5MT455s = endfMFList[5][455] endfMFList[1][455] = [ endfFormatsModule.endfHeadLine( targetZA, targetInfo['mass'], 0, 2, 0, 0 ) ] # Currently, only LDG = 0, LNU = 2 is supported. endfMFList[1][455] += [ endfFormatsModule.endfHeadLine( 0, 0, 0, 0, len( targetInfo['delayedRates'] ), 0 ) ] endfMFList[1][455] += endfFormatsModule.endfDataList( targetInfo['delayedRates'] ) multiplicityModule.fissionNeutronsToENDF6( 455, totalDelayedNubar, endfMFList, flags, targetInfo ) MF5MT455List = [ endfFormatsModule.endfHeadLine( targetZA, targetInfo['mass'], 0, 0, len( MF5MT455s ), 0 ) ] for MF5MT455 in MF5MT455s : MF5MT455List += MF5MT455 if( len( MF5MT455s ) == 0 ) : del endfMFList[5][455] else : endfMFList[5][455] = MF5MT455List + [ endfFormatsModule.endfSENDLineNumber( ) ] if( 'promptNubar' in targetInfo.dict ) : promptNubar = targetInfo['promptNubar'] multiplicityModule.fissionNeutronsToENDF6( 456, promptNubar, endfMFList, flags, targetInfo ) totalNubar = promptNubar try : if( not( totalDelayedNubar is None ) ) : totalNubar = totalNubar + totalDelayedNubar except : # The following is a kludge for some "bad" data. if( ( totalNubar.domainMax( unitTo = 'MeV' ) == 30. ) and ( totalDelayedNubar.domainMax( unitTo = 'MeV' ) == 20. ) ) : totalDelayedNubar[-1] = [ totalNubar.domainMax( ), totalDelayedNubar.getValue( totalDelayedNubar.domainMax( ) ) ] totalNubar = totalNubar + totalDelayedNubar elif( 'totalNubar' in targetInfo.dict ) : totalNubar = targetInfo['totalNubar'] if( totalNubar is not None ) : multiplicityModule.fissionNeutronsToENDF6( 452, totalNubar, endfMFList, flags, targetInfo ) if( covarianceSuite ) : covarianceSuite.toENDF6( endfMFList, flags, targetInfo ) endfDoc = self.documentation.get( 'endfDoc' ) if( endfDoc is None ) : docHeader2 = [ ' %2d-%-2s-%3d LLNL EVAL-OCT03 Unknown' % ( targetZ, fudge.particles.nuclear.elementSymbolFromZ( targetZ ), targetA ), ' DIST-DEC99 19990101 ', '----ENDL MATERIAL %4d' % MAT, '-----INCIDENT %s DATA' % { 1 : 'NEUTRON', 1001 : 'PROTON', 1002 : 'DEUTERON', 1003 : 'TRITON', 2003 : 'HELION', 2004 : 'ALPHA' }[projectileZA], '------ENDF-6 FORMAT' ] endfDoc = [ 'LLNL ENDL file translated to ENDF6 by FUDGE.', '' ' ************************ C O N T E N T S ***********************' ] else : docHeader2 = [] endfDoc = endfDoc.getLines( ) # update the documentation, including metadata on first 4 lines: try : self.getReaction( 'fission' ) LFI = True except KeyError : LFI = False LRP = -1 if( self.resonances is not None ) : if( self.resonances.scatteringRadius ) : LRP = 0 elif( self.resonances.reconstructCrossSection ) : LRP = 1 elif( self.resonances.unresolved and not( self.resonances.resolved ) and self.resonances.unresolved.tabulatedWidths.forSelfShieldingOnly ) : LRP = 1 else : LRP = 2 EMAX = max( [ reaction.crossSection.domainMax( unitTo = 'eV' ) for reaction in self.reactions ] ) temperature = self.styles[style].temperature.getValueAs( 'K' ) library = evaluatedStyle.library version = evaluatedStyle.version if( library == 'ENDL' ) : # Additional ENDF meta-data. If the library is unknown, use NLIB = -1 NVER, LREL, NMOD = 1, 1, 1 NLIB = -1 else : NVER, LREL, NMOD = map( int, version.split( '.' ) ) # Version stored as '7.2.1' NLIB = { "ENDF/B" : 0, "ENDF/A" : 1, "JEFF" : 2, "EFF" : 3, "ENDF/B (HE)" : 4, "CENDL" : 5, "JENDL" : 6, "SG-23" : 21, "INDL/V" : 31, "INDL/A" : 32, "FENDL" : 33, "IRDF" : 34, "BROND (IAEA version)" : 35, "INGDB-90" : 36, "FENDL/A" : 37, "BROND" : 41 }.get( library, -1 ) NFOR = 6 # ENDF-6 format NSUB = 10 * IPART + ITYPE LDRV = 0 STA = 0 if( isinstance( self.target, fudge.gnd.xParticle.nuclearLevel ) or self.target.attributes.get( 'unstable' ) ) : STA = 1 if( targetInfo['LISO'] ) : STA = 1 levelIndex, level_eV = 0, 0. if( hasattr( self.target, 'getLevelIndex' ) ) : levelIndex, level_eV = self.target.getLevelIndex( ), self.target.getLevelAsFloat( 'eV' ) docHeader = [ endfFormatsModule.endfHeadLine( targetZA, targetInfo['mass'], LRP, LFI, NLIB, NMOD ), endfFormatsModule.endfHeadLine( level_eV, STA, levelIndex, targetInfo['LISO'], 0, NFOR ), endfFormatsModule.endfHeadLine( self.projectile.getMass( 'eV/c**2' ) / targetInfo['neutronMass'], EMAX, LREL, 0, NSUB, NVER ), endfFormatsModule.endfHeadLine( temperature, 0, LDRV, 0, len( endfDoc ), -1 ) ] new_doc = fudge.gnd.documentation.documentation( 'endf', '\n'.join( docHeader + docHeader2 + endfDoc ) ) endfMFList[1][451] += endfFormatsModule.toEndfStringList( new_doc ) return( endfFormatsModule.endfMFListToFinalFile( endfMFList, MAT, lineNumbers = True ) )
def endfFileToGND(fileName, useFilesQAlways=True, singleMTOnly=None, evaluation=None, MTs2Skip=None, parseCrossSectionOnly=False, toStdOut=True, toStdErr=True, logFile=None, skipBadData=False, doCovariances=True, verboseWarnings=False, verbose=1, reconstructResonances=True, **kwargs): logs = logFiles(toStdOut=toStdOut, toStdErr=toStdErr, logFile=logFile, defaultIsStderrWriting=False) header, MAT, MTDatas = endfFileToGNDMisc.parseENDFByMT_MF(fileName, logFile=logs) styleName = 'eval' reconstructedStyleName = 'recon' if MTs2Skip is None: MTs2Skip = [] # Parse the ENDF documentation section info = readMF1MT451(MAT, MTDatas, styleName=styleName, logFile=logs, verboseWarnings=verboseWarnings, **kwargs) # OK, now decide what to do # First batch of ITYPE's are the special cases if (info.ITYPE == 2): # Thermal scattering law data return (ENDF_ITYPE_2.ITYPE_2(MTDatas, info, verbose=verbose)) elif (info.ITYPE == 4): # Decay data, including SFPY return (ENDF_ITYPE_4.ITYPE_4(MTDatas, info, verbose=verbose)) elif (info.ITYPE == 5): # Decay data, including SFPY return (ENDF_ITYPE_5.ITYPE_5(MTDatas, info, verbose=verbose)) elif (info.ITYPE == 6): # Atomic relaxation data if (info.NSUB not in [6]): raise ValueError('For ITYPE = %d, invalid NSUB = %s' % (info.ITYPE, info.NSUB)) return (ENDF_ITYPE_6.ITYPE_6(info.targetZA / 1000, MTDatas, info, verbose=verbose)) # Second batch of ITYPE's are general transport data if (info.LIS != 0): levelIndex = info.LIS if (info.ITYPE in [ 0, 1, 9 ]): # Nuclear transport data (g, n, p, d, t, h, a), including FPY target = toGNDMisc.getTypeNameGamma(info, info.targetZA, level=info.level, levelIndex=info.levelIndex) targetID = target.id if ((info.STA != 0)): halflife = halflifeModule.string(info.PoPsLabel, halflifeModule.UNSTABLE, halflifeModule.baseUnit) target = info.PoPs[targetID] if (isinstance(target, nuclearLevelModule.particle)): target = target.nucleus if (isinstance(target, isotopeModule.suite)): target = target[0].nucleus if (len(target.halflife) == 0): target.halflife.add(halflife) elif (info.ITYPE == 3): # Atomic transport data (e, x) targetZ = info.targetZA / 1000 targetID = chemicalElementModule.symbolFromZ[targetZ] targetName = chemicalElementModule.nameFromZ[targetZ] info.PoPs.add( chemicalElementModule.suite(targetID, targetZ, targetName)) else: raise ValueError("Unsupported ITYPE = %s" % info.ITYPE) # Add alias if needed for metastable target ZA2, MAT2 = endf_endlModule.ZAAndMATFromParticleName(targetID) MAT2 += info.LISO if (MAT2 != info.MAT): info.logs.write( " WARNING: ENDF MAT = %s not as expected (i.e., %s).\n" % (info.MAT, MAT2), stderrWriting=True) if (info.LISO != 0): targetBaseName = targetID.split('_')[0] aliasName = alias.aliases.nuclearMetaStableName( targetBaseName, info.LISO) info.PoPs.add( PoPsAliasModule.metaStable(aliasName, targetID, info.LISO)) # Compute the reconstructed and evaluated Styles evaluatedStyle = fudge.gnd.styles.evaluated( styleName, '', physicalQuantityModule.temperature( PQUModule.pqu_float.surmiseSignificantDigits( info.targetTemperature), 'K'), info.library, info.libraryVersion, date=info.Date) if (evaluation is None): evaluation = "%s-%d.%d" % (info.library, info.NVER, info.LREL) info.reconstructedStyle = stylesModule.crossSectionReconstructed( reconstructedStyleName, derivedFrom=evaluatedStyle.label, date="2016-11-06") # Stuff for handling transport data info.printBadNK14 = True info.continuumSpectraFix = False info.ignoreMF10Fission = False options = [ 'printBadNK14', 'continuumSpectraFix', 'ignoreBadDate', 'ignoreMF10Fission' ] for option in kwargs: if (option not in options): raise DeprecationWarning('invalid deprecated option "%s"' % option) setattr(info, option, kwargs[option]) info.evaluatedStyle = evaluatedStyle info.reconstructedAccuracy = 0.001 info.MF12_LO2 = {} info.AWR_mode = None info.particleSpins = {} info.missingTwoBodyMasses = {} info.MF4ForNonNeutrons = [] projectile = toGNDMisc.getTypeNameGamma(info, info.projectileZA) # Set up the reactionSuite reactionSuite = reactionSuiteModule.reactionSuite( projectile.id, targetID, evaluation, style=info.evaluatedStyle, documentation=info.documentation, MAT=MAT, PoPs=info.PoPs) MTDatas[451][1] = MTDatas[451][1][:4 + info.NWD] info.reactionSuite = reactionSuite info.PoPs = reactionSuite.PoPs info.target = reactionSuite.target # Set up the covarianceSuite, if needed, and do other ITYPE-specific calculations covarianceSuite = None if ((info.ITYPE == 0) or (info.ITYPE == 9)): doRaise = info.NSUB not in { 0: [0, 10, 10010, 10020, 10030, 20030, 20040], 9: [19] }[info.ITYPE] if (doRaise): raise ValueError('For ITYPE = %d, invalid NSUB = %s' % (info.ITYPE, info.NSUB)) covarianceSuite = ENDF_ITYPE_0.ITYPE_0( MTDatas, info, reactionSuite, singleMTOnly, MTs2Skip, parseCrossSectionOnly, doCovariances, verbose, reconstructResonances=reconstructResonances) elif (info.ITYPE in [3, 1]): if (info.NSUB not in [3, 11, 113]): raise ValueError('For ITYPE = %d, invalid NSUB = %s' % (info.ITYPE, info.NSUB)) ENDF_ITYPE_3.ITYPE_3(MTDatas, info, reactionSuite, singleMTOnly, parseCrossSectionOnly, verbose=verbose) # Fill up the reactionSuite for reaction in reactionSuite.reactions: addUnspecifiedDistributions(info, reaction.outputChannel) for production in reactionSuite.productions: addUnspecifiedDistributions(info, production.outputChannel) PoPs = reactionSuite.PoPs lightMasses = { # atomic masses in amu, taken from AME2012 (http://www.nndc.bnl.gov/masses/mass.mas12) 'n': 1.00866491585, 'H1': 1.00782503223, 'H2': 2.01410177812, 'H3': 3.01604927791, 'He3': 3.01602932008, 'He4': 4.00260325413, } for product1ID in info.missingTwoBodyMasses: try: product1Mass = PoPs[product1ID].getMass('amu') except Exception as exc: # FIXME currently getMass raises Exception, should probably be KeyError instead if product1ID in lightMasses: product1Mass = lightMasses[product1ID] PoPs[product1ID].mass.add( massModule.double( info.PoPsLabel, product1Mass, quantityModule.stringToPhysicalUnit('amu'))) else: raise exc massPTmP1 = PoPs[reactionSuite.projectile].getMass( 'amu' ) + PoPs[reactionSuite.target].getMass( 'amu' ) - \ product1Mass summedQM = 0 for product2ID, QM in info.missingTwoBodyMasses[product1ID]: summedQM += QM mass = massPTmP1 - PQUModule.PQU( summedQM / len(info.missingTwoBodyMasses[product1ID]), 'eV/c**2').getValueAs('amu') mass = massModule.double(info.PoPsLabel, mass, quantityModule.stringToPhysicalUnit('amu')) residual = reactionSuite.PoPs[info.missingTwoBodyMasses[product1ID][0] [0]] if (len(residual.mass) == 0): residual.mass.add(mass) # Did we have trouble? if (len(info.MF4ForNonNeutrons) > 0): print ' WARNING: MF=4 data for non-neutron product: MTs = %s' % sorted( info.MF4ForNonNeutrons) if (len(info.doRaise) > 0 and not skipBadData): info.logs.write('\nRaising due to following errors:\n') for err in info.doRaise: info.logs.write(err + '\n') raise Exception('len( info.doRaise ) > 0') return ({ 'reactionSuite': reactionSuite, 'covarianceSuite': covarianceSuite, 'errors': info.doRaise, 'info': info })
def endfFileToGND( fileName, xenslIsotopes = None, useFilesQAlways = True, singleMTOnly = None, MTs2Skip = None, parseCrossSectionOnly = False, toStdOut = True, toStdErr = True, logFile = None, skipBadData = False, doCovariances = True, verboseWarnings = False, verbose = 1, **kwargs ) : logs = logFiles( toStdOut = toStdOut, toStdErr = toStdErr, logFile = logFile, defaultIsStderrWriting = False ) header, MAT, MTDatas = endfFileToGNDMisc.parseENDFByMT_MF( fileName, logFile = logs ) styleName = 'eval' reconstructedStyleName = 'recon' if MTs2Skip is None: MTs2Skip = [] targetZA, targetMass, LRP, LFI, NLIB, NMOD = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MTDatas[451][1][0], logFile = logs ) targetZA = int( targetZA ) # Target's ZA LRP = int( LRP ) # Resonance parameter data info LFI = int( LFI ) # Is fission present NLIB = int( NLIB ) # What library (e.g., 0 = ENDF/B NMOD = int( NMOD ) # Version modification flag isNaturalTarget = ( targetZA % 1000 ) == 0 targetExcitationEnergy, STA, LIS, LISO, dummy, NFOR = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MTDatas[451][1][1], logFile = logs ) STA = int( STA ) # Is nucleus unstable LIS = int( LIS ) # Excitation number LISO = int( LISO ) # Isomeric state number NFOR = int( NFOR ) # Must be 6 for ENDF/B6 format if (NFOR != 6): print (" WARNING: endfFileToGND only supports ENDF-6 format. This file has unsupported NFOR=%d" % NFOR) projectileMass, dummy, LREL, dummy, NSUB, NVER = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MTDatas[451][1][2], logFile = logs ) NSUB = int( NSUB ) # 10 * ZA + iType for projectile NVER = int( NVER ) # Evaluation version number LREL = int( LREL ) # Evaluation sub-version number IPART, ITYPE = NSUB / 10, NSUB % 10 projectileZA = IPART if( projectileZA == 11 ) : projectileZA = 9 targetTemperature, dummy, LDRZ, dummy, NWD, NXC = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MTDatas[451][1][3], logFile = logs ) LDRZ = int( LDRZ ) # Primary or special evaluation of this material NWD = int( NWD ) # NXC = int( NXC ) # library = { 0: "ENDF/B", 1: "ENDF/A", 2: "JEFF", 3: "EFF", 4: "ENDF/B (HE)", 5: "CENDL", 6: "JENDL", 21: "SG-23", 31: "INDL/V", 32: "INDL/A", 33: "FENDL", 34: "IRDF", 35: "BROND (IAEA version)", 36: "INGDB-90", 37: "FENDL/A", 41: "BROND", }.get( NLIB, 'Unknown' ) libraryVersion = "%d.%d.%d" % ( NVER, LREL,NMOD ) transportables = [ 'n', 'gamma' ] # ???? Check this with Gerry? info = toGNDMisc.infos( styleName, xenslIsotopes, transportables = transportables ) info.doRaise = [] try : Date = endfFileToGNDMisc.getENDFDate( MTDatas[451][1][4][22:33] ) except Exception as e : info.doRaise.append( str(e) ) import datetime Date = datetime.datetime.today().strftime("%Y-%m-%d") author = MTDatas[451][1][4][33:66] evaluatedStyle = fudge.gnd.styles.evaluated( styleName, PQU.PQU( PQU.pqu_float.surmiseSignificantDigits( targetTemperature ), 'K' ), library, libraryVersion, date = Date ) info.Date = Date info.verboseWarnings = verboseWarnings info.printBadNK14 = True info.continuumSpectraFix = False options = [ 'printBadNK14', 'continuumSpectraFix' ] for option in kwargs : if( option not in options ) : raise Exception( 'invalid deprecated option "%s"' % option ) setattr( info, option, kwargs[option] ) info.logs = logs info.MAT = MAT info.LRP = LRP info.NLIB = NLIB info.evaluation = library info.NMOD = NMOD info.NVER = NVER info.LREL = LREL info.evaluatedStyle = evaluatedStyle info.reconstructedStyle = reconstructedStyleName info.reconstructedAccuracy = 0.001 info.projectile = { 0 : 'g', 1 : 'n', 11 : 'e-', 1001 : 'H1', 1002 : 'H2', 1003 : 'H3', 2003 : 'He3', 2004 : 'He4' }[IPART] info.projectileZA = projectileZA info.ZA_AWRMasses = {} info.ZA_AWRMasses[projectileZA] = { projectileMass : 1 } info.ZA_AWRMasses[targetZA] = { targetMass : 1 } info.ZAMasses[projectileZA] = info.masses.getMassFromZA( projectileZA ) info.ZAMasses[targetZA] = targetMass * info.masses.getMassFromZA( 1 ) info.ZAMasses[1] = info.masses.getMassFromZA( 1 ) # always need neutron mass in table info.MF12_LO2 = {} info.AWR_mode = None # info.AWR_mode = open( 'AWR_mode.out', 'w' ) # Used by BRB to print masses for testing. if( ITYPE == 6 ) : if( NSUB not in [ 6 ] ) : raise Exception( 'For ITYPE = %d, invalid NSUB = %s' % ( ITYPE, NSUB ) ) return( ENDF_ITYPE_6.ITYPE_6( targetZA / 1000, MTDatas, info, verbose = True ) ) projectile = toGNDMisc.getTypeNameGamma( info, projectileZA ) info.level = targetExcitationEnergy levelIndex = None if( LIS != 0 ) : levelIndex = LIS if( ITYPE in [ 0, 9 ] ) : target = toGNDMisc.getTypeNameGamma( info, targetZA, level = info.level, levelIndex = levelIndex ) if( ( STA != 0 ) and not isinstance( target, fudge.gnd.xParticle.nuclearLevel ) ) : target.attributes['unstable'] = True elif( ITYPE in [ 1, 3 ] ) : elementSymbol = fudge.particles.nuclear.elementSymbolFromZ( targetZA / 1000 ) target = fudge.gnd.xParticle.element( elementSymbol ) else : raise ValueError( "Unsupported ITYPE = %s" % ITYPE ) ZA2, MAT2 = endf_endlModule.ZAAndMATFromParticleName( target.name ) MAT2 += LISO if( MAT2 != MAT ) : info.logs.write( " WARNING: ENDF MAT = %s not as expected (i.e., %s).\n" % \ ( MAT, MAT2 ), stderrWriting = True ) documentation = fudge.gnd.documentation.documentation( 'endfDoc', '\n'.join( MTDatas[451][1][4:4+NWD] ) ) reactionSuite = fudge.gnd.reactionSuite.reactionSuite( projectile, target, particleList = info.particleList, style = evaluatedStyle, documentation = documentation, MAT = MAT ) if( LISO != 0 ) : targetBaseName = target.name.split( '_' )[0] aliasName = alias.aliases.nuclearMetaStableName( targetBaseName, LISO ) reactionSuite.addNuclearMetaStableAlias( targetBaseName, target.name, LISO ) info.setReactionSuite( reactionSuite ) info.target = reactionSuite.target info.targetZA = targetZA info.targetLevel = LIS MTDatas[451][1] = MTDatas[451][1][:4+NWD] covarianceSuite = None if( ( ITYPE == 0 ) or ( ITYPE == 9 ) ) : doRaise = NSUB not in { 0 : [ 0, 10, 10010, 10020, 10030, 20030, 20040 ], 9 : [ 19 ] }[ITYPE] if( doRaise ) : raise ValueError( 'For ITYPE = %d, invalid NSUB = %s' % ( ITYPE, NSUB ) ) covarianceSuite = ENDF_ITYPE_0.ITYPE_0( MTDatas, info, reactionSuite, singleMTOnly, MTs2Skip, parseCrossSectionOnly, doCovariances, verbose ) elif( ITYPE == 3 ) : if( NSUB not in [ 3, 113 ] ) : raise ValueError( 'For ITYPE = %d, invalid NSUB = %s' % ( ITYPE, NSUB ) ) ENDF_ITYPE_3.ITYPE_3( MTDatas, info, reactionSuite, singleMTOnly, parseCrossSectionOnly, verbose = True ) if( len( info.doRaise ) > 0 and not skipBadData ) : info.logs.write( '\nRaising due to following errors:\n' ) for err in info.doRaise : info.logs.write( err + '\n' ) raise Exception( 'len( info.doRaise ) > 0' ) for reaction in reactionSuite.reactions : addUnspecifiedDistributions( info, reaction.outputChannel ) for production in reactionSuite.productions : addUnspecifiedDistributions( info, production.outputChannel ) return( { 'reactionSuite' : reactionSuite, 'covarianceSuite' : covarianceSuite, 'errors' : info.doRaise, 'info':info } )
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, PQUModule.PQU))): temperature = PQUModule.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() processingTime = [2014, 5, 10] 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_endlModule.ZAAndMATFromParticleName(target.name)[1] MAT_ID = ' mat %d' % MAT evaluated = self.styles.getEvaluatedStyle() HK = '%2d-%s at %.1fK from %s-%s Fudge.toACE' % \ ( targetZ, target.name, temperature_K, evaluated.library, evaluated.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] MTR, 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'].domainUnitConversionFactor( 'MeV') * MTData['ESZ'].domainMin break axes = axesModule.axes(labelsUnits={1: ('', 'MeV'), 0: ('', 'b')}) totalXSec = XYsModule.XYs1d(data=[], axes=axes, accuracy=1e-3) absorptionXSec = XYsModule.XYs1d(data=[], axes=axes, accuracy=1e-3) sortedMTs = sorted([[MT_MTData[0], i1] for i1, MT_MTData in enumerate(productData) ]) # Sort MTs like NJOY. delayedNeutronDatas = [] for MT, i1 in sortedMTs: _MT, MTData = productData[i1] XSec = MTData['ESZ'] XSec = XSec.convertAxisToUnit(1, 'MeV') XSec = XSec.convertAxisToUnit(0, 'b') neutronDatas = MTData['n'] multiplicity = 0 if (MT == 2): elasticXSec = XSec if (len(neutronDatas) > 1): raise Exception( 'Only one type of neutron data are supported for the elastic reaction.' ) if (len(neutronDatas) > 0): neutronAngular.append((MT, neutronDatas[0]['angularData'])) else: MTR.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 _neutronDatas = [] for neutronData in neutronDatas: product = neutronData['product'] if ((product.attributes['emissionMode'] == tokensModule.promptToken) or (product.attributes['emissionMode'] == 'total')): totalPresent = product.attributes[ 'emissionMode'] == 'total' NU_prompt = neutronData['multiplicity'] _neutronDatas = [] else: delayedNeutronDatas.append(neutronData) neutronDatas = _neutronDatas if (NU_prompt is None): raise Exception('Missing prompt neutron') if (len(delayedNeutronDatas) > 0): if (totalPresent): raise Exception( 'Total nu_bar present and delayed neutron data.' ) NU_total = NU_prompt for neutronData in delayedNeutronDatas: 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 = specialMF6Module.neutrons( neutronDatas) if (isinstance(neutronMultiplicity, float)): if (neutronMultiplicity != int(neutronMultiplicity)): raise Exception('Bad neutronMultiplicity = %e' % neutronMultiplicity) neutronMultiplicity = int(neutronMultiplicity) if (not (isinstance(neutronMultiplicity, int))): nonFissionEnergyDependentNeutronMultiplicitiesIndex += 1 nonFissionEnergyDependentNeutronMultiplicities.append([ MT, nonFissionEnergyDependentNeutronMultiplicitiesIndex, neutronMultiplicity ]) neutronMultiplicity = nonFissionEnergyDependentNeutronMultiplicitiesIndex if (frame == standardsModule.frames.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, energyModule.NBodyPhaseSpace)): angularData = None neutronAngular.append((MT, angularData)) neutronEnergies.append( [MT, XSec.domainMin, XSec.domainMax, energyData]) TYP.append(neutronMultiplicity) totalXSec = elasticXSec + totalXSec energyGrid, totalSigma = [], [] e1s = "" for energy, sigma in totalXSec: e2s = floatFormat % energy if (e1s == e2s): continue # Remove duplicate energy values. energyGrid.append(energy) totalSigma.append(sigma) e1s = e2s annotates, XSS = [], [] # 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, mapCrossSectionToGrid(energyGrid, absorptionXSec)) updateXSSInfo('elastic cross section', annotates, XSS, mapCrossSectionToGrid(energyGrid, 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 MTR block. NXS[4 - 1] = len(MTR) JXS[3 - 1] = len(XSS) + 1 updateXSSInfo('MTR', annotates, XSS, MTR) # 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, i1 in sortedMTs: _MT, MTData = productData[i1] 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, (angularModule.XYs2d, angularEnergyModule.angularFor_angularEnergy))): LAND.append(length + 1) length += 2 * len(angular) + 1 energies_in = [len(angular)] LCs, Ps = [], [] for xys in angular: energy_in = PQUModule.PQU( xys.value, angular.axes[2].unit).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) # 24, 25, 26 and 27) Added the DNU, BDD, DNEDL and DNED blocks if (len(delayedNeutronDatas) > 0): skipDelayed = False for delayedNeutronData in delayedNeutronDatas: if (delayedNeutronData['energyData'] is None): skipDelayed = True if (skipDelayed): delayedNeutronDatas = [] if (len(delayedNeutronDatas) > 0): delayedFissionNeutrons = [] axes = axesModule.axes(labelsUnits={1: ('', 'MeV'), 0: ('', '')}) totolDelayedMultiplicity = XYsModule.XYs1d(data=[], axes=axes, accuracy=1e-3) for delayedNeutronData in delayedNeutronDatas: decayRate = 1e-8 * delayedNeutronData['product'].attributes[ 'decayRate'].getValueAs('1/s') multiplicity = delayedNeutronData['multiplicity'] if (not (isinstance(multiplicity, multiplicityModule.XYs1d))): raise Exception('fix me') if (multiplicity.interpolation != standardsModule.interpolation.linlinToken): raise Exception('fix me') multiplicity = multiplicity.convertAxisToUnit(1, 'MeV') delayedFissionNeutrons.append([decayRate, multiplicity]) totolDelayedMultiplicity += multiplicity energies, multiplicities = [], [] for energy, multiplicity in totolDelayedMultiplicity: energies.append(energy) multiplicities.append(multiplicity) DNU = [2, 0, len(totolDelayedMultiplicity)] + energies + multiplicities JXS[24 - 1] = len(XSS) + 1 updateXSSInfo('DNU', annotates, XSS, DNU) BDD = [] for decayRate, multiplicity in delayedFissionNeutrons: probability = multiplicity / totolDelayedMultiplicity probability = probability.thin(1e-3) energies, probabilities = [], [] for energy, _probability in probability: energies.append(energy) probabilities.append(_probability) BDD += [decayRate, 0, len(probability)] + energies + probabilities JXS[25 - 1] = len(XSS) + 1 updateXSSInfo('BDD', annotates, XSS, BDD) delayedNeutronEnergies = [] for delayedNeutronData in delayedNeutronDatas: multiplicity = delayedNeutronData['multiplicity'] multiplicity = multiplicity.convertAxisToUnit(1, 'MeV') delayedNeutronEnergies.append([ 18, multiplicity.domainMin, multiplicity.domainMax, delayedNeutronData['energyData'] ]) LDLW, MT_DLW = processEnergyData(massUnit, neutronMass, delayedNeutronEnergies) JXS[26 - 1] = len(XSS) + 1 updateXSSInfo('DNEDL', annotates, XSS, LDLW) JXS[27 - 1] = len(XSS) + 1 for MT, DLW in MT_DLW: updateXSSInfo('DNED(MT=%s)' % MT, annotates, XSS, DLW) # 12) GPD block. Not needed. # 13) MTRP block (gammas). # 14) LSIGP block (gammas). # 15) SIGP block (gammas). # 16) LANDP block (gammas). # 17) ANDP block (gammas). # 18) LDLWP block (gammas). # 19) DLWP block (gammas). # 20) YP block (gammas). # 21) FIS block. Not needed. # 22) UNR block. # 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 toENDF6(self, style, flags, verbosityIndent='', covarianceSuite=None, useRedsFloatFormat=False, lineNumbers=True, **kwargs): _useRedsFloatFormat = endfFormatsModule.useRedsFloatFormat endfFormatsModule.useRedsFloatFormat = useRedsFloatFormat evaluatedStyle = self.styles.getEvaluatedStyle() if (evaluatedStyle is None): raise ValueError('no evaluation style found') if (flags['verbosity'] >= 10): print '%s%s' % (verbosityIndent, self.inputParticlesToReactionString(suffix=" -->")) verbosityIndent2 = verbosityIndent + ' ' * ( len(self.inputParticlesToReactionString(suffix=" -->")) + 1) projectileZA = miscPoPsModule.ZA(self.PoPs[self.projectile]) IPART = projectileZA if (self.projectile == 'e-'): IPART = 11 targetZA, MAT = endf_endlModule.ZAAndMATFromParticleName(self.target) targetZ, targetA = divmod(targetZA, 1000) targetInfo = {} targetInfo['massTracker'] = massTrackerModule.massTracker() for particle in self.PoPs: if (isinstance(particle, (gaugeBosonPoPsModule.particle, leptonPoPsModule.particle, isotopePoPsModule.suite))): ZA = miscPoPsModule.ZA(particle) if (isinstance(particle, isotopePoPsModule.suite)): if (particle[0].intIndex != 0): continue if (len(particle.mass) > 0): targetInfo['massTracker'].addMassAMU(ZA, particle.getMass('amu')) elif (isinstance(particle, chemicalElementPoPsModule.suite)): ZA = 1000 * particle.Z targetInfo['massTracker'].addMassAMU( ZA, targetInfo['massTracker'].getElementalMassAMU(ZA)) targetInfo['style'] = style targetInfo['reactionSuite'] = self targetInfo['ZA'] = targetZA target = self.PoPs[self.target] levelIndex = 0 levelEnergy_eV = 0 if (isinstance(target, nuclearLevelPoPsModule.particle)): # isomer target levelIndex = target.intIndex levelEnergy_eV = target.energy[0].float('eV') targetInfo['mass'] = targetInfo['massTracker'].getMassAWR( targetZA, levelEnergyInEv=levelEnergy_eV) targetInfo['LIS'] = levelIndex targetInfo['metastables'] = {} targetInfo['LISO'] = 0 if (levelIndex > 0): targetInfo['LISO'] = 1 # BRBBRB for alias in self.PoPs.aliases: if (hasattr(alias, 'metaStableIndex')): targetInfo['metastables'][alias.pid] = alias MAT += targetInfo['LISO'] if (self.MAT is not None): MAT = self.MAT ITYPE = 0 for reaction in self.reactions: if (500 <= reaction.ENDF_MT < 573): ITYPE = 3 targetInfo['crossSectionMF'] = {0: 3, 3: 23}[ITYPE] targetInfo['delayedRates'] = [] targetInfo['MTs'], targetInfo['MF8'], targetInfo['LRs'] = {}, {}, {} endfMFList = { 1: { 451: [] }, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 8: {}, 9: {}, 10: {}, 12: {}, 13: {}, 14: {}, 15: {}, 23: {}, 26: {}, 27: {}, 31: {}, 32: {}, 33: {}, 34: {}, 35: {}, 40: {} } if (self.resonances is not None): # Add resonances, independent of reaction channels self.resonances.toENDF6(endfMFList, flags, targetInfo, verbosityIndent=verbosityIndent2) targetInfo['production_gammas'] = {} for multiplicitySum in self.sums.multiplicities: if multiplicitySum.ENDF_MT == 452: targetInfo['totalNubar'] = multiplicitySum.multiplicity.evaluated elif multiplicitySum.ENDF_MT == 455: targetInfo[ 'totalDelayedNubar'] = multiplicitySum.multiplicity.evaluated for reaction in self: reaction.toENDF6(endfMFList, flags, targetInfo, verbosityIndent=verbosityIndent2) gndToENDF6Module.upDateENDFMF8Data(endfMFList, targetInfo) for MT, production_gammas in targetInfo['production_gammas'].items(): MF, production_gammas = production_gammas[0], production_gammas[1:] for productionReaction in production_gammas: gammas = [gamma for gamma in productionReaction.outputChannel] targetInfo['crossSection'] = productionReaction.crossSection[ targetInfo['style']] gndToENDF6Module.gammasToENDF6_MF12_13(MT, MF, endfMFList, flags, targetInfo, gammas) for particle in self.PoPs: if (isinstance(particle, nucleusPoPsModule.particle)): if (len(particle.decayData.decayModes) > 0): for baseMT in [50, 600, 650, 700, 750, 800]: residualZA = endf_endlModule.ENDF_MTZAEquation( projectileZA, targetZA, baseMT)[0][-1] atomID = particle.findClassInAncestry( isotopePoPsModule.suite).id if (nuclearModule.nucleusNameFromZA(residualZA) == atomID): break addDecayGamma(self.PoPs, particle, baseMT, endfMFList, flags, targetInfo) if 'totalNubar' in targetInfo: multiplicityModule.fissionNeutronsToENDF6(452, targetInfo['totalNubar'], endfMFList, flags, targetInfo) if 'promptNubar' in targetInfo: multiplicityModule.fissionNeutronsToENDF6(456, targetInfo['promptNubar'], endfMFList, flags, targetInfo) if 'totalDelayedNubar' in targetInfo: MF5MT455s = endfMFList[5][455] endfMFList[1][455] = [ endfFormatsModule.endfHeadLine(targetZA, targetInfo['mass'], 0, 2, 0, 0) ] # Currently, only LDG = 0, LNU = 2 is supported. endfMFList[1][455] += [ endfFormatsModule.endfHeadLine(0, 0, 0, 0, len(targetInfo['delayedRates']), 0) ] endfMFList[1][455] += endfFormatsModule.endfDataList( targetInfo['delayedRates']) multiplicityModule.fissionNeutronsToENDF6( 455, targetInfo['totalDelayedNubar'], endfMFList, flags, targetInfo) MF5MT455List = [ endfFormatsModule.endfHeadLine(targetZA, targetInfo['mass'], 0, 0, len(MF5MT455s), 0) ] for MF5MT455 in MF5MT455s: MF5MT455List += MF5MT455 if (len(MF5MT455s) == 0): del endfMFList[5][455] else: endfMFList[5][455] = MF5MT455List + [ endfFormatsModule.endfSENDLineNumber() ] if (covarianceSuite): covarianceSuite.toENDF6(endfMFList, flags, targetInfo) endfDoc = self.documentation.get('endfDoc') if (endfDoc is None): docHeader2 = [ ' %2d-%-2s-%3d LLNL EVAL-OCT03 Unknown' % (targetZ, nuclearModule.elementSymbolFromZ(targetZ), targetA), ' DIST-DEC99 19990101 ', '----ENDL MATERIAL %4d' % MAT, '-----INCIDENT %s DATA' % { 1: 'NEUTRON', 1001: 'PROTON', 1002: 'DEUTERON', 1003: 'TRITON', 2003: 'HELION', 2004: 'ALPHA' }[projectileZA], '------ENDF-6 FORMAT' ] endfDoc = [ 'LLNL ENDL file translated to ENDF6 by FUDGE.', '' ' ************************ C O N T E N T S ***********************' ] endlDoc = self.documentation.get('ENDL').getLines() endlDoc2 = [] if endlDoc != None: for line in endlDoc: if 'endep' in line: # remove text from the line before the ones containing 'endep' del endlDoc2[-1] break newline = textwrap.wrap(line, width=66, drop_whitespace=False, subsequent_indent=' ') if len(newline) == 0: newline = [' ' ] # do not let blank lines disappear altogether endlDoc2 += newline endfDoc = endlDoc2 + endfDoc else: docHeader2 = [] endfDoc = endfDoc.getLines() # update the documentation, including metadata on first 4 lines: if self.getReaction('fission') is not None: LFI = True else: LFI = False LRP = -1 if (self.resonances is not None): if (self.resonances.scatteringRadius): LRP = 0 elif (self.resonances.reconstructCrossSection): LRP = 1 elif (self.resonances.unresolved and not self.resonances.resolved): # self-shielding only LRP = 1 else: LRP = 2 crossSectionScale = self.reactions[0].domainUnitConversionFactor('eV') EMAX = max([ crossSectionScale * reaction.crossSection.domainMax for reaction in self.reactions ]) temperature = self.styles[style].temperature.getValueAs('K') library = evaluatedStyle.library version = evaluatedStyle.version if ( library == 'ENDL' ): # Additional ENDF meta-data. If the library is unknown, use NLIB = -1 NVER, LREL, NMOD = 1, 1, 1 NLIB = -1 else: NVER, LREL, NMOD = map(int, version.split('.')) # Version stored as '7.2.1' NLIB = { "ENDF/B": 0, "ENDF/A": 1, "JEFF": 2, "EFF": 3, "ENDF/B (HE)": 4, "CENDL": 5, "JENDL": 6, "SG-23": 21, "INDL/V": 31, "INDL/A": 32, "FENDL": 33, "IRDF": 34, "BROND (IAEA version)": 35, "INGDB-90": 36, "FENDL/A": 37, "BROND": 41 }.get(library, -1) NFOR = 6 # ENDF-6 format NSUB = 10 * IPART + ITYPE LDRV = 0 NLIB = kwargs.get('NLIB', NLIB) STA = 0 target = self.PoPs[self.target] if (isinstance(target, isotopePoPsModule.suite)): target = target[0] if (len(target.nucleus.halflife) > 0): if (target.nucleus.halflife[0].value == halflifePoPsModule.UNSTABLE ): STA = 1 if (levelIndex > 0): STA = 1 projectileMass = targetInfo['massTracker'].getMassAWR(projectileZA, asTarget=False) docHeader = [ endfFormatsModule.endfHeadLine(targetZA, targetInfo['mass'], LRP, LFI, NLIB, NMOD), endfFormatsModule.endfHeadLine(levelEnergy_eV, STA, levelIndex, targetInfo['LISO'], 0, NFOR), endfFormatsModule.endfHeadLine(projectileMass, EMAX, LREL, 0, NSUB, NVER), endfFormatsModule.endfHeadLine(temperature, 0, LDRV, 0, len(docHeader2 + endfDoc), -1) ] new_doc = documentationModule.documentation( 'endf', '\n'.join(docHeader + docHeader2 + endfDoc)) endfMFList[1][451] += endfFormatsModule.toEndfStringList(new_doc) endfFormatsModule.useRedsFloatFormat = _useRedsFloatFormat return (endfFormatsModule.endfMFListToFinalFile(endfMFList, MAT, lineNumbers=lineNumbers))