pydfnWorks
python wrapper for dfnWorks
upscale.py
Go to the documentation of this file.
1 """
2 .. module:: upscale.py
3  :synopsis: Generates PFLOTRAN or FEHM input from octree refined continuum mesh
4 .. moduleauthor:: Matthew Sweeney <msweeney2796@lanl.gov>
5 
6 """
7 
8 import os
9 import numpy as np
10 import sys
11 import subprocess
12 import shutil
13 import h5py
14 from pydfnworks.dfnGen.meshing import mesh_dfn_helper as mh
15 import time
16 import math as m
17 import glob
18 import pickle
19 
20 
21 def upscale(self, mat_perm, mat_por, path='../'):
22  """ Generate permeabilities and porosities based on output of map2continuum.
23 
24  Parameters
25  ----------
26  self : object
27  DFN Class
28  mat_perm : float
29  Matrix permeability (in m^2)
30  mat_por: float
31  Matrix porosity
32 
33  Returns
34  -------
35  perm_fehm.dat : text file
36  Contains permeability data for FEHM input
37  rock_fehm.dat : text file
38  Contains rock properties data for FEHM input
39  mesh_permeability.h5 : h5 file
40  Contains permeabilites at each node for PFLOTRAN input
41  mesh_porosity.h5 : h5 file
42  Contains porosities at each node for PFLOTRAN input
43 
44  Notes
45  -----
46  None
47 
48  """
49 
50  print('=' * 80)
51  print("Generating permeability and porosity for octree mesh: Starting")
52  print('=' * 80)
53 
54  # Bring in all the relevant data
55  try:
56  os.symlink(path + 'params.txt', 'params.txt')
57  except:
58  pass
59  num_poly, _, _, _, domain = mh.parse_params_file(quiet=True)
60 
61  aperture = np.genfromtxt(path + 'aperture.dat', skip_header=1)[:, -1]
62  normal_vectors = np.genfromtxt(path + 'normal_vectors.dat', delimiter=' ')
63 
64  if self.flow_solver == "FEHM":
65  with open("perm_fehm.dat", "w") as f:
66  f.write("perm\n")
67  with open("rock_fehm.dat", "w") as g:
68  g.write("rock\n")
69 
70  # Make dictionary w/ cell IDs (keys) and intersecting fractures, areas (values)
71  for i in range(1, num_poly + 1):
72  if i == 1:
73  with open('frac1.inp', 'r') as f:
74  line = f.readline().strip().split()
75  num_nodes = int(float(line[0]))
76  num_cells = int(float(line[1]))
77  f_dict = {}
78  perm_var = np.zeros(num_nodes, 'float')
79  por_var = np.zeros(num_nodes, 'float')
80  cv_vol = np.zeros(num_nodes, 'float')
81  iarray = np.zeros(num_nodes, '=i4')
82  frac_vol = np.zeros(num_nodes, 'float')
83  permX = np.zeros(num_nodes, 'float')
84  permY = np.zeros(num_nodes, 'float')
85  permZ = np.zeros(num_nodes, 'float')
86  f.close()
87  with open('frac{0}.inp'.format(i), 'r') as f:
88  with open('area_sum{0}.inp'.format(i), 'r') as g:
89  for j in range(num_nodes):
90  f.readline()
91  g.readline()
92  f.readline()
93  g.readline()
94  for j in range(num_cells):
95  f.readline()
96  g.readline()
97  f.readline()
98  f.readline()
99  f.readline()
100  g.readline()
101  g.readline()
102  g.readline()
103  g.readline()
104  g.readline()
105  g.readline()
106  g.readline()
107  for j in range(num_nodes):
108  fline = f.readline().strip().split()
109  gline = g.readline().strip().split()
110  iarray[j] = int(float(gline[0]))
111  if int(float(gline[1])) != (num_poly + 1) and float(
112  gline[6]) > 0:
113  f_dict.setdefault(j + 1, []).append(
114  (i, float(gline[6])))
115  g.close()
116  f.close()
117 
118  p_out = open("connections.p", "wb")
119  pickle.dump(f_dict, p_out)
120  p_out.close()
121 
122  with open('full_mesh.uge', 'r') as f:
123  f.readline()
124  for j in range(num_nodes):
125  fline = f.readline().strip().split()
126  cv_vol[j] = float(fline[4])
127  f.close()
128 
129  # Populate permeability and porosity arrays here
130  for i in range(1, num_nodes + 1):
131  if i in f_dict:
132 
133  # Get porosity:
134  for j in range(len(f_dict[i])):
135  # Calculate total volume of fractures in cv cell i
136  frac_vol[i -
137  1] += aperture[f_dict[i][j][0] - 1] * f_dict[i][j][1]
138  por_var[i - 1] = frac_vol[i - 1] / cv_vol[i - 1]
139  if por_var[i - 1] == 0:
140  por_var[i - 1] = mat_por
141  if por_var[i - 1] > 1.0:
142  por_var[i - 1] = 1.0
143 
144  # Get permeability:
145  perm_tensor = np.zeros([3, 3])
146  phi_sum = 0
147  for j in range(len(f_dict[i])):
148  phi = (aperture[f_dict[i][j][0] - 1] *
149  f_dict[i][j][1]) / cv_vol[i - 1]
150  if phi > 1.0:
151  phi = 1.0
152  phi_sum += phi
153  if phi_sum > 1.0:
154  phi_sum = 1.0
155  b = aperture[f_dict[i][j][0] - 1]
156  # Construct tensor Omega
157  Omega = np.zeros([3, 3])
158  n1 = normal_vectors[f_dict[i][j][0] - 1][0]
159  n2 = normal_vectors[f_dict[i][j][0] - 1][1]
160  n3 = normal_vectors[f_dict[i][j][0] - 1][2]
161  Omega[0][0] = (n2)**2 + (n3)**2
162  Omega[0][1] = -n1 * n2
163  Omega[0][2] = -n3 * n1
164  Omega[1][0] = -n1 * n2
165  Omega[1][1] = (n3)**2 + (n1)**2
166  Omega[1][2] = -n2 * n3
167  Omega[2][0] = -n3 * n1
168  Omega[2][1] = -n2 * n3
169  Omega[2][2] = (n1)**2 + (n2)**2
170  perm_tensor += (phi * (b)**2 * Omega)
171  perm_tensor *= 1. / 12
172 
173  # Calculate eigenvalues
174  permX[i - 1] = np.linalg.eigvals(perm_tensor)[0]
175  permY[i - 1] = np.linalg.eigvals(perm_tensor)[1]
176  permZ[i - 1] = np.linalg.eigvals(perm_tensor)[2]
177 
178  # Arithmetic average of matrix perm
179  permX[i - 1] += (1 - phi_sum) * mat_perm
180  permY[i - 1] += (1 - phi_sum) * mat_perm
181  permZ[i - 1] += (1 - phi_sum) * mat_perm
182 
183  # Correction factor
184 
185  # Actual value doesn't matter here, just needs to be high
186  min_n1 = 1e6
187  min_n2 = 1e6
188  min_n3 = 1e6
189 
190  # See Sweeney et al. 2019 Computational Geoscience
191  for j in range(len(f_dict[i])):
192  n1_temp = normal_vectors[f_dict[i][j][0] - 1][0]
193  theta1_t = m.degrees(m.acos(n1_temp)) % 90
194  if abs(theta1_t - 45) <= min_n1:
195  theta1 = theta1_t
196  min_n1 = theta1_t
197  n2_temp = normal_vectors[f_dict[i][j][0] - 1][1]
198  theta2_t = m.degrees(m.acos(n2_temp)) % 90
199  if abs(theta2_t - 45) <= min_n2:
200  theta2 = theta2_t
201  min_n2 = theta2_t
202  n3_temp = normal_vectors[f_dict[i][j][0] - 1][2]
203  theta3_t = m.degrees(m.acos(n3_temp)) % 90
204  if abs(theta3_t - 45) <= min_n3:
205  theta3 = theta3_t
206  min_n3 = theta3_t
207 
208  sl = (2 * 2**(1. / 2) - 1) / -45.0
209  b = 2 * 2**(1. / 2)
210 
211  cf_x = sl * abs(theta1 - 45) + b
212  cf_y = sl * abs(theta2 - 45) + b
213  cf_z = sl * abs(theta3 - 45) + b
214 
215  permX[i - 1] *= cf_x
216  permY[i - 1] *= cf_y
217  permZ[i - 1] *= cf_z
218 
219  # Correct 0 perm if exists
220  # Note I don't think it's possible for 0 perm to exist
221  # because of L177-9 and 110. Will leave for now...
222  if permX[i - 1] == 0:
223  permX[i - 1] += mat_perm
224  if permY[i - 1] == 0:
225  permY[i - 1] += mat_perm
226  if permZ[i - 1] == 0:
227  permZ[i - 1] += mat_perm
228  perm_var[i - 1] = max(permX[i - 1], permY[i - 1], permZ[i - 1])
229  else:
230  # Assign matrix properties
231  por_var[i - 1] = mat_por
232  perm_var[i - 1] = mat_perm
233 
234  # Note these aren't needed if not using anisotropic perm
235  permX[i - 1] = mat_perm
236  permY[i - 1] = mat_perm
237  permZ[i - 1] = mat_perm
238 
239  if self.flow_solver == "FEHM":
240  with open("perm_fehm.dat", "a") as f:
241  f.write(
242  str(i) + " " + str(i) + " " + "1" + " " +
243  str(perm_var[i - 1]) + " " + str(perm_var[i - 1]) + " " +
244  str(perm_var[i - 1]) + "\n")
245  with open("rock_fehm.dat", "a") as g:
246  g.write(
247  str(i) + " " + str(i) + " " + "1" + " " + "2165." + " " +
248  "931." + " " + str(por_var[i - 1]) + "\n")
249 
250  # Need an extra space at end for FEHM
251  if self.flow_solver == "FEHM":
252  with open("perm_fehm.dat", "a") as f:
253  f.write("\n")
254  with open("rock_fehm.dat", "a") as g:
255  g.write("\n")
256 
257  if self.flow_solver == "PFLOTRAN":
258  perm_filename = 'mesh_permeability.h5'
259  poros_filename = 'mesh_porosity.h5'
260 
261  h5file = h5py.File(perm_filename, mode='w')
262  dataset_name = 'Cell Ids'
263  h5dset = h5file.create_dataset(dataset_name, data=iarray)
264 
265  dataset_name = 'Permeability'
266  h5dset = h5file.create_dataset(dataset_name, data=perm_var)
267 
268  #dataset_name = 'Perm_X'
269  #h5dset = h5file.create_dataset(dataset_name, data = permX)
270 
271  #dataset_name = 'Perm_Y'
272  #h5set = h5file.create_dataset(dataset_name, data = permY)
273 
274  #dataset_name = 'Perm_Z'
275  #h5set = h5file.create_dataset(dataset_name, data = permZ)
276  h5file.close()
277 
278  h5file = h5py.File(poros_filename, mode='w')
279  dataset_name = 'Cell Ids'
280  h5dset = h5file.create_dataset(dataset_name, data=iarray)
281 
282  dataset_name = 'Porosity'
283  h5dset = h5file.create_dataset(dataset_name, data=por_var)
284  h5file.close()
285 
287 
288  # What nodes are fractures vs. matrix
289  tag = perm_var > mat_perm
290  tag.astype("uint8")
291  np.savetxt("tag_frac.dat", tag, '%d', delimiter=",")
292 
293 
295  files_to_remove = [
296  "area*", "build*", "driver*", "ex*", "frac*", "hex*", "intersect*",
297  "log*", "out*", "parame*", "remove*", "time*", "tmp*"
298  ]
299  for name in files_to_remove:
300  for fl in glob.glob(name):
301  os.remove(fl)
def upscale(self, mat_perm, mat_por, path='../')
Definition: upscale.py:21