Exemplo n.º 1
0
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
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
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 ) )
Exemplo n.º 4
0
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
    })
Exemplo n.º 5
0
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 } )
Exemplo n.º 6
0
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()
Exemplo n.º 7
0
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))