15 """ Get the matrices D, A that make up the Laplacian sparse matrix in desired sparsity format. Used to enforce boundary conditions by modifying rows of L = D - A
20 NetworkX graph equipped with weight attribute
23 list of nodes of G for which laplacian is desired. Default is None in which case, all the nodes
26 For weighted Laplacian, else all weights assumed unity
28 dtype : default is None, cooresponds to float
31 sparse matrix format, csr, csc, coo, lil_matrix with default being lil
35 D : sparse 2d float array
36 Diagonal part of Laplacian
38 A : sparse 2d float array
39 Adjacency matrix of graph
42 A = nx.to_scipy_sparse_matrix(G,
49 data = np.asarray(A.sum(axis=1).T)
50 D = scipy.sparse.spdiags(data, 0, n, n, format=format)
55 """ Create a NetworkX graph, prepare it for flow solve by equipping edges with attributes, renumber vertices, and tag vertices which are on inlet or outlet
60 name of file containing list of DFN fractures on inflow boundary
63 name of file containing list of DFN fractures on outflow boundary
67 Gtilde : NetworkX graph
71 G = d2g.create_intersection_graph(
72 inflow, outflow, intersection_file=
"intersection_list.dat")
77 d2g.add_weight(Gtilde)
83 for v
in nx.nodes(Gtilde):
84 Gtilde.nodes[v][
'inletflag'] =
False
85 Gtilde.nodes[v][
'outletflag'] =
False
87 for v
in nx.neighbors(Gtilde,
's'):
88 Gtilde.nodes[v][
'inletflag'] =
True
90 for v
in nx.neighbors(Gtilde,
't'):
91 Gtilde.nodes[v][
'outletflag'] =
True
93 Gtilde.remove_node(
's')
94 Gtilde.remove_node(
't')
96 Gtilde = nx.convert_node_labels_to_integers(Gtilde,
99 label_attribute=
"old_label")
105 """ Given a NetworkX graph prepared for flow solve, solve for vertex pressures, and equip edges with attributes (Darcy) flux and time of travel
109 Gtilde : NetworkX graph
112 Value of pressure (in Pa) at inlet
115 Value of pressure (in Pa) at outlet
117 fluid_viscosity : double
118 optional, in Pa-s, default is for water
122 Gtilde : NetworkX graph
123 Gtilde is updated with vertex pressures, edge fluxes and travel times
126 Inlet = [v
for v
in nx.nodes(Gtilde)
if Gtilde.nodes[v][
'inletflag']]
127 Outlet = [v
for v
in nx.nodes(Gtilde)
if Gtilde.nodes[v][
'outletflag']]
129 if not set(Inlet).isdisjoint(set(Outlet)):
130 error =
"Incompatible graph: Vertex connected to both source and target\n"
131 sys.stderr.write(error)
136 rhs = np.zeros(Gtilde.number_of_nodes())
148 print(
"Solving sparse system")
149 Phat = scipy.sparse.linalg.spsolve(L, rhs)
150 print(
"Updating graph edges with flow solution")
152 for v
in nx.nodes(Gtilde):
153 Gtilde.nodes[v][
'pressure'] = Phat[v]
155 for u, v
in nx.edges(Gtilde):
156 delta_p = abs(Gtilde.nodes[u][
'pressure'] -
157 Gtilde.nodes[v][
'pressure'])
158 if delta_p > np.spacing(Gtilde.nodes[u][
'pressure']):
159 Gtilde.edges[u, v][
'flux'] = (
160 Gtilde.edges[u, v][
'perm'] / fluid_viscosity
161 ) * abs(Gtilde.nodes[u][
'pressure'] -
162 Gtilde.nodes[v][
'pressure']) / Gtilde.edges[u, v][
'length']
163 Gtilde.edges[u, v][
'time'] = Gtilde.edges[
164 u, v][
'length'] / Gtilde.edges[u, v][
'flux']
166 Gtilde.edges[u, v][
'flux'] = 0
168 print(
"Graph flow complete")
172 def run_graph_flow(self, inflow, outflow, Pin, Pout, fluid_viscosity=8.9e-4, G = None):
173 """ Run the graph flow portion of the workflow
182 name of file containing list of DFN fractures on inflow boundary
185 name of file containing list of DFN fractures on outflow boundary
188 Value of pressure (in Pa) at inlet
191 Value of pressure (in Pa) at outlet
193 fluid_viscosity : double
194 optional, in Pa-s, default is for water
198 Gtilde : NetworkX graph
199 Grtilde is updated with vertex pressures, edge fluxes and travel times
203 Information on individual functions in found therein
def solve_flow_on_graph(Gtilde, Pin, Pout, fluid_viscosity=8.9e-4)
def run_graph_flow(self, inflow, outflow, Pin, Pout, fluid_viscosity=8.9e-4, G=None)
def get_laplacian_sparse_mat(G, nodelist=None, weight=None, dtype=None, format='lil')
def prepare_graph_with_attributes(inflow, outflow, G=None)