def condense_spectrum(dec_file): """ We will explicitly ignore all continuous distributions because they do not show up as clean gamma lines. Note that the ENDF-B/decay/ directory stores a lot of spectra (even those with very clear lines) as continuous, so it may lead to the following method ignoring it. The workaround is just to use another library where the evaluators aren't so lazy to not use the continuous_flag=='both' :/ """ count = Variable(0.0, 0.0) if ("gamma" in dec_file['spectra']) and ("discrete" in dec_file['spectra']['gamma']): norm_factor = dec_file['spectra']['gamma']['discrete_normalization'] for gamma_line in dec_file['spectra']['gamma']['discrete']: if np.clip(gamma_line['energy'].n, *gamma_E) == gamma_line['energy'].n: count += photopeak_eff_curve( gamma_line['energy'] ) * gamma_line['intensity'] / 100 * norm_factor if ('xray' in dec_file['spectra']) and ('discrete' in dec_file['spectra']['xray']): norm_factor = dec_file['spectra']['xray']['discrete_normalization'] for xray_line in dec_file['spectra']['xray']['discrete']: if np.clip(xray_line['energy'].n, *gamma_E) == xray_line['energy'].n: additional_counts = photopeak_eff_curve( xray_line['energy'] ) * xray_line['intensity'] / 100 * norm_factor if not additional_counts.s <= additional_counts.n: additional_counts = Variable( additional_counts.n, additional_counts.n ) # clipping the uncertainty so that std never exceed the mean. This takes care of the nan's too. count += additional_counts del dec_file['spectra'] dec_file[ 'countable_photons'] = count #countable photons per decay of this isotope return
def unserialize_dict(mixed_object): """ Turn the string representation of the uncertainties back into uncertainties.core.Variable 's. """ if isinstance(mixed_object, dict): if tuple(mixed_object.keys()) == ( "x", "y", "interpolation" ): # if the mixed_object is a openmc.data.Tabulated1D object in disguise: mixed_object = tabulate(mixed_object) else: for key, val in mixed_object.items(): mixed_object[key] = unserialize_dict( val) # recursively un-serialize elif isinstance(mixed_object, list): for ind, item in enumerate(mixed_object): mixed_object[ind] = unserialize_dict(item) elif isinstance(mixed_object, str): if '+/-' in mixed_object: # is an uncertainties.core.Variable object if ')' in mixed_object: multiplier = float('1' + mixed_object.split(')')[1]) mixed_object_stripped = mixed_object.split(')')[0].strip('(') else: multiplier = 1.0 mixed_object_stripped = mixed_object mixed_object = Variable(*[ float(i) * multiplier for i in mixed_object_stripped.split('+/-') ]) else: pass # just a normal string else: # unknown type pass return mixed_object
def build_decay_chain_tree(decay_parent, decay_dict, decay_constant_threshold=1E-23): """ Build the entire decay chain for a given starting isotope. decay_parent : str names of the potentially unstable nuclide decay_dict : dictionary the entire decay_dict containing all of the that there is. """ if not decay_parent in decay_dict: # decay_dict does not contain any decay data record about the specified isotope (decay_parent), meaning it is (possibly) stable. return_dict = { 'name': decay_parent, 'decay_constant': Variable(0.0, 0.0), 'countable_photons': Variable(0.0, 0.0), 'modes': {} } else: # decay_dict contains the specified decay_parent parent = decay_dict[decay_parent] return_dict = { 'name': decay_parent, 'decay_constant': parent['decay_constant'], 'countable_photons': parent['countable_photons'] } # countable_photons per decay of this isotope if decay_dict[decay_parent][ 'decay_constant'] <= decay_constant_threshold: # if this isotope is rather stable. return return_dict else: return_dict['modes'] = [] for name, branching_ratio in decay_dict[decay_parent][ 'branching_ratio'].items(): if name != decay_parent: return_dict['modes'].append({ 'daughter': build_decay_chain_tree(name, decay_dict), 'branching_ratio': branching_ratio }) return return_dict
def extract_decay(dec_file): """ extract the useful information out of an openmc.data.Decay entry """ half_life = Variable( np.clip(dec_file.half_life.n, 1E-23, None), dec_file.half_life.s) # increase the half-life to a non-zero value. decay_constant = ln(2) / (half_life) modes = {} for mode in dec_file.modes: modes[mode.daughter] = mode.branching_ratio return dict(decay_constant=decay_constant, branching_ratio=modes, spectra=dec_file.spectra)
def decode(self, o): """ Catch the uncertainties Edit: This class doesn't work because the cpython/decoder.py is not written in a open-for-expansion principle. I suspect this is because turning variables (which aren't strings) into strings is an imporper way to use jsons; but I don't have any other solutions for EncoderOpenMC. In any case, DecoderOpenMC will be replaced by unserialize_dict below. """ if '+/-' in o: if ')' in o: multiplier = float('1' + o.split(')')[1]) o = o.split(')')[0].strip('(') else: multiplier = 1.0 return Variable(*[float(i) * multiplier for i in o.split('+/-')]) else: return super().decode(o)
def linearize_decay_chain(decay_file): """ Return a comprehensive list of path-to-nodes. Each path starts from the origin, and ends at the node of interest. Each node in the original graph must be must be recorded as the end node exactly once. The initial population is always assumed as 1. """ self_decay = IsotopeDecay( [decay_file['name']], [Variable(1.0, 0.0)], # branching ratio dummy value [decay_file['decay_constant']], decay_file['countable_photons']) all_chains = [self_decay] if 'modes' in decay_file: # expand the decay modes if there are any. for mode in decay_file['modes']: this_branch = linearize_decay_chain( mode['daughter'] ) # note that this is a list, so we need to unpack it. for subbranch in this_branch: subbranch.branching_ratios[0] = mode['branching_ratio'] all_chains.append(self_decay + subbranch) return all_chains # returns a list