diff --git a/README.rst b/README.rst index 8164360..b4ed6df 100644 --- a/README.rst +++ b/README.rst @@ -4,6 +4,8 @@ Overview wnnet is a python package for handling `webnucleo `_ reaction networks. +|pypi| |doc_stat| |license| |black| + Installation ------------ @@ -39,3 +41,13 @@ Usage The best way to get started using wnnet is to follow the `tutorial `_. + +.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black +.. |pypi| image:: https://badge.fury.io/py/wnnet.svg + :target: https://badge.fury.io/py/wnnet +.. |license| image:: https://img.shields.io/github/license/mbradle/wnnet + :alt: GitHub +.. |doc_stat| image:: https://readthedocs.org/projects/wnnet/badge/?version=latest + :target: https://wnnet.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status \ No newline at end of file diff --git a/doc/requirements.txt b/doc/requirements.txt index 18148c7..11f0545 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -2,4 +2,5 @@ wnutils networkx gslconsts sphinx_rtd_theme +jsonpickle #readthedocs-sphinx-search==0.1.1 diff --git a/wnnet/flows.py b/wnnet/flows.py index 5acf83c..0d50567 100644 --- a/wnnet/flows.py +++ b/wnnet/flows.py @@ -1,7 +1,9 @@ """This module computes various reaction flows in a network.""" - +import pickle +import jsonpickle import wnutils.xml as wx import numpy as np +from multiprocessing import Pool def _compute_flows_for_valid_reactions( @@ -100,10 +102,45 @@ def compute_flows( user_funcs, ) +def par_flow(zone,zones,user_funcs,net_pickled,valid_reactions_pickled,dups_pickled, + nuc_xpath,reac_xpath): + -def compute_flows_for_zones( - net, zones, nuc_xpath="", reac_xpath="", user_funcs="" -): + net = jsonpickle.decode(net_pickled) + valid_reactions = pickle.loads(valid_reactions_pickled) + dups = pickle.loads(dups_pickled) + + s_t9 = "t9" + s_rho = "rho" + _zone = zones[zone] + props = _zone["properties"] + if s_t9 in props and s_rho in props: + t9 = float(props[s_t9]) + rho = float(props[s_rho]) + _user_funcs = {} + if user_funcs: + for func in user_funcs: + _user_funcs[func] = lambda reaction, t9, func=func: user_funcs[ + func + ](reaction, t9, _zone) + return _compute_flows_for_valid_reactions( + net, + t9, + rho, + _zone["mass fractions"], + valid_reactions, + dups, + nuc_xpath, + reac_xpath, + _user_funcs, + ) + +def arg_unpack(args): + zone,zones,user_funcs,net_pickled,valid_reactions_pickled,dups_pickled,nuc_xpath,reac_xpath = args + return par_flow(zone,zones,user_funcs,net_pickled,valid_reactions_pickled,dups_pickled, + nuc_xpath,reac_xpath) + +def compute_flows_for_zones(net, zones, nuc_xpath="", reac_xpath="", user_funcs=""): """A routine to compute flows for a set of zones. Args: @@ -135,15 +172,20 @@ def compute_flows_for_zones( reverse flow. """ - zone_flows = {} - valid_reactions = net.get_valid_reactions( nuc_xpath=nuc_xpath, reac_xpath=reac_xpath ) - dups = net.compute_duplicate_factors() + net_pickled = jsonpickle.encode(net) + valid_reactions_pickled = pickle.dumps(valid_reactions) + dups_pickled = pickle.dumps(dups) + + + args_list = [(zone,zones,user_funcs,net_pickled,valid_reactions_pickled + ,dups_pickled,nuc_xpath,reac_xpath) for zone in zones] + ''' for zone in zones: s_t9 = "t9" s_rho = "rho" @@ -155,11 +197,9 @@ def compute_flows_for_zones( _user_funcs = {} if user_funcs: for func in user_funcs: - _user_funcs[ + _user_funcs[func] = lambda reaction, t9, func=func: user_funcs[ func - ] = lambda reaction, t9, func=func: user_funcs[func]( - reaction, t9, _zone - ) + ](reaction, t9, _zone) zone_flows[zone] = _compute_flows_for_valid_reactions( net, t9, @@ -171,7 +211,12 @@ def compute_flows_for_zones( reac_xpath, _user_funcs, ) + ''' + with Pool() as pool: + zone_flows = pool.map(arg_unpack, args_list) + + zone_flows = dict(zip(zones,zone_flows)) return zone_flows @@ -398,9 +443,7 @@ def compute_link_flows_for_zones( """ - assert ( - direction == "forward" or direction == "reverse" or direction == "both" - ) + assert direction == "forward" or direction == "reverse" or direction == "both" assert order == "normal" or order == "reversed" nuclides = net.get_nuclides() @@ -429,11 +472,9 @@ def compute_link_flows_for_zones( _user_funcs = {} if user_funcs: for func in user_funcs: - _user_funcs[ + _user_funcs[func] = lambda reaction, t9, func=func: user_funcs[ func - ] = lambda reaction, t9, func=func: user_funcs[func]( - reaction, t9, zones[zone] - ) + ](reaction, t9, zones[zone]) f = _compute_link_flows_for_valid_reactions( net, float(props[s_t9]), diff --git a/wnnet/graph.py b/wnnet/graph.py index a620c78..8276059 100644 --- a/wnnet/graph.py +++ b/wnnet/graph.py @@ -5,6 +5,7 @@ import wnnet.zones as wz import wnnet.flows as wf +from multiprocessing import Pool def get_solar_species(): """A method to return the naturally-occurring solar-system species. @@ -1109,9 +1110,7 @@ def create_network_graph( """ - assert ( - direction == "forward" or direction == "reverse" or direction == "both" - ) + assert direction == "forward" or direction == "reverse" or direction == "both" result = {} diff --git a/wnnet/net.py b/wnnet/net.py index 7abccf9..79b4ae5 100644 --- a/wnnet/net.py +++ b/wnnet/net.py @@ -45,9 +45,7 @@ def compute_Q_values(self, nuc_xpath="", reac_xpath=""): result = {} - for r in self.get_valid_reactions( - nuc_xpath=nuc_xpath, reac_xpath=reac_xpath - ): + for r in self.get_valid_reactions(nuc_xpath=nuc_xpath, reac_xpath=reac_xpath): tmp = self.compute_reaction_Q_value(r) if tmp: result[r] = tmp @@ -102,10 +100,7 @@ def compute_reaction_Q_value(self, name): else: result -= nuclides[sp]["mass excess"] - if ( - "positron" in reaction.products - and "neutrino_e" in reaction.products - ): + if "positron" in reaction.products and "neutrino_e" in reaction.products: result -= 2.0 * wc.m_e_in_MeV return result @@ -152,13 +147,7 @@ def _obeys_conservation_laws(self, nuclides, reaction): if sp in tau_lepton: d_l_tau -= tau_lepton[sp] - return ( - d_a == 0 - and d_z == 0 - and d_l_e == 0 - and d_l_mu == 0 - and d_l_tau == 0 - ) + return d_a == 0 and d_z == 0 and d_l_e == 0 and d_l_mu == 0 and d_l_tau == 0 def is_valid_reaction(self, name, nuc_xpath=""): """Method to determine a reaction is valid in the network. @@ -249,8 +238,6 @@ def compute_rates(self, t9, nuc_xpath="", reac_xpath="", user_funcs=""): result = {} for r in v_reactions: - result[r] = self.compute_rates_for_reaction( - r, t9, user_funcs=user_funcs - ) + result[r] = self.compute_rates_for_reaction(r, t9, user_funcs=user_funcs) return result diff --git a/wnnet/nuc.py b/wnnet/nuc.py index 88fc83b..be8f167 100644 --- a/wnnet/nuc.py +++ b/wnnet/nuc.py @@ -33,9 +33,7 @@ def get_nuclides(self, nuc_xpath=""): """ if nuc_xpath not in self.nuclides: - self.nuclides[nuc_xpath] = self.xml.get_nuclide_data( - nuc_xpath=nuc_xpath - ) + self.nuclides[nuc_xpath] = self.xml.get_nuclide_data(nuc_xpath=nuc_xpath) return self.nuclides[nuc_xpath] def compute_nuclear_partition_function(self, name, t9): @@ -97,9 +95,7 @@ def compute_quantum_abundance(self, name, t9, rho): m = wc.m_u_in_MeV * nuclide["a"] + nuclide["mass excess"] - result = self.compute_nuclear_partition_function(name, t9) / ( - rho * wc.N_A - ) + result = self.compute_nuclear_partition_function(name, t9) / (rho * wc.N_A) p1 = (m * wc.MeV_to_ergs) * wc.k_B * t9 * 1.0e9 p2 = 2.0 * np.pi * np.power(wc.hbar * wc.c, 2) diff --git a/wnnet/reac.py b/wnnet/reac.py index 49bf95e..569f235 100644 --- a/wnnet/reac.py +++ b/wnnet/reac.py @@ -18,9 +18,7 @@ class Reac: def __init__(self, file, reac_xpath=""): self.xml = wx.Xml(file) self.reactions = {} - self.reactions[reac_xpath] = self.xml.get_reaction_data( - reac_xpath=reac_xpath - ) + self.reactions[reac_xpath] = self.xml.get_reaction_data(reac_xpath=reac_xpath) def get_reactions(self, reac_xpath=""): """Method to return a collection of reactions.