pydfnWorks
python wrapper for dfnWorks
lagrit_scripts.py
Go to the documentation of this file.
1 """
2 .. module:: lagrit_scripts.py
3  :synopsis: create lagrit scripts for meshing dfn using LaGriT
4 .. moduleauthor:: Jeffrey Hyman <jhyman@lanl.gov>
5 
6 """
7 import os
8 import sys
9 import glob
10 from shutil import copy, rmtree, move
11 from numpy import genfromtxt, sqrt, cos, arcsin
12 import subprocess
13 
14 
15 def edit_intersection_files(num_poly, fracture_list, path):
16  """ If pruning a DFN, this function walks through the intersection files
17  and removes references to files that are not included in the
18  fractures that will remain in the network.
19 
20  Parameters
21  ---------
22  num_poly : int
23  Number of Fractures in the original DFN
24  fracture_list :list of int
25  List of fractures to keep in the DFN
26 
27  Returns
28  -------
29  None
30 
31  Notes
32  -----
33  1. Currently running in serial, but it could be parallelized
34  2. Assumes the pruning directory is not the original directory
35 
36  """
37  # Make list of connectivity.dat
38  connectivity = []
39  fp = open("connectivity.dat", "r")
40  for i in range(num_poly):
41  tmp = []
42  line = fp.readline()
43  line = line.split()
44  for frac in line:
45  tmp.append(int(frac))
46  connectivity.append(tmp)
47  fp.close()
48 
49  fractures_to_remove = list(
50  set(range(1, num_poly + 1)) - set(fracture_list))
51  cwd = os.getcwd()
52  os.chdir('intersections')
53  # clean up directory
54  #fl_list = glob.glob("*prune.inp")
55  #for fl in fl_list:
56  # os.remove(fl)
57 
58  print("Editing Intersection Files")
59  for i in fracture_list:
60  filename = 'intersections_%d.inp' % i
61  print('--> Working on: %s' % filename)
62  intersecting_fractures = connectivity[i - 1]
63  pull_list = list(
64  set(intersecting_fractures).intersection(set(fractures_to_remove)))
65  if len(pull_list) > 0:
66  # Create Symlink to origignal intersection file
67  os.symlink(path + 'intersections/' + filename, filename)
68  # Create LaGriT script to remove intersections with fractures not in prune_file
69  lagrit_script = 'read / %s / mo1' % filename
70  lagrit_script += '''
71 pset / pset2remove / attribute / b_a / 1,0,0 / eq / %d
72  ''' % pull_list[0]
73  for j in pull_list[1:]:
74  lagrit_script += '''
75 pset / prune / attribute / b_a / 1,0,0 / eq / %d
76 pset / pset2remove / union / pset2remove, prune
77 #rmpoint / pset, get, prune
78 pset / prune / delete
79  ''' % j
80  lagrit_script += '''
81 rmpoint / pset, get, pset2remove
82 rmpoint / compress
83 
84 cmo / modatt / mo1 / imt / ioflag / l
85 cmo / modatt / mo1 / itp / ioflag / l
86 cmo / modatt / mo1 / isn / ioflag / l
87 cmo / modatt / mo1 / icr / ioflag / l
88 
89 cmo / status / brief
90 dump / intersections_%d_prune.inp / mo1
91 finish
92 
93 ''' % i
94 
95  lagrit_filename = 'prune_intersection.lgi'
96  f = open(lagrit_filename, 'w')
97  f.write(lagrit_script)
98  f.flush()
99  f.close()
100  subprocess.call(os.environ['LAGRIT_EXE'] + \
101  '< prune_intersection.lgi > out_%d.txt'%i,shell=True)
102  os.remove(filename)
103  move("intersections_%d_prune.inp" % i, "intersections_%d.inp" % i)
104  else:
105  try:
106  copy(path + 'intersections/' + filename, filename)
107  except:
108  pass
109  os.chdir(cwd)
110 
111 
112 def create_parameter_mlgi_file(fracture_list, h, slope=2.0, refine_dist=0.5):
113  """Create parameteri.mlgi files used in running LaGriT Scripts
114 
115  Parameters
116  ----------
117  num_poly : int
118  Number of polygons
119  h : float
120  Meshing length scale
121  slope : float
122  Slope of coarsening function, default = 2
123  refine_dist : float
124  Distance used in coarsening function, default = 0.5
125 
126  Returns
127  -------
128  None
129 
130  Notes
131  -----
132  Set slope = 0 for uniform mesh
133  """
134 
135  print("\n--> Creating parameter*.mlgi files")
136  try:
137  os.mkdir('parameters')
138  except OSError:
139  rmtree('parameters')
140  os.mkdir('parameters')
141 
142  # Extrude and Translate computation
143  # Parameters, delta: buffer zone, amount of h/2 we remove from around line
144  # h_extrude height of rectangle extruded from line of intersection
145  # r_radius: Upper bound on radius of circumscribed circle around rectangle
146  # h_trans : amount needed to translate to create delta buffer
147  # It's just a little trig!
148  delta = 0.75
149  h_extrude = 0.5 * h # upper limit on spacing of points on interssction line
150  h_radius = sqrt((0.5 * h_extrude)**2 + (0.5 * h_extrude)**2)
151  h_trans = -0.5 * h_extrude + h_radius * cos(arcsin(delta))
152 
153  #Go through the list and write out parameter file for each polygon
154  #to be an input file for LaGriT
155  data = genfromtxt('poly_info.dat')
156  for index, i in enumerate(fracture_list):
157  # using i - 1 do to python indexing from 0
158  # fracture index starts at 1
159  frac_id = str(int(data[i - 1, 0]))
160  long_name = str(int(data[i - 1, 0]))
161  theta = data[i - 1, 2]
162  x1 = data[i - 1, 3]
163  y1 = data[i - 1, 4]
164  z1 = data[i - 1, 5]
165  x2 = data[i - 1, 6]
166  y2 = data[i - 1, 7]
167  z2 = data[i - 1, 8]
168  family = data[i - 1, 1]
169 
170  fparameter_name = 'parameters/parameters_' + long_name + '.mlgi'
171  f = open(fparameter_name, 'w')
172  f.write('define / ID / ' + str(index + 1) + '\n')
173  f.write('define / OUTFILE_GMV / mesh_' + long_name + '.gmv\n')
174  f.write('define / OUTFILE_AVS / mesh_' + long_name + '.inp\n')
175  f.write('define / OUTFILE_LG / mesh_' + long_name + '.lg\n')
176  f.write('define / POLY_FILE / poly_' + long_name + '.inp\n')
177  f.write('define / QUAD_FILE / tmp_quad_' + frac_id + '.inp\n')
178  f.write('define / EXCAVATE_FILE / tmp_excavate_' + frac_id + '.inp\n')
179  f.write('define / PRE_FINAL_FILE / tmp_pre_final_' + frac_id +
180  '.inp\n')
181  f.write('define / PRE_FINAL_MASSAGE / tmp_pre_final_massage_' +
182  frac_id + '.gmv\n')
183 
184  f.write('define / H_SCALE / %e \n' % h)
185  f.write('define / H_EPS / %e \n' % (h * 10**-7))
186  f.write('define / H_SCALE2 / %e \n' % (1.5 * h))
187 
188  f.write('define / H_EXTRUDE / %e \n' % (h_extrude))
189  f.write('define / H_TRANS / %e \n' % (h_trans))
190 
191  f.write('define / H_PRIME / %e \n' % (0.8 * h))
192  f.write('define / H_PRIME2 / %e \n' % (0.3 * h))
193 
194  f.write('define / H_SCALE3 / %e \n' % (3.0 * h))
195  f.write('define / H_SCALE8 / %e \n' % (8.0 * h))
196  f.write('define / H_SCALE16 / %e \n' % (16.0 * h))
197  f.write('define / H_SCALE32 / %e \n' % (32.0 * h))
198  f.write('define / H_SCALE64 / %e \n' % (64.0 * h))
199 
200  f.write('define / PERTURB8 / %e \n' % (8 * 0.05 * h))
201  f.write('define / PERTURB16 / %e \n' % (16 * 0.05 * h))
202  f.write('define / PERTURB32 / %e \n' % (32 * 0.05 * h))
203  f.write('define / PERTURB64 / %e \n' % (64 * 0.05 * h))
204 
205  f.write('define / PARAM_A / %f \n' % slope)
206  f.write('define / PARAM_B / %f \n' % (h * (1 - slope * refine_dist)))
207 
208  f.write('define / PARAM_A2 / %f \n' % (0.5 * slope))
209  f.write('define / PARAM_B2 / %f \n' %
210  (h * (1 - 0.5 * slope * refine_dist)))
211 
212  f.write('define / THETA / %0.12f \n' % theta)
213  f.write('define / X1 / %0.12f \n' % x1)
214  f.write('define / Y1 / %0.12f \n' % y1)
215  f.write('define / Z1 / %0.12f \n' % z1)
216  f.write('define / X2 / %0.12f \n' % x2)
217  f.write('define / Y2 / %0.12f \n' % y2)
218  f.write('define / Z2 / %0.12f \n' % z2)
219  f.write('define / FAMILY / %d \n' % family)
220  f.write('finish \n')
221  f.flush()
222  f.close()
223  print("--> Creating parameter*.mlgi files: Complete\n")
224 
225 
226 def create_lagrit_scripts(visual_mode,
227  ncpu,
228  refine_factor=1,
229  production_mode=True):
230  """ Creates LaGriT script to be mesh each polygon
231 
232  Parameters
233  ----------
234  visual_mode : bool
235  Sets if running if visual mode or in full dump
236  ncpu : int
237  Number of cpus
238  refine_factor : int
239  Number of times original polygon gets refined
240  production_mode : bool
241  Determines if clean up of work files occurs on the fly.
242 
243  Returns
244  -------
245  None
246 
247  Notes
248  -----
249  1. Only ncpu of these files are created
250  2. Symbolic links are used to rotate through fractures on different CPUs
251  """
252 
253  #Section 2 : Creates LaGriT script to be run for each polygon
254  #Switches to control the LaGriT output
255  #Network visualization mode True ouputs the triangulated mesh
256  #for each fracture without any refinement. The goal is to visualize
257  #the network structure instead of outputing the appropriate values
258  #for computation
259 
260  print("--> Writing LaGriT Control Files")
261  #Go through the list and write out parameter file for each polygon
262  #to be an input file for LaGriT
263 
264  lagrit_input = """infile %s
265 #LaGriT Script
266 # Name the input files that contain the polygons
267 # and lines of intersection.
268 
269 define / POLY_FILE / %s
270 define / LINE_FILE / %s
271 define / OUTPUT_INTER_ID_SSINT / id_tri_node_CPU%d.list
272 
273 # Define parameters such as:
274 # length scale to refine triangular mesh
275 # purturbation distance to break symmetry of refined mesh#
276 
277 # Read in line and polygon files
278 read / POLY_FILE / mo_poly_work
279 """
280  if not visual_mode:
281  lagrit_input += """
282 read / LINE_FILE / mo_line_work
283 """
284  #
285  # START: Refine the point distribution
286  #
287  if (refine_factor > 1):
288  lagrit_input += 'extrude / mo_quad_work / mo_line_work / const / H_SCALE8 / volume / 0. 0. 1. \n'
289  if (refine_factor == 2):
290  lagrit_input += 'refine/constant/imt1/linear/element/1 0 0 /-1.,0.,0./inclusive amr 2 \n'
291 
292  if (refine_factor == 4):
293  lagrit_input += 'refine/constant/imt1/linear/element/1 0 0 /-1.,0.,0./inclusive amr 2 \n'
294  lagrit_input += 'refine/constant/imt1/linear/element/1 0 0 /-1.,0.,0./inclusive amr 2 \n'
295 
296  if (refine_factor == 8):
297  lagrit_input += 'refine/constant/imt1/linear/element/1 0 0 /-1.,0.,0./inclusive amr 2 \n'
298  lagrit_input += 'refine/constant/imt1/linear/element/1 0 0 /-1.,0.,0./inclusive amr 2 \n'
299  lagrit_input += 'refine/constant/imt1/linear/element/1 0 0 /-1.,0.,0./inclusive amr 2 \n'
300 
301  lagrit_input += """
302 # Convert octree data structure with overlapping parent/child cells to a
303 # simple octree mesh that only keeps the child cells.
304 grid2grid / tree_to_fe / mo_quad_work / mo_quad_work
305 # Extract a quad surface mesh of the exterior of the octree mesh.
306 extract / surfmesh / 1,0,0 / mo_ext_work / mo_quad_work / external
307 # Compute the distance field from mo_line_work to mo_ext_work and
308 # put the distance field in attribute dfield.
309 compute / distance_field / mo_ext_work / mo_line_work / dfield
310 # Make a pset of vertices that have dfield values greater than H_SCALE3
311 pset / pdel_work / attribute / dfield / 1 0 0 / H_SCALE3 / gt
312 # Delete all the exterior surface quads in the pset
313 rmpoint / pset get pdel_work / inclusive
314 rmpoint / compress
315 # The mesh object mo_ext_work now exists only where dfield is < H_SCALE3
316 
317 # Clean up some mesh objects
318 cmo / delete / mo_quad_work
319 cmo / delete / mo_line_work
320 # Change the name of mo_ext_work to mo_line_work
321 cmo / move / mo_line_work / mo_ext_work
322 rmpoint / compress
323 
324 """
325  # END: Refine the point distribution
326  #
327  lagrit_input += """
328 ## Triangulate Fracture without point addition
329 cmo / create / mo_pts / / / triplane
330 copypts / mo_pts / mo_poly_work
331 cmo / select / mo_pts
332 triangulate / counterclockwise
333 
334 cmo / setatt / mo_pts / imt / 1 0 0 / ID
335 cmo / setatt / mo_pts / itetclr / 1 0 0 / ID
336 resetpts / itp
337 cmo / delete / mo_poly_work
338 cmo / select / mo_pts
339 
340 """
341  if not visual_mode:
342  lagrit_input += """
343 # Creates a Coarse Mesh and then refines it using the distance field from intersections
344 massage / H_SCALE64 / H_EPS / H_EPS
345 recon 0; smooth;recon 0;smooth;recon 0;smooth;recon 0
346 resetpts / itp
347 pset / p_move / attribute / itp / 1 0 0 / 0 / eq
348 perturb / pset get p_move / PERTURB64 PERTURB64 0.0
349 recon 0; smooth;recon 0;smooth;recon 0;smooth;recon 0
350 smooth;recon 0;smooth;recon 0;smooth;recon 0
351 
352 massage / H_SCALE32 / H_EPS / H_EPS
353 resetpts / itp
354 pset / p_move / attribute / itp / 1 0 0 / 0 / eq
355 perturb / pset get p_move / PERTURB32 PERTURB32 0.0
356 recon 0; smooth;recon 0;smooth;recon 0;smooth;recon 0
357 smooth;recon 0;smooth;recon 0;smooth;recon 0
358 
359 massage / H_SCALE16 / H_EPS / H_EPS
360 resetpts / itp
361 pset / p_move / attribute / itp / 1 0 0 / 0 / eq
362 perturb / pset get p_move / PERTURB16 PERTURB16 0.0
363 recon 0; smooth;recon 0;smooth;recon 0;smooth;recon 0
364 smooth;recon 0;smooth;recon 0;smooth;recon 0
365 
366 massage / H_SCALE8 / H_EPS / H_EPS
367 resetpts / itp
368 pset / p_move / attribute / itp / 1 0 0 / 0 / eq
369 perturb / pset get p_move / PERTURB8 PERTURB8 0.0
370 recon 0; smooth;recon 0;smooth;recon 0;smooth;recon 0
371 smooth;recon 0;smooth;recon 0;smooth;recon 0
372 
373 cmo/addatt/ mo_pts /x_four/vdouble/scalar/nnodes
374 cmo/addatt/ mo_pts /fac_n/vdouble/scalar/nnodes
375 
376 # Massage points based on linear function down to h_prime
377 massage2/user_function2.lgi/H_PRIME/fac_n/1.e-5/1.e-5/1 0 0/strictmergelength
378 
379 assign///maxiter_sm/1
380 smooth;recon 0;smooth;recon 0;smooth;recon 0
381 
382 assign///maxiter_sm/10
383 
384 massage2/user_function.lgi/H_PRIME/fac_n/1.e-5/1.e-5/1 0 0/strictmergelength
385 cmo / DELATT / mo_pts / rf_field_name
386 
387 # Extrude and excavate the lines of intersection
388 cmo / select / mo_line_work
389 
390 extrude / mo_quad / mo_line_work / const / H_EXTRUDE / volume / 0. 0. 1.
391 """
392  if not production_mode:
393  lagrit_input += """
394 dump / avs / QUAD_FILE / mo_quad
395 cmo / delete / mo_quad
396 read / QUAD_FILE / mo_quad
397 """
398  else:
399  lagrit_input += 'cmo / select / mo_quad \n'
400 
401  lagrit_input += """
402 # Translate extruced lines of intersectino down slightly to excavate
403 # nearby points from the mesh
404 
405 trans / 1 0 0 / 0. 0. 0. / 0. 0. H_TRANS
406 hextotet / 2 / mo_tri / mo_quad
407 cmo / delete / mo_quad
408 addmesh / excavate / mo_excavate / mo_pts / mo_tri
409 
410 ##### DEBUG #####
411 # If meshing fails, uncomment and rerun the script to get tmp meshes,
412 # which are otherwise not output
413 #dump / avs2 / tmp_tri.inp / mo_tri / 1 1 1 0
414 #dump / avs2 / tmp_pts.inp / mo_pts / 1 1 1 0
415 #dump / avs2 / tmp_excavate.inp / mo_excavate / 1 1 1 0
416 #finish
417 #####
418 
419 cmo / delete / mo_tri
420 cmo / delete / mo_pts
421 
422 # recompute dfield
423 cmo / create / mo_final / / / triplane
424 copypts / mo_final / mo_excavate
425 compute / distance_field / mo_final / mo_line_work / dfield
426 cmo / printatt / mo_final / dfield / minmax
427 pset / pdel / attribute dfield / 1,0,0 / lt H_PRIME2
428 rmpoint / pset,get,pdel / inclusive
429 rmpoint / compress
430 
431 copypts / mo_final / mo_line_work
432 
433 cmo / select / mo_final
434 cmo / setatt / mo_final / imt / 1 0 0 / ID
435 cmo / setatt / mo_final / itp / 1 0 0 / 0
436 cmo / setatt / mo_final / itetclr / 1 0 0 / ID
437 # cmo / printatt / mo_final / -xyz- / minmax
438 trans/ 1 0 0 / zero / xyz
439 cmo / setatt / mo_final / zic / 1 0 0 / 0.0
440 cmo / printatt / mo_final / -xyz- / minmax
441 connect
442 
443 trans / 1 0 0 / original / xyz
444 cmo / printatt / mo_final / -xyz- / minmax
445 
446 #cmo / delete / mo_line_work
447 cmo / delete / mo_excavate
448 cmo / select / mo_final
449 resetpts / itp
450 
451 """
452  if not production_mode:
453  lagrit_input += 'dump / gmv / PRE_FINAL_MASSAGE / mo_final \n'
454 
455  lagrit_input += """
456 ## Massage Mesh Away from Intersection
457 pset / pref / attribute / dfield / 1,0,0 / lt / H_EPS
458 pset / pregion / attribute / dfield / 1,0,0 / gt / H_SCALE2
459 pset / pboundary / attribute / itp / 1,0,0 / eq / 10
460 pset / psmooth / not / pregion pref pboundary
461 #massage / H_SCALE / 1.e-5 / 1.e-5 / pset get pref / &
462 #nosmooth / strictmergelenth
463 
464 assign///maxiter_sm/1
465 
466 smooth / position / esug / pset get psmooth; recon 0;
467 smooth / position / esug / pset get psmooth; recon 0;
468 smooth / position / esug / pset get psmooth; recon 0;
469 
470 assign///maxiter_sm/10
471 ###########################################
472 # nodes for Intersection / Mesh Connectivity Check
473 cmo / copy / mo_final_check / mo_final
474 #
475 # Define variables that are hard wired for this part of the workflow
476 define / MO_TRI_MESH_SSINT / mo_tri_tmp_subset
477 define / MO_LINE_MESH_SSINT / mo_line_tmp_subset
478 define / ATT_ID_INTERSECTION_SSINT / b_a
479 define / ATT_ID_SOURCE_SSINT / id_node_global
480 define / ATT_ID_SINK_SSINT / id_node_tri
481 #
482 # Before subsetting the mesh reate a node attribute containing the integer global node number
483 cmo / set_id / mo_final_check / node / ATT_ID_SOURCE_SSINT
484 #
485 # Subset the triangle mesh based on b_a node attribute ne 0
486 #
487 cmo / select / mo_final_check
488 pset / pkeep / attribute / ATT_ID_INTERSECTION_SSINT / 1 0 0 / ne / 0
489 pset / pall / seq / 1 0 0
490 pset / pdel / not pall pkeep
491 rmpoint / pset get pdel / exclusive
492 rmpoint / compress
493 #
494 # Create an integer node attribute in the line mesh to interpolate the triangle node number onto
495 #
496 cmo / addatt / mo_line_work / ATT_ID_SINK_SSINT / vint / scalar / nnodes
497 interpolate / voronoi / mo_line_work ATT_ID_SINK_SSINT / 1 0 0 / &
498  mo_final_check ATT_ID_SOURCE_SSINT
499 #
500 # Supress AVS output of a bunch of node attributes
501 #
502 cmo / modatt / mo_line_work / imt / ioflag / l
503 cmo / modatt / mo_line_work / itp / ioflag / l
504 cmo / modatt / mo_line_work / isn / ioflag / l
505 cmo / modatt / mo_line_work / icr / ioflag / l
506 cmo / modatt / mo_line_work / a_b / ioflag / l
507 cmo / modatt / mo_line_work / b_a / ioflag / l
508 #
509 # Output list of intersection nodes with the corrosponding node id number from the triangle mesh
510 
511 dump / avs2 / OUTPUT_INTER_ID_SSINT / mo_line_work / 0 0 2 0
512 cmo / delete / mo_line_work
513 
514 cmo / delete / mo_final_check
515 # nodes for intersection check over
516 
517 cmo / select / mo_final
518 
519 ##### DEBUG
520 # write out mesh before it is rotate back into its final location
521 # Useful to compare with meshing workflow if something crashes
522 #dump / avs2 / tmp_mesh_2D.inp / mo_final / 1 1 1 0
523 ##### DEBUG
524 # Rotate facture back into original plane
525 rotateln / 1 0 0 / nocopy / X1, Y1, Z1 / X2, Y2, Z2 / THETA / 0.,0.,0.,/
526 cmo / printatt / mo_final / -xyz- / minmax
527 recon 1
528 
529 resetpts / itp
530 
531 cmo / addatt / mo_final / unit_area_normal / xyz / vnorm
532 cmo / addatt / mo_final / scalar / xnorm ynorm znorm / vnorm
533 cmo / DELATT / mo_final / vnorm
534 
535 """
536  # Clean up before output to GMV/AVS
537  if production_mode:
538  lagrit_input += """
539 cmo / DELATT / mo_final / x_four
540 cmo / DELATT / mo_final / fac_n
541 cmo / DELATT / mo_final / rf_field_name
542 cmo / DELATT / mo_final / xnorm
543 cmo / DELATT / mo_final / ynorm
544 cmo / DELATT / mo_final / znorm
545 cmo / DELATT / mo_final / a_b
546 cmo / setatt / mo_final / ipolydat / no
547 cmo / modatt / mo_final / icr1 / ioflag / l
548 cmo / modatt / mo_final / isn1 / ioflag / l
549 
550 # Create Family element set
551 cmo / addatt / mo_final / family_id / vint / scalar / nelements
552 cmo / setatt / mo_final / family_id / 1 0 0 / FAMILY
553 
554 """
555  lagrit_input += """
556 dump / OUTFILE_AVS / mo_final
557 dump / lagrit / OUTFILE_LG / mo_final
558 """
559  else:
560  lagrit_input += """
561 cmo / setatt / mo_pts / imt / 1 0 0 / ID
562 cmo / setatt / mo_pts / itetclr / 1 0 0 / ID
563 resetpts / itp
564 
565 cmo / setatt / mo_line_work / imt / 1 0 0 / ID
566 cmo / setatt / mo_line_work / itetclr / 1 0 0 / ID
567 
568 addmesh / merge / mo_final / mo_pts / mo_line_work
569 cmo / delete / mo_pts
570 cmo / delete / mo_line_work
571 
572 # Create Family element set
573 cmo / addatt / mo_final / family_id / vint / scalar / nelements
574 cmo / setatt / mo_final / family_id / 1 0 0 / FAMILY
575 
576 cmo / select / mo_final
577 # Rotate
578 rotateln / 1 0 0 / nocopy / X1, Y1, Z1 / X2, Y2, Z2 / THETA / 0.,0.,0.,/
579 
580 cmo / printatt / mo_final / -xyz- / minmax
581 cmo / modatt / mo_final / icr1 / ioflag / l
582 cmo / modatt / mo_final / isn1 / ioflag / l
583 dump / lagrit / OUTFILE_LG / mo_final
584 """
585 
586  lagrit_input += """
587 quality
588 cmo / delete / mo_final
589 cmo / status / brief
590 finish
591 """
592 
593  # Create a different Run file for each CPU
594  for i in range(1, ncpu + 1):
595  file_name = 'mesh_poly_CPU%d.lgi' % i
596  f = open(file_name, 'w')
597  #Name of parameter Input File
598  fparameter_name = 'parameters_CPU%d.mlgi' % i
599  fintersection_name = 'intersections_CPU%d.inp' % i
600  fpoly_name = 'poly_CPU%d.inp' % i
601  parameters = (fparameter_name, fpoly_name, fintersection_name, i)
602  f.write(lagrit_input % parameters)
603  f.flush()
604  f.close()
605  print('--> Writing LaGriT Control Files: Complete')
606 
607 
609  """ Create user_function.lgi files for meshing
610 
611  Parameters
612  ----------
613  None
614 
615  Returns
616  -------
617  None
618 
619  Notes
620  -----
621  These functions are called within LaGriT. It controls the mesh resolution using slope and refine_dist
622 
623  """
624 
625  # user_function.lgi useing PARAM_A and PARAM_B for slope and intercept
626  lagrit_input = """
627 cmo/DELATT/mo_pts/dfield
628 compute / distance_field / mo_pts / mo_line_work / dfield
629 math/multiply/mo_pts/x_four/1,0,0/mo_pts/dfield/PARAM_A/
630 math/add/mo_pts/x_four/1,0,0/mo_pts/x_four/PARAM_B/
631 cmo/copyatt/mo_pts/mo_pts/fac_n/x_four
632 finish
633 """
634  f = open('user_function.lgi', 'w')
635  f.write(lagrit_input)
636  f.close()
637 
638  # user_function2.lgi uses PARAM_A2 and PARAM_B2 for slope and intercept
639  lagrit_input = """
640 cmo/DELATT/mo_pts/dfield
641 compute / distance_field / mo_pts / mo_line_work / dfield
642 math/multiply/mo_pts/x_four/1,0,0/mo_pts/dfield/PARAM_A2/
643 math/add/mo_pts/x_four/1,0,0/mo_pts/x_four/PARAM_B2/
644 cmo/copyatt/mo_pts/mo_pts/fac_n/x_four
645 finish
646 """
647  f = open('user_function2.lgi', 'w')
648  f.write(lagrit_input)
649  f.close()
650 
651 
652 def create_merge_poly_files(ncpu, num_poly, fracture_list, h, visual_mode,
653  domain, flow_solver):
654  """ Creates a LaGriT script that reads in each fracture mesh, appends it to the main mesh, and then deletes that mesh object. Then duplicate points are removed from the main mesh using EPS_FILTER. The points are compressed, and then written to file.
655 
656  Parameters
657  ----------
658  ncpu : int
659  Number of Processors used for meshing
660  fracture_list : list of int
661  List of fracture numbers in the DFN
662  h : float
663  Meshing length scale
664  visual_mode : bool
665  If True, reduced_mesh.inp will be output. If False, full_mesh.inp is output
666  domain : dict
667  Dictionary of x,y,z domain size
668  flow_solver : string
669  Name of target flow solver (Changes output files)
670 
671  Returns
672  -------
673  n_jobs : int
674  number of merge jobs
675 
676  Notes
677  -----
678  1. Fracture mesh objects are read into different part_*.lg files. This allows for merging of the mesh to be performed in batches.
679  """
680 
681  print("--> Writing : merge_poly.lgi")
682  part_size = int(num_poly / ncpu) + 1
683  endis = []
684  ii = 0
685  for i in fracture_list[:-1]:
686  ii += 1
687  if ii == part_size:
688  endis.append(i)
689  ii = 0
690  endis.append(fracture_list[-1])
691  n_jobs = len(endis)
692 
693  lagrit_input = """
694 # Change to read LaGriT
695 read / lagrit / %s / mo_%d / binary
696 cmo / move / mo_%d / mo_final
697 define / MO_NAME_FRAC / mo_%d
698 """
699  if not visual_mode:
700  lagrit_input += """
701 cmo / addatt / MO_NAME_FRAC / volume / evol_one
702 math / sum / MO_NAME_FRAC / evol_sum / 1 0 0 / MO_NAME_FRAC / evol_one
703 """
704  lagrit_input += """
705 addmesh / merge / cmo_tmp / cmo_tmp / mo_%d
706 cmo / delete / mo_%d
707 """
708  lagrit_input_2 = '#Writing out merged fractures\n'
709  if not visual_mode:
710  lagrit_input_2 += """
711 mo / addatt/ cmo_tmp / volume / evol_all
712 math / sum / cmo_tmp / evol_sum / 1 0 0 / cmo_tmp / evol_all """
713  lagrit_input_2 += """
714 cmo select cmo_tmp
715 dump lagrit part%d.lg cmo_tmp
716 finish \n
717 """
718 
719  j = 0 # Counter for cpus
720  fout = 'merge_poly_part_1.lgi'
721  f = open(fout, 'w')
722  for i in fracture_list:
723  tmp = 'mesh_' + str(i) + '.lg'
724  f.write(lagrit_input % (tmp, i, i, i, i, i))
725  # if i is the last fracture in the cpu set
726  # move to the next cpu set
727  if i == endis[j]:
728  f.write(lagrit_input_2 % (j + 1))
729  f.flush()
730  f.close()
731  j += 1
732  fout = 'merge_poly_part_' + str(j + 1) + '.lgi'
733  f = open(fout, 'w')
734 
735  f.flush()
736  f.close()
737  os.remove(fout)
738 
739 
740 
741  lagrit_input = """
742 read / lagrit / part%d.lg / junk / binary
743 addmesh / merge / mo_all / mo_all / cmo_tmp
744 cmo / delete / cmo_tmp
745  """
746  f = open('merge_rmpts.lgi', 'w')
747  for j in range(1, n_jobs + 1):
748  f.write(lagrit_input % (j))
749 
750  # Append meshes complete
751  if not visual_mode:
752  lagrit_input = """
753 # Appending the meshes complete
754 # LaGriT Code to remove duplicates and output the mesh
755 cmo / select / mo_all
756 #recon 1
757 define / EPS / %e
758 define / EPS_FILTER / %e
759 pset / pinter / attribute / dfield / 1,0,0 / lt / EPS
760 #cmo / addatt / mo_all / inter / vint / scalar / nnodes
761 #cmo / setatt / mo_all / inter / 1 0 0 / 0
762 #cmo / setatt / mo_all / inter / pset, get, pinter / 1
763 
764 filterkd / pset get pinter / EPS_FILTER / nocheck
765 pset / pinter / delete
766 
767 rmpoint / compress
768 # SORT can affect a_b attribute
769 sort / mo_all / index / ascending / ikey / imt xic yic zic
770 reorder / mo_all / ikey
771 cmo / DELATT / mo_all / ikey
772 """ % (h * 10**-5, h * 10**-3)
773  lagrit_input += """
774 resetpts / itp
775 boundary_components
776 #dump / full_mesh.gmv / mo_all
777 dump / full_mesh.inp / mo_all
778 dump / lagrit / full_mesh.lg / mo_all
779 """
780  if flow_solver == "PFLOTRAN":
781  print("\nDumping output for %s" % flow_solver)
782  lagrit_input += """
783 dump / pflotran / full_mesh / mo_all / nofilter_zero
784 dump / stor / full_mesh / mo_all / ascii
785  """
786  elif flow_solver == "FEHM":
787  print("\nDumping output for %s" % flow_solver)
788  lagrit_input += """
789 dump / stor / full_mesh / mo_all / ascii
790 dump / coord / full_mesh / mo_all
791 # matid start at 1, but we need them to start at 7 for FEHM due to zone files
792 # So we do a little addition
793 math / add / mo_all / imt1 / 1,0,0 / mo_all / imt1 / 6
794 dump / zone_imt / full_mesh / mo_all
795 # and then we subtract 6 back
796 math / subtract / mo_all / imt1 / 1,0,0 / mo_all / imt1 / 6
797 """
798  else:
799  print("WARNING!!!!!!!\nUnkown flow solver selection: %s" %
800  flow_solver)
801  lagrit_input += """
802 # Dump out Material ID Dat file
803 cmo / modatt / mo_all / isn / ioflag / l
804 cmo / modatt / mo_all / x_four / ioflag / l
805 cmo / modatt / mo_all / fac_n / ioflag / l
806 cmo / modatt / mo_all / dfield / ioflag / l
807 cmo / modatt / mo_all / rf_field / ioflag / l
808 cmo / modatt / mo_all / a_b / ioflag / l
809 cmo / modatt / mo_all / b_a / ioflag / l
810 cmo / modatt / mo_all / xnorm / ioflag / l
811 cmo / modatt / mo_all / ynorm / ioflag / l
812 cmo / modatt / mo_all / znorm / ioflag / l
813 cmo / modatt / mo_all / evol_one / ioflag / l
814 cmo / modatt / mo_all / evol_all / ioflag / l
815 cmo / modatt / mo_all / numbnd / ioflag / l
816 cmo / modatt / mo_all / id_numb / ioflag / l
817 cmo / modatt / mo_all / evol_all / ioflag / l
818 cmo / modatt / mo_all / itp / ioflag / l
819 cmo / modatt / mo_all / icr / ioflag / l
820 cmo / modatt / mo_all / meshid / ioflag / l
821 cmo / modatt / mo_all / id_n_1 / ioflag / l
822 cmo / modatt / mo_all / id_n_2 / ioflag / l
823 cmo / modatt / mo_all / pt_gtg / ioflag / l
824 cmo / modatt / mo_all / pt_gtg / ioflag / l
825 # Dump out Material ID Dat file
826 dump / avs2 / materialid.dat / mo_all / 0 0 2 0
827 
828 cmo / modatt / mo_all / imt1 / ioflag / l
829 cmo / modatt / mo_all / family_id / ioflag / l
830 cmo / modatt / mo_all / evol_onen / ioflag / l
831 # Dump mesh with no attributes for viz
832 dump / full_mesh_viz.inp / mo_all
833 
834 # Dump out zone files
835 define / XMAX / %e
836 define / XMIN / %e
837 define / YMAX / %e
838 define / YMIN / %e
839 define / ZMAX / %e
840 define / ZMIN / %e
841 
842 define / ZONE / 1
843 define / FOUT / boundary_top
844 pset / top / attribute / zic / 1,0,0/ gt / ZMAX
845 pset / top / zone / FOUT/ ascii / ZONE
846 
847 define / ZONE / 2
848 define / FOUT / boundary_bottom
849 pset / bottom / attribute / zic / 1,0,0/ lt / ZMIN
850 pset / bottom / zone / FOUT/ ascii / ZONE
851 
852 define / ZONE / 3
853 define / FOUT / boundary_left_w
854 pset / left_w / attribute/ xic/ 1,0,0 /lt / XMIN
855 pset / left_w / zone / FOUT/ ascii / ZONE
856 
857 define / ZONE / 4
858 define / FOUT / boundary_front_n
859 pset / front_n / attribute/ yic / 1,0,0 / gt / YMAX
860 pset / front_n / zone / FOUT/ ascii / ZONE
861 
862 define / ZONE / 5
863 define / FOUT / boundary_right_e
864 pset / right_e / attribute/ xic / 1,0,0/ gt / XMAX
865 pset / right_e / zone / FOUT/ ascii / ZONE
866 
867 define / ZONE / 6
868 define / FOUT / boundary_back_s
869 pset / back_s / attribute/ yic/ 1,0,0 / lt / YMIN
870 pset / back_s / zone / FOUT/ ascii / ZONE
871 
872 """
873  eps = h * 10**-3
874  parameters = (0.5*domain['x'] - eps, -0.5*domain['x'] + eps, \
875  0.5*domain['y'] - eps, -0.5*domain['y'] + eps, \
876  0.5*domain['z'] - eps, -0.5*domain['z'] + eps)
877 
878  lagrit_input = lagrit_input % parameters
879 
880  else:
881  lagrit_input = """
882 cmo / modatt / mo_all / icr1 / ioflag / l
883 cmo / modatt / mo_all / isn1 / ioflag / l
884 cmo / modatt / mo_all / itp1 / ioflag / l
885 #dump / reduced_mesh.gmv / mo_all
886 dump / reduced_mesh.inp / mo_all
887 """
888  lagrit_input += """
889 quality
890 finish
891 """
892  f.write(lagrit_input)
893  f.flush()
894  f.close()
895 
896  return n_jobs
897 
898 
900  """Processes zone files for particle tracking. All zone files are combined into allboundaries.zone
901 
902  Parameters
903  ----------
904  None
905 
906  Returns
907  -------
908  None
909 
910  Notes
911  -----
912  None
913  """
914 
915  fall = open("allboundaries.zone", "w")
916  #copy all but last 2 lines of boundary_top.zone in allboundaries.zone
917  fzone = open("boundary_top.zone", "r")
918  lines = fzone.readlines()
919  lines = lines[:-2]
920  fzone.close()
921  fall.writelines(lines)
922  #copy all but frist and last 2 lines of boundary_bottom.zone in allboundaries.zone
923  files = ['bottom', 'left_w', 'front_n', 'right_e']
924  for f in files:
925  fzone = open("boundary_%s.zone" % f, "r")
926  lines = fzone.readlines()
927  lines = lines[1:-2]
928  fzone.close()
929  fall.writelines(lines)
930  fzone = open("boundary_back_s.zone", "r")
931  lines = fzone.readlines()
932  lines = lines[1:]
933  fzone.close()
934  fall.writelines(lines)
935  fall.close()
936  # copies boundary zone files for PFLOTRAN
937  # This can be deleted once we clean up the flow
938  move('boundary_bottom.zone', 'pboundary_bottom.zone')
939  move('boundary_left_w.zone', 'pboundary_left_w.zone')
940  move('boundary_front_n.zone', 'pboundary_front_n.zone')
941  move('boundary_right_e.zone', 'pboundary_right_e.zone')
942  move('boundary_back_s.zone', 'pboundary_back_s.zone')
943  move('boundary_top.zone', 'pboundary_top.zone')
944 
945 
def create_merge_poly_files(ncpu, num_poly, fracture_list, h, visual_mode, domain, flow_solver)
def create_parameter_mlgi_file(fracture_list, h, slope=2.0, refine_dist=0.5)
def create_lagrit_scripts(visual_mode, ncpu, refine_factor=1, production_mode=True)
def edit_intersection_files(num_poly, fracture_list, path)