pydfnWorks
python wrapper for dfnWorks
mass_balance.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Calculate mass balance across a boundary of a DFN mesh
4 # Make sure that you run PFLOTRAN with MASS_FLOWRATE under OUTPUT
5 # Satish Karra
6 # March 17, 2016
7 # Updated Jeffrey Hyman Dec 19 2018
8 
9 import numpy as np
10 import glob
11 from pydfnworks.dfnGen.meshing.mesh_dfn_helper import parse_params_file
12 
13 __author__ = 'Satish Karra'
14 __email__ = 'satkarra@lanl.gov'
15 
16 
17 def get_domain():
18  ''' Return dictionary of domain x,y,z by calling parse_params_file
19 
20  Parameters
21  ----------
22  None
23 
24  Returns
25  -------
26  domain : dict
27  Dictionary of domain sizes in x, y, z
28 
29  Notes
30  -----
31  parse_params_file() is in mesh_dfn_helper.py
32 '''
33  _, _, _, _, domain = parse_params_file(quiet=True)
34  return domain
35 
36 
37 def parse_pflotran_input(pflotran_input_file):
38  ''' Walk through PFLOTRAN input file and find inflow boundary, inflow and outflow pressure, and direction of flow
39 
40  Parameters
41  ----------
42  pflotran_input_file : string
43  Name of PFLOTRAN input file
44 
45  Returns
46  -------
47  inflow_pressure : double
48  Inflow Pressure boundary condition
49  outflow_pressure : float
50  Outflow pressure boundary condition
51  inflow_file : string
52  Name of inflow boundary .ex file
53  direction : string
54  Primary direction of flow x, y, or z
55 
56  Notes
57  -----
58  Currently only works for Dirichlet Boundary Conditions
59 '''
60 
61  with open(pflotran_input_file) as fp:
62  outflow_found = False
63  inflow_found = False
64  for line in fp.readlines():
65  if "BOUNDARY_CONDITION OUTFLOW" in line:
66  outflow_found = True
67  if outflow_found:
68  if "REGION" in line:
69  outflow = line.split()[-1]
70  outflow_found = False
71  if "BOUNDARY_CONDITION INFLOW" in line:
72  inflow_found = True
73  if inflow_found:
74  if "REGION" in line:
75  inflow = line.split()[-1]
76  inflow_found = False
77 
78  with open(pflotran_input_file) as fp:
79  inflow_name_found = False
80  outflow_name_found = False
81  inflow_found = False
82  outflow_found = False
83 
84  for line in fp.readlines():
85  if "REGION " + inflow in line:
86  inflow_name_found = True
87  if inflow_name_found:
88  if "FILE" in line:
89  inflow_file = line.split()[-1]
90  inflow_name_found = False
91  if "FLOW_CONDITION " + inflow in line:
92  inflow_found = True
93  if inflow_found:
94  if "PRESSURE " in line:
95  if "dirichlet" not in line:
96  tmp = line.split()[-1]
97  tmp = tmp.split('d')
98  inflow_pressure = float(tmp[0]) * 10**float(tmp[1])
99  inflow_found = False
100 
101  if "REGION " + outflow in line:
102  outflow_name_found = True
103  if outflow_name_found:
104  if "FILE" in line:
105  outflow_file = line.split()[-1]
106  outflow_name_found = False
107  if "FLOW_CONDITION " + outflow in line:
108  outflow_found = True
109  if outflow_found:
110  if "PRESSURE " in line:
111  if "dirichlet" not in line:
112  tmp = line.split()[-1]
113  tmp = tmp.split('d')
114  outflow_pressure = float(tmp[0]) * 10**float(tmp[1])
115  outflow_found = False
116 
117  if inflow_file == 'pboundary_left_w.ex' or inflow_file == 'pboundary_right_e.ex':
118  direction = 'x'
119  if inflow_file == 'pboundary_front_n.ex' or inflow_file == 'pboundary_back_s.ex':
120  direction = 'y'
121  if inflow_file == 'pboundary_top.ex' or inflow_file == 'pboundary_bottom.ex':
122  direction = 'z'
123 
124  print("Inflow file: %s" % inflow_file)
125  print("Inflow Pressure %e" % inflow_pressure)
126  print("Outflow Pressure %e" % outflow_pressure)
127  print("Primary Flow Direction : %s" % direction)
128 
129  return inflow_pressure, outflow_pressure, inflow_file, direction
130 
131 
132 def flow_rate(darcy_vel_file, boundary_file):
133  '''Calculates the flow rate across the inflow boundary
134 
135  Parameters
136  ----------
137  darcy_vel_file : string
138  Name of concatenated Darcy velocity file
139  boundary_file : string
140  ex file for the inflow boundary
141 
142  Returns
143  -------
144  mass_rate : float
145  Mass flow rate across the inflow boundary
146  volume_rate : float
147  Volumetric flow rate across the inflow boundary
148 
149  Notes
150  -----
151  None
152 '''
153  # Calculate the mass flow rate
154  mass_rate = 0.0 #kg/s
155  volume_rate = 0.0 #m^3/s
156 
157  dat_boundary = np.genfromtxt(boundary_file, skip_header=1)
158  dat = np.genfromtxt(darcy_vel_file)
159  for cell in dat_boundary[:, 0]:
160  if (np.any(dat[:, 0] == int(cell))):
161  ids = np.where(dat[:, 0] == int(cell))[0]
162  for idx in ids:
163  cell_up = int(dat[idx, 0])
164  cell_down = int(dat[idx, 1])
165  mass_flux = dat[idx, 2] # in m/s , darcy flux, right? m3/m2/s
166  density = dat[idx, 3] # in kg/m3
167  area = dat[idx, 4] # in m^2
168  if (cell_up == int(cell)):
169  mass_rate = mass_flux * area * \
170  density + mass_rate # in kg/s
171  volume_rate = mass_flux * area + volume_rate #in m3/s
172  else:
173  mass_rate = - mass_flux * area * \
174  density + mass_rate # in kg/s
175  volume_rate = -mass_flux * area + volume_rate #in m3/s
176  #print cell_up, cell_down, mass_flux, density, area, mass_rate, volume_rate
177  if (np.any(dat[:, 1] == int(cell))):
178  ids = np.where(dat[:, 1] == int(cell))[0]
179  for idx in ids:
180  cell_up = int(dat[idx, 0])
181  cell_down = int(dat[idx, 1])
182  mass_flux = dat[idx, 2] # in m/s
183  density = dat[idx, 3] # in kg/m3
184  area = dat[idx, 4] # in m^2
185  if (cell_up == int(cell)):
186  mass_rate = mass_flux * area * \
187  density + mass_rate # in kg/s
188  volume_rate = mass_flux * area + volume_rate #in m3/s
189  else:
190  mass_rate = - mass_flux * area * \
191  density + mass_rate # in kg/s
192  volume_rate = -mass_flux * area + volume_rate #in m3/s
193  #print cell_up, cell_down, mass_flux, density, area, mass_rate, volume_rate
194  return mass_rate, volume_rate
195 
196 
197 def dump_effective_perm(local_jobname, mass_rate, volume_rate, domain,
198  direction, inflow_pressure, outflow_pressure):
199  '''Compute the effective permeability of the DFN and write it to screen and to the file local_jobname_effective_perm.dat
200 
201  Parameters
202  ----------
203  local_jobname : string
204  Jobname
205  mass_rate : float
206  Mass flow rate through inflow boundary
207  volume_rate : float
208  Volumetric flow rate through inflow boundary
209  direction : string
210  Primary direction of flow (x, y, or z)
211  domain : dict
212  Dictionary of domain sizes in x, y, z
213  inflow_pressure : float
214  Inflow boundary pressure
215  outflow_pressure : float
216  Outflow boundary pressure
217 
218  Returns
219  -------
220  None
221 
222  Notes
223  -----
224  Information is written into (local_jobname)_effective_perm.txt
225 '''
226 
227  Lm3 = domain['x'] * domain['y'] * domain['z'] #L/m^3
228  # if flow is in x direction, cross section is domain['y']*domain['z']
229  if direction == 'x':
230  surface = domain['y'] * domain['z']
231  L = domain['x']
232  if direction == 'y':
233  surface = domain['x'] * domain['z']
234  L = domain['y']
235  if direction == 'z':
236  surface = domain['x'] * domain['y']
237  L = domain['z']
238  # Print the calculated mass flow rate in kg/s
239  mu = 8.9e-4 #dynamic viscosity of water at 20 degrees C, Pa*s
240  spery = 3600. * 24. * 365.25 #seconds per year
241  # compute pressure gradient
242  pgrad = (inflow_pressure - outflow_pressure) / L
243 
244  print("\n\nEffective Permeabilty Properties\n")
245  fp = open(local_jobname + '_effective_perm.txt', "w")
246  print('The mass flow rate [kg/s]: ' + str(mass_rate))
247  fp.write('The mass flow rate [kg/s]: %e\n' % (mass_rate))
248  print('The volume flow rate [m3/s]: ' + str(volume_rate))
249  fp.write('The volume flow rate [m3/s]: %s\n' % (volume_rate))
250  q = volume_rate / surface #darcy flux over entire face m3/m2/s
251 
252  if direction == 'x':
253  print('The darcy flow rate over %f x %f m2 area [m3/m2/s]: %e' %
254  (domain['y'], domain['z'], q))
255  fp.write('The darcy flow rate over %f x %f m2 area [m3/m2/s]: %e\n' %
256  (domain['y'], domain['z'], q))
257  print('The darcy flow rate over %f x %f m2 area [m3/m2/y]: %e' %
258  (domain['y'], domain['z'], spery * q))
259  fp.write('The darcy flow rate over %f x %f m2 area [m3/m2/y]: %e\n' %
260  (domain['y'], domain['z'], spery * q))
261 
262  if direction == 'y':
263  print('The darcy flow rate over %f x %f m2 area [m3/m2/s]: %e' %
264  (domain['x'], domain['z'], q))
265  fp.write('The darcy flow rate over %f x %f m2 area [m3/m2/s]: %e\n' %
266  (domain['x'], domain['z'], q))
267  print('The darcy flow rate over %f x %f m2 area [m3/m2/y]: %e' %
268  (domain['x'], domain['z'], spery * q))
269  fp.write('The darcy flow rate over %f x %f m2 area [m3/m2/y]: %e\n' %
270  (domain['x'], domain['z'], spery * q))
271 
272  if direction == 'z':
273  print('The darcy flow rate over %f x %f m2 area [m3/m2/s]: %e' %
274  (domain['x'], domain['y'], q))
275  fp.write('The darcy flow rate over %f x %f m2 area [m3/m2/s]: %e\n' %
276  (domain['x'], domain['y'], q))
277  print('The darcy flow rate over %f x %f m2 area [m3/m2/y]: %e' %
278  (domain['x'], domain['y'], spery * q))
279  fp.write('The darcy flow rate over %f x %f m2 area [m3/m2/y]: %e\n' %
280  (domain['x'], domain['y'], spery * q))
281  print('The effective permeability of the domain [m2]: ' +
282  str(q * mu / pgrad))
283  fp.write('The effective permeability of the domain [m2]: %e\n' %
284  (q * mu / pgrad))
285  fp.close()
286 
287 
288 def effective_perm(self):
289  '''Computes the effective permeability of a DFN in the primary direction of flow using a steady-state PFLOTRAN solution.
290 
291  Parameters
292  ----------
293  self : object
294  DFN Class
295 
296  Returns
297  -------
298  None
299 
300  Notes
301  -----
302  1. Information is written to screen and to the file self.local_jobname_effective_perm.txt
303  2. Currently, only PFLOTRAN solutions are supported
304  3. Assumes density of water
305 
306 '''
307  print("\n--> Computing Effective Permeability of Block")
308  if not self.flow_solver == "PFLOTRAN":
309  print(
310  "Incorrect flow solver selected. Cannot compute effective permeability"
311  )
312  return 0
313 
314  darcy_vel_file = 'darcyvel.dat'
315  pflotran_input_file = self.local_dfnFlow_file
316 
317  inflow_pressure, outflow_pressure, boundary_file, direction = parse_pflotran_input(
318  pflotran_input_file)
319  domain = get_domain()
320  mass_rate, volume_rate = flow_rate(darcy_vel_file, boundary_file)
321  dump_effective_perm(self.local_jobname, mass_rate, volume_rate, domain,
322  direction, inflow_pressure, outflow_pressure)
323  print("\n--> Complete\n\n")
def flow_rate(darcy_vel_file, boundary_file)
def dump_effective_perm(local_jobname, mass_rate, volume_rate, domain, direction, inflow_pressure, outflow_pressure)
def parse_pflotran_input(pflotran_input_file)
Definition: mass_balance.py:37