2 functions for using pflotran in dfnworks
15 """ Takes output from LaGriT and processes it for use in PFLOTRAN.
16 Calls the functuon write_perms_and_correct_volumes_areas() and zone2ex
23 Name of the inp (AVS) file produced by LaGriT
27 True if hex mesh elements should be converted to tet elements, False otherwise.
38 if self.flow_solver !=
"PFLOTRAN":
39 error =
"ERROR! Wrong flow solver requested\n"
40 sys.stderr.write(error)
44 print(
"Starting conversion of files for PFLOTRAN ")
47 self.inp_file = inp_file
49 inp_file = self.inp_file
52 error =
'ERROR: Please provide inp filename!\n'
53 sys.stderr.write(error)
57 if mesh_type
in mesh_types_allowed:
58 self.mesh_type = mesh_type
60 error =
'ERROR: Unknown mesh type. Select one of dfn, volume or mixed!\n'
61 sys.stderr.write(error)
64 mesh_type = self.mesh_type
67 error =
'ERROR: Please provide mesh type!\n'
68 sys.stderr.write(error)
72 self.uge_file = inp_file[:-4] +
'.uge'
73 if not os.path.isfile(self.uge_file):
74 error =
'ERROR!!! Cannot find .uge file\nExiting\n'
75 sys.stderr.write(error)
78 if mesh_type ==
'dfn':
79 self.write_perms_and_correct_volumes_areas(
89 self.zone2ex(zone_file=
'all')
91 print(
"Conversion of files for PFLOTRAN complete")
100 boundary_cell_area=1.e-1):
102 Convert zone files from LaGriT into ex format for LaGriT
112 Face : Face of the plane corresponding to the zone file
114 Name of zone file to work on. Can be 'all' processes all directions, top, bottom, left, right, front, back
115 boundary_cell_area : double
116 should be a large value relative to the mesh size to force pressure boundary conditions.
124 the boundary_cell_area should be a function of h, the mesh resolution
127 print(
'--> Converting zone files to ex')
129 uge_file = self.uge_file
131 self.uge_file = uge_file
133 uge_file = self.uge_file
135 error =
'ERROR: Please provide uge filename!\n'
136 sys.stderr.write(error)
140 print(
'\n--> Opening uge file')
141 fuge = open(uge_file,
'r')
144 line = fuge.readline()
146 NumCells = int(line[1])
148 Cell_id = np.zeros(NumCells,
'int')
149 Cell_coord = np.zeros((NumCells, 3),
'float')
150 Cell_vol = np.zeros(NumCells,
'float')
152 for cells
in range(NumCells):
153 line = fuge.readline()
155 Cell_id[cells] = int(line.pop(0))
156 line = [float(id)
for id
in line]
157 Cell_vol[cells] = line.pop(3)
158 Cell_coord[cells] = line
161 print(
'--> Finished with uge file\n')
164 if zone_file ==
'all':
165 zone_files = [
'pboundary_front_n.zone',
'pboundary_back_s.zone',
'pboundary_left_w.zone', \
166 'pboundary_right_e.zone',
'pboundary_top.zone',
'pboundary_bottom.zone']
167 face_names = [
'north',
'south',
'west',
'east',
'top',
'bottom']
170 error =
'ERROR: Please provide boundary zone filename!\n'
171 sys.stderr.write(error)
174 error =
'ERROR: Please provide face name among: top, bottom, north, south, east, west !\n'
175 sys.stderr.write(error)
177 zone_files = [zone_file]
180 for iface, zone_file
in enumerate(zone_files):
181 face = face_names[iface]
183 ex_file = zone_file.strip(
'zone') +
'ex'
186 print(
'--> Opening zone file: ', zone_file)
187 fzone = open(zone_file,
'r')
193 print(
'--> Calculating number of nodes')
194 num_nodes = int(fzone.readline())
195 Node_array = np.zeros(num_nodes,
'int')
197 print(
'--> Reading boundary node ids')
201 node_array = g.split()
203 node_array = [int(id)
for id
in node_array]
204 Node_array = np.asarray(node_array)
206 for i
in range(int(num_nodes / 10 + (num_nodes % 10 != 0))):
208 node_array = g.split()
210 node_array = [int(id)
for id
in node_array]
211 if (num_nodes - 10 * i < 10):
212 for j
in range(num_nodes % 10):
213 Node_array[i * 10 + j] = node_array[j]
216 Node_array[i * 10 + j] = node_array[j]
218 print(
'--> Finished with zone file')
222 _, self.h, _, _, _ = parse_params_file(quiet=
True)
224 Boundary_cell_area = np.zeros(num_nodes,
'float')
225 for i
in range(num_nodes):
227 i] = boundary_cell_area
229 print(
'--> Finished calculating boundary connections')
230 boundary_cell_coord = [
231 Cell_coord[Cell_id[i - 1] - 1]
for i
in Node_array
233 epsilon = self.h * 10**-3
236 boundary_cell_coord = [[cell[0], cell[1], cell[2] + epsilon]
237 for cell
in boundary_cell_coord]
238 elif (face ==
'bottom'):
239 boundary_cell_coord = [[cell[0], cell[1], cell[2] - epsilon]
240 for cell
in boundary_cell_coord]
241 elif (face ==
'north'):
242 boundary_cell_coord = [[cell[0], cell[1] + epsilon, cell[2]]
243 for cell
in boundary_cell_coord]
244 elif (face ==
'south'):
245 boundary_cell_coord = [[cell[0], cell[1] - epsilon, cell[2]]
246 for cell
in boundary_cell_coord]
247 elif (face ==
'east'):
248 boundary_cell_coord = [[cell[0] + epsilon, cell[1], cell[2]]
249 for cell
in boundary_cell_coord]
250 elif (face ==
'west'):
251 boundary_cell_coord = [[cell[0] - epsilon, cell[1], cell[2]]
252 for cell
in boundary_cell_coord]
253 elif (face ==
'well'):
254 boundary_cell_coord = [[cell[0], cell[1], cell[2] + epsilon]
255 for cell
in boundary_cell_coord]
256 elif (face ==
'none'):
257 boundary_cell_coord = [[cell[0], cell[1], cell[2]]
258 for cell
in boundary_cell_coord]
260 error =
'ERROR: unknown face. Select one of: top, bottom, east, west, north, south.\n'
261 sys.stderr.write(error)
264 with open(ex_file,
'w')
as f:
265 f.write(
'CONNECTIONS\t%i\n' % Node_array.size)
266 for idx, cell
in enumerate(boundary_cell_coord):
267 f.write(
'%i\t%.6e\t%.6e\t%.6e\t%.6e\n' %
268 (Node_array[idx], cell[0], cell[1], cell[2],
269 Boundary_cell_area[idx]))
270 print(
'--> Finished writing ex file "' + ex_file +
271 '" corresponding to the zone file: ' + zone_file +
'\n')
273 print(
'--> Converting zone files to ex complete')
277 """ Write permeability values to perm_file, write aperture values to aper_file, and correct volume areas in uge_file
290 Calls executable correct_uge
293 if self.flow_solver !=
"PFLOTRAN":
294 error =
"ERROR! Wrong flow solver requested\n"
295 sys.stderr.write(error)
298 print(
"--> Writing Perms and Correct Volume Areas")
299 inp_file = self.inp_file
301 error =
'ERROR: inp file must be specified!\n'
302 sys.stderr.write(error)
305 uge_file = self.uge_file
307 error =
'ERROR: uge file must be specified!\n'
308 sys.stderr.write(error)
311 perm_file = self.perm_file
312 if perm_file ==
'' and self.perm_cell_file ==
'':
313 error =
'ERROR: perm file must be specified!\n'
314 sys.stderr.write(error)
317 aper_file = self.aper_file
318 aper_cell_file = self.aper_cell_file
319 if aper_file ==
'' and self.aper_cell_file ==
'':
320 error =
'ERROR: aperture file must be specified!\n'
321 sys.stderr.write(error)
324 mat_file =
'materialid.dat'
327 f = open(
"convert_uge_params.txt",
"w")
328 f.write(
"%s\n" % inp_file)
329 f.write(
"%s\n" % mat_file)
330 f.write(
"%s\n" % uge_file)
331 f.write(
"%s" % (uge_file[:-4] +
'_vol_area.uge\n'))
332 if self.aper_cell_file:
333 f.write(
"%s\n" % self.aper_cell_file)
336 f.write(
"%s\n" % self.aper_file)
340 cmd = os.environ[
'CORRECT_UGE_EXE'] +
' convert_uge_params.txt'
341 failure = subprocess.call(cmd, shell=
True)
343 error =
'ERROR: UGE conversion failed\nExiting Program\n'
344 sys.stderr.write(error)
348 print(
'--> Time elapsed for UGE file conversion: %0.3f seconds\n' %
351 print(
'--> Writing HDF5 File')
352 materialid = np.genfromtxt(mat_file, skip_header=3).astype(int)
353 materialid = -1 * materialid - 6
354 NumIntNodes = len(materialid)
357 filename =
'dfn_properties.h5'
358 h5file = h5py.File(filename, mode=
'w')
359 print(
'--> Beginning writing to HDF5 file')
360 print(
'--> Allocating cell index array')
361 iarray = np.zeros(NumIntNodes,
'=i4')
362 print(
'--> Writing cell indices')
364 for i
in range(NumIntNodes):
366 dataset_name =
'Cell Ids'
367 h5dset = h5file.create_dataset(dataset_name, data=iarray)
369 print(
'--> Allocating permeability array')
370 perm = np.zeros(NumIntNodes,
'=f8')
372 print(
'--> reading permeability data')
373 print(
'--> Note: this script assumes isotropic permeability')
374 perm_list = np.genfromtxt(perm_file, skip_header=1)
375 perm_list = np.delete(perm_list, np.s_[1:5], 1)
377 matid_index = -1 * materialid - 7
378 for i
in range(NumIntNodes):
380 if int(perm_list[j, 0]) == materialid[i]:
381 perm[i] = perm_list[j, 1]
383 error =
'Indexing Error in Perm File\n'
384 sys.stderr.write(error)
387 dataset_name =
'Permeability'
388 h5dset = h5file.create_dataset(dataset_name, data=perm)
391 print(
"--> Done writing permeability to h5 file")
394 if self.perm_cell_file:
395 filename =
'dfn_properties.h5'
396 h5file = h5py.File(filename, mode=
'w')
398 print(
'--> Beginning writing to HDF5 file')
399 print(
'--> Allocating cell index array')
400 iarray = np.zeros(NumIntNodes,
'=i4')
401 print(
'--> Writing cell indices')
403 for i
in range(NumIntNodes):
405 dataset_name =
'Cell Ids'
406 h5dset = h5file.create_dataset(dataset_name, data=iarray)
407 print(
'--> Allocating permeability array')
408 perm = np.zeros(NumIntNodes,
'=f8')
409 print(
'--> reading permeability data')
410 print(
'--> Note: this script assumes isotropic permeability')
411 f = open(self.perm_cell_file,
'r')
422 perm_list = [float(perm[0])
for perm
in perm_list]
424 dataset_name =
'Permeability'
425 h5dset = h5file.create_dataset(dataset_name, data=perm_list)
429 print(
'--> Done writing permeability to h5 file')
432 def pflotran(self, transient=False, restart=False, restart_file=''):
433 """ Run PFLOTRAN. Copy PFLOTRAN run file into working directory and run with ncpus
440 Boolean if PFLOTRAN is running in transient mode
442 Boolean if PFLOTRAN is restarting from checkpoint
443 restart_file : string
444 Filename of restart file
452 Runs PFLOTRAN Executable, see http://www.pflotran.org/ for details on PFLOTRAN input cards
454 if self.flow_solver !=
"PFLOTRAN":
455 error =
"ERROR! Wrong flow solver requested\n"
456 sys.stderr.write(error)
460 shutil.copy(os.path.abspath(self.dfnFlow_file),
461 os.path.abspath(os.getcwd()))
463 error =
"--> ERROR!! Unable to copy PFLOTRAN input file\n"
464 sys.stderr.write(error)
468 print(
"--> Running PFLOTRAN")
469 cmd = os.environ[
'PETSC_DIR']+
'/'+os.environ[
'PETSC_ARCH']+
'/bin/mpirun -np ' + str(self.ncpu) + \
470 ' ' + os.environ[
'PFLOTRAN_EXE'] +
' -pflotranin ' + self.local_dfnFlow_file
471 print(
"Running: %s" % cmd)
472 subprocess.call(cmd, shell=
True)
475 error =
"ERROR!!!! PFLOTRAN did not converge. Consider running in transient mode to march to steady-state\n"
476 sys.stderr.write(error)
481 shutil.copy(os.path.abspath(restart_file),
482 os.path.abspath(os.getcwd()))
484 error =
"--> ERROR!! Unable to copy PFLOTRAN restart input file\n"
485 sys.stderr.write(error)
489 print(
"--> Running PFLOTRAN")
490 cmd = os.environ[
'PETSC_DIR']+
'/'+os.environ[
'PETSC_ARCH']+
'/bin/mpirun -np ' + str(self.ncpu) + \
491 ' ' + os.environ[
'PFLOTRAN_EXE'] +
' -pflotranin ' + ntpath.basename(restart_file)
492 print(
"Running: %s" % cmd)
493 subprocess.call(cmd, shell=
True)
496 print(
"--> Running PFLOTRAN Complete")
502 """ checks pflotran_input_file.out for convergence
506 pflotran_input_file : string
512 True if solver converged / False if not
518 with open(pflotran_input_file,
"r")
as fp:
519 for line
in fp.readlines():
520 if "STEADY_STATE" in line:
524 pflotran_output_file = pflotran_input_file[:-2] +
"out"
525 print(
"\n--> Opening %s to check for convergence" %
526 pflotran_output_file)
527 with open(pflotran_output_file,
"r")
as fp:
528 for line
in fp.readlines():
529 if "STEADY-SOLVE 1 snes_conv_reason:" in line:
530 print(
"--> PFLOTRAN converged")
536 "PFLOTRAN ran in transient mode, unable to check for steady-state convergence"
543 Concatenate PFLOTRAN output files and then delete them
550 If PFLOTRAN has multiple dumps use this to pick which dump is put into cellinfo.dat and darcyvel.dat
557 Can be run in a loop over all pflotran dumps
559 if self.flow_solver !=
"PFLOTRAN":
560 error =
"ERROR! Wrong flow solver requested\n"
561 sys.stderr.write(error)
565 filename = self.local_dfnFlow_file[:-3]
567 filename = ntpath.basename(filename[:-3])
569 print(
'--> Processing PFLOTRAN output')
571 for index
in range(index_start, index_finish + 1):
572 cmd =
'cat ' + filename +
'-cellinfo-%03d-rank*.dat > cellinfo_%03d.dat' % (
574 print(
"Running >> %s" % cmd)
575 subprocess.call(cmd, shell=
True)
577 cmd =
'cat ' + filename +
'-darcyvel-%03d-rank*.dat > darcyvel_%03d.dat' % (
579 print(
"Running >> %s" % cmd)
580 subprocess.call(cmd, shell=
True)
587 for fl
in glob.glob(filename +
'-cellinfo-%03d-rank*.dat' % index):
589 for fl
in glob.glob(filename +
'-darcyvel-%03d-rank*.dat' % index):
592 os.symlink(
"darcyvel_%03d.dat" % index_finish,
"darcyvel.dat")
594 print(
"--> WARNING!!! Unable to create symlink for darcyvel.dat")
596 os.symlink(
"cellinfo_%03d.dat" % index_finish,
"cellinfo.dat")
598 print(
"--> WARNING!!! Unable to create symlink for cellinfo.dat")
603 """ Adds CELL_DATA to POINT_DATA in the VTK output from PFLOTRAN.
608 grid_vtk_file : string
609 Name of vtk file with mesh. Typically local_dfnFlow_file.vtk
617 If DFN class does not have a vtk file, inp2vtk_python is called
619 print(
'--> Parsing PFLOTRAN output with Python')
621 if self.flow_solver !=
"PFLOTRAN":
622 error =
"ERROR! Wrong flow solver requested\n"
623 sys.stderr.write(error)
627 self.vtk_file = grid_vtk_file
629 self.inp2vtk_python()
631 grid_file = self.vtk_file
633 files = glob.glob(
'*-[0-9][0-9][0-9].vtk')
636 with open(grid_file,
'r')
as f:
637 grid = f.readlines()[3:]
639 out_dir =
'parsed_vtk'
643 num_cells = line.strip(
' ').split()[1]
646 print(f
"--> Processing file: {file}")
647 with open(file,
'r')
as f:
648 pflotran_out = f.readlines()[4:]
650 w.replace(
'CELL_DATA',
'POINT_DATA ')
for w
in pflotran_out
653 '# vtk DataFile Version 2.0\n',
'PFLOTRAN output\n',
'ASCII\n'
655 filename = out_dir +
'/' + file
656 if not os.path.exists(os.path.dirname(filename)):
657 os.makedirs(os.path.dirname(filename))
658 with open(filename,
'w')
as f:
666 f.write(
'POINT_DATA\t ' + num_cells +
'\n')
667 for line
in pflotran_out:
670 print(
'--> Parsing PFLOTRAN output complete')
def pflotran_cleanup(self, index_start=0, index_finish=1, filename='')
def write_perms_and_correct_volumes_areas(self)
def zone2ex(self, uge_file='', zone_file='', face='', boundary_cell_area=1.e-1)
def parse_pflotran_vtk_python(self, grid_vtk_file='')
def pflotran(self, transient=False, restart=False, restart_file='')
def check_pflotran_convergence(pflotran_input_file)
def lagrit2pflotran(self, inp_file='', mesh_type='', hex2tet=False)