def addProductToDecayMode(info, decayMode, decayParticleID, RFS=0, lastDecayMode=False): if (lastDecayMode and (RFS != 0)): isotopeNuclideID = nucleusModule.levelNameFromIsotopeNameAndIndex( decayParticleID, str(RFS)) metaStableID = PoPsAliasModule.metaStable.metaStableNameFromNuclearLevelNameAndMetaStableIndex( isotopeNuclideID, RFS) info.PoPs.add( PoPsAliasModule.metaStable(metaStableID, isotopeNuclideID, RFS)) decayParticleID = metaStableID decayMode.products.add( decayMode.products.uniqueLabel( productModule.product(decayParticleID, decayParticleID)))
def ITYPE_4(MTDatas, info, verbose=0): """Convert ENDF ITYPE 4 data (decay data) into PoPs.""" errors = [] # Add ENDF documentation info.PoPs.documentation = '\n'.join(MTDatas[451][1][4:-info.NXC]) # The atom containing the parent nucleus parentAtom = toGNDMisc.getPoPsParticle(info, info.targetZA, name=None, levelIndex=info.levelIndex, level=info.level, levelUnit=energyUnit) decayParticle = parentAtom if (miscPoPsModule.hasNucleas(parentAtom)): decayParticle = parentAtom.nucleus if (457 in MTDatas): dataIndex = 0 MT457MF8Data = MTDatas[457][8] decayData = decayParticle.decayData # Read parent info block ZA, AWR, LIS, LISO, NST, NSP = endfFileToGNDMisc.sixFunkyFloatStringsToIntsAndFloats( MT457MF8Data[dataIndex], intIndices=[2, 3, 4, 5]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) if (LIS != 0): aliasID = "%s_m%s" % (isotopeModule.isotopeIDFromElementIDAndA( parentAtom.chemicalElement, parentAtom.A), LISO) info.PoPs.add( PoPsAliasModule.metaStable(aliasID, parentAtom.id, LISO)) HL, dHL, dummy, dummy, NC2, dummy = endfFileToGNDMisc.sixFunkyFloatStringsToIntsAndFloats( MT457MF8Data[dataIndex], intIndices=[4]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) NC = NC2 // 2 # NC: number of decay energies if (NC not in [3, 17]): raise ValueError( "Number of decay energies must be 3 or 17, found %d" % NC) nlines = (NC2 + 5) // 6 aveDecayEnergies = [] for index in range(nlines): aveDecayEnergies.extend( endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MT457MF8Data[dataIndex])) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) if (len([ aveDecayEnergy for aveDecayEnergy in aveDecayEnergies if (aveDecayEnergy != 0) ]) > 0): aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.lightParticles) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.electroMagneticRadiation) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.heavyParticles) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.betaMinus) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.betaPlus) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.AugerElectron) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.conversionElectron) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.gamma) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.xRay) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.internalBremsstrahlung) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.annihilation) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.alpha) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.recoil) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.spontaneousFission) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.fissionNeutrons) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.proton) aveDecayEnergies = addAverageDecayEnergyIfPresent( decayData, aveDecayEnergies, averageEnergyModule.neutrino) SPI, PAR, dum, dum, NDK6, NDK = endfFileToGNDMisc.sixFunkyFloatStringsToIntsAndFloats( MT457MF8Data[dataIndex], intIndices=[1, 2, 3, 4, 5]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) if (-77.8 < SPI < -77.7): SPI = None # see page 180 of ENDF manual # FIXME: Need "UNKNOWN" markup halflifeValue = None if (NST == 1): halflifeValue = 'stable' if (PAR == 0): PAR = None # BRB, Happens for dec-013_Al_040.endf toGNDMisc.addParticleData(decayParticle, info, massValue=None, spinValue=SPI, parityValue=PAR, chargeValue=None, halflifeValue=halflifeValue) if (NST == 1): # Nucleus is stable, nothing to do pass elif (NST == 0): # Nucleus is unstable halflife = halflifeModule.double( info.PoPsLabel, HL, halflifeModule.baseUnit ) # FIXME: PQU(HL, 's', dHL), can't store uncertainty? decayParticle.halflife.add(halflife) # Iterate over decay chains decayModes = {} for i1 in range(NDK): # iterate over decay modes initialDecay, otherDecays, RTYP_key = getRTYP( MT457MF8Data[dataIndex]) RTYP, RFS, Q, dQ, BR, dBR = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MT457MF8Data[dataIndex]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) if (verbose > 3): print('RTYP = ', RTYP) RFS = int(RFS) # BRB, Isometic state of daughter allDecays = [initialDecay] + otherDecays decayMode = decayDataModule.decayMode( str(i1), ','.join([decayType[r_id] for r_id in allDecays])) decayModes[RTYP_key] = decayMode if (dBR): branching = PQU(BR, '', dBR) else: branching = PQU(BR, '') if (dQ): Qval = PQU(Q, energyUnit, dQ) else: Qval = PQU(Q, energyUnit) decayMode.Q.add( QModule.double('', Qval.getValue(), Qval.unit) ) # FIXME: PQU(Q, 'eV', dQ), can't store uncertainty decayMode.probability.add( probabilityModule.double("BR", branching.getValue(), '') ) # FIXME: PQU(BR, 's', dBR), can't store uncertainty # FIXME: what should we do for really small probabilities, so small ENDF gives 0, like spontaneous fission? n1 = len(otherDecays) - 1 residualZA = addDecayMode(info, decayMode, initialDecay, info.targetZA, RFS, -1 == n1) for i2, otherDecay in enumerate(otherDecays): residualZA = addDecayMode(info, decayMode, otherDecay, residualZA, RFS, i2 == n1) decayData.decayModes.add(decayMode) # LCON determines whether continuum spectra given: LCON 0: discrete only, 1: continuous only, 2: both for i1 in range(NSP): # Iterate over spectra initialDecay, otherDecays, STYP_key = getRTYP( MT457MF8Data[dataIndex], 11) dum, STYP, LCON, zero, six, NER = endfFileToGNDMisc.sixFunkyFloatStringsToIntsAndFloats( MT457MF8Data[dataIndex], intIndices=[2, 3, 4, 5]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) STYP = initialDecay specType = decayType[STYP] FD, dFD, ERave, dERave, FC, dFC = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MT457MF8Data[dataIndex] ) # FD: discrete normalization, FC: continuum norm., ERave: average decay energy dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) if (LCON != 1): # Discrete spectra given. for i2 in range(NER): ER, dER, dum, dum, NT, dum = endfFileToGNDMisc.sixFunkyFloatStringsToIntsAndFloats( MT457MF8Data[dataIndex], intIndices=[2, 3, 4, 5]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) discreteSpectra = {'ER': ER, 'dER': dER} if (LCON != 1): if (NT not in (6, 8, 12)): raise ValueError( "Unexpected NT=%d encountered!" % NT) initialDecay, otherDecays, RTYP_key = getRTYP( MT457MF8Data[dataIndex]) discreteSpectra[ 'RTYP_plus'] = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MT457MF8Data[dataIndex]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) if (verbose > 3): print('STYP, RTYP = ', STYP, RTYP_key) if (NT > 6): RICC, dRICC, RICK, dRICK, RICL, dRICL = endfFileToGNDMisc.sixFunkyFloatStringsToFloats( MT457MF8Data[dataIndex]) dataIndex += printInfo(verbose, dataIndex, MT457MF8Data) discreteSpectra['RICC'], discreteSpectra[ 'dRICC'] = RICC, dRICC if (NT > 8): discreteSpectra['RICK'], discreteSpectra[ 'dRICK'] = RICK, dRICK discreteSpectra['RICL'], discreteSpectra[ 'dRICL'] = RICL, dRICL addDiscreteSpectra(decayModes, RTYP_key, STYP, discreteSpectra) if (LCON != 0): # Continuum spectra given. initialDecay, otherDecays, RTYP_key = getRTYP( MT457MF8Data[dataIndex]) dataIndex, TAB1, regions = endfFileToGNDMisc.getTAB1Regions( dataIndex, MT457MF8Data) RTYP = TAB1['C1'] if (verbose > 3): print('STYP, RTYP = ', STYP, RTYP) LCOV = int(TAB1['L2']) if (len(regions) != 1): raise Exception('len( regions ) = %s' % len(regions)) covariance = None if (LCOV != 0): print(" LCOV != 0") dataIndex, covariance = getList( dataIndex, MT457MF8Data) addContinuumSpectrum(decayModes, RTYP_key, STYP, regions, covariance) else: raise ValueError( "In decay data (MT=457,MF=8), NST should be 0 or 1. Found %d" % NST) # Add documentation to PoPs return ({'PoPs': info.PoPs, 'errors': errors, 'info': info})
'1': [None, None, 6049.400, None, None, None, None], '2': [None, None, 6129.893, None, None, None, None], '3': [None, None, 6917.100, None, None, None, None] } for A, data in [['17', O16Data], ['16', O16Data]]: nuclearLevel(8, A, data) # atomMass nuclearMass, energy, charge, halflife, spin, parity Am242Data = { '0': [242.059549159, None, 0, None, '16.02 h', 1, -1], '1': [None, None, 44.092, None, None, 0, -1], '2': [None, None, 48.60, None, '141 yr', 5, -1], '3': [None, None, 52.70, None, None, 3, -1] } nuclearLevel(95, '242', Am242Data) database.add(aliasModule.metaStable('Am242_m1', 'Am242_e2', 1)) photon = gaugeBosonModule.particle('photon') mass = massModule.double('base', 0, quantityModule.stringToPhysicalUnit('amu')) photon.mass.add(mass) charge = chargeModule.integer('base', 0, quantityModule.stringToPhysicalUnit('e')) photon.charge.add(charge) halflife = halflifeModule.string('base', 'stable', quantityModule.stringToPhysicalUnit('s')) photon.halflife.add(halflife) spin = spinModule.fraction('base', spinModule.fraction.toValueType('1'),
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 })