5 from pydfnworks
import *
10 """ Identifies nodes in a DFN for nodes the intersect a well with radius r [m]\n
11 1. Well coordinates in well["filename"] are converted to a polyline that are written into "well_{well['name']}_line.inp"\n
12 2. Well is expanded to a volume with radius well["r"] and written into the avs file well_{well["name"]}_volume.inp\n
13 3. Nodes in the DFN that intersect with the well are written into the zone file well_{well["name"]}.zone\n
14 4. If using PFLOTRAN, then an ex file is created from the well zone file\n
21 Dictionary of information about the well that contains the following attributes
26 well["filename"] : string
27 filename of the well coordinates with the following format
40 Wells can be a list of well dictionaries
44 if type(wells)
is dict:
47 f
"\n\n--> Identifying nodes in the DFN intersecting with a vertical well named {well['name']}."
51 if not os.path.isfile(f
"well_{well['name']}_line.inp"):
61 if self.flow_solver ==
"PFLOTRAN":
62 self.zone2ex(zone_file=f
"well_{well['name']}.zone", face=
'well')
64 if self.flow_solver ==
"FEHM":
65 print(f
"--> Well nodes are in well_{well['name']}.zone")
67 print(f
"--> Well creation for {well['name']} complete\n\n")
69 if type(wells)
is list:
72 f
"\n\n--> Identifying nodes in the DFN intersecting with a vertical well named {well['name']}."
76 if not os.path.isfile(f
"well_{well['name']}_line.inp"):
86 if self.flow_solver ==
"PFLOTRAN":
87 self.zone2ex(zone_file=f
"well_{well['name']}.zone",
90 if self.flow_solver ==
"FEHM":
91 print(f
"--> Well nodes are in well_{well['name']}.zone")
93 print(f
"--> Well creation for {well['name']} complete\n\n")
97 """ Identifies converts well coordinates into a polyline avs file. Distance between
98 point on the polyline are h/2 apart. Polyline is written into "well_{well['name']}_line.inp"
102 well: dictionary of information about the well. Contains the following:
104 well["name"] : string
107 well["filename"] : string
108 filename of the well coordinates. "well_coords.dat" for example.
118 h parameter for meshing.
126 If flow solver is set to PFLOTRAN, the zone file dumped by LaGriT will be converted to
130 print(
"--> Interpolating well coordinates into a polyline")
134 _, h, _, _, _ = parse_params_file(quiet=
True)
137 pts = np.genfromtxt(f
"{well['filename']}")
142 new_pts.append(pts[0])
145 for i
in range(1, n):
146 distance = np.linalg.norm(pts[i, :] - pts[i - 1, :])
148 new_pts.append(pts[i, :])
152 m = int(np.ceil(distance / h))
153 dx = (pts[i, 0] - pts[i - 1, 0]) / m
154 dy = (pts[i, 1] - pts[i - 1, 1]) / m
155 dz = (pts[i, 2] - pts[i - 1, 2]) / m
158 interp[0] = new_pts[new_idx][0] + dx
159 interp[1] = new_pts[new_idx][1] + dy
160 interp[2] = new_pts[new_idx][2] + dz
161 new_pts.append(interp)
165 print(
"--> Interpolating well coordinates into a polyline: Complete")
167 avs_filename = f
"well_{well['name']}_line.inp"
168 print(f
"--> Writing polyline into avs file : {avs_filename}")
170 num_pts = new_idx + 1
171 pt_digits = len(str(num_pts))
174 elem_digits = len(str(num_elem))
176 favs = open(avs_filename,
"w")
177 favs.write(f
"{num_pts}\t{num_elem}\t0\t0\t0\n")
178 for i
in range(num_pts):
180 f
"{i+1:0{pt_digits}d} {new_pts[i][0]:12e} {new_pts[i][1]:12e} {new_pts[i][2]:12e}\n"
182 for i
in range(num_elem):
183 favs.write(f
"{i+1} 1 line {i+1} {i+2}\n")
185 print(f
"--> Writing polyline into avs file : {avs_filename} : Complete")
189 """ Expands the polyline defining the well into a volume with radius r [m].
190 A sphere of points around each point is created and then connected.
191 Volume is written into the avs file well_{well["name"]}_volume.inp
196 dictionary of information about the well. Contains the following:
198 well["name"] : string
201 well["filename"] : string
202 filename of the well coordinates. "well_coords.dat" for example.
218 Mesh of the well is written into the avs file {well["name"][:-4]}.inp
222 print(
"--> Expanding well into a volume.")
228 angle_r = r / np.sqrt(2)
231 ## read in polyline of well
232 read / well_{well['name']}_line.inp / mo_line
233 cmo / printatt / mo_line / -xyz- / minmax
235 ## expand every point in the polyline into a discrete sphere
237 cmo / create / mo_well / / / tet
238 copypts / mo_well / mo_line
240 cmo / create / mo_tmp / / / line
241 copypts / mo_tmp / mo_line
242 cmo / select / mo_tmp
243 trans / 1 0 0 / 0. 0. 0. / {well["r"]} 0 0
244 copypts / mo_well / mo_tmp
245 cmo / delete / mo_tmp
247 cmo / create / mo_tmp / / / line
248 copypts / mo_tmp / mo_line
249 cmo / select / mo_tmp
250 trans / 1 0 0 / 0. 0. 0. / -{well["r"]} 0 0
251 copypts / mo_well / mo_tmp
252 cmo / delete / mo_tmp
254 cmo / create / mo_tmp / / / line
255 copypts / mo_tmp / mo_line
256 cmo / select / mo_tmp
257 trans / 1 0 0 / 0. 0. 0. / 0 {well["r"]} 0
258 copypts / mo_well / mo_tmp
259 cmo / delete / mo_tmp
261 cmo / create / mo_tmp / / / line
262 copypts / mo_tmp / mo_line
263 cmo / select / mo_tmp
264 trans / 1 0 0 / 0. 0. 0. / 0 -{well["r"]} 0
265 copypts / mo_well / mo_tmp
266 cmo / delete / mo_tmp
268 cmo / create / mo_tmp / / / line
269 copypts / mo_tmp / mo_line
270 cmo / select / mo_tmp
271 trans / 1 0 0 / 0. 0. 0. / 0 0 {well["r"]}
272 copypts / mo_well / mo_tmp
273 cmo / delete / mo_tmp
275 cmo / create / mo_tmp / / / line
276 copypts / mo_tmp / mo_line
277 cmo / select / mo_tmp
278 trans / 1 0 0 / 0. 0. 0. / 0 0 -{well["r"]}
279 copypts / mo_well / mo_tmp
280 cmo / delete / mo_tmp
282 cmo / create / mo_tmp / / / line
283 copypts / mo_tmp / mo_line
284 cmo / select / mo_tmp
285 trans / 1 0 0 / 0. 0. 0. / {angle_r} {angle_r} 0
286 copypts / mo_well / mo_tmp
287 cmo / delete / mo_tmp
289 cmo / create / mo_tmp / / / line
290 copypts / mo_tmp / mo_line
291 cmo / select / mo_tmp
292 trans / 1 0 0 / 0. 0. 0. / {angle_r} -{angle_r} 0
293 copypts / mo_well / mo_tmp
294 cmo / delete / mo_tmp
296 cmo / create / mo_tmp / / / line
297 copypts / mo_tmp / mo_line
298 cmo / select / mo_tmp
299 trans / 1 0 0 / 0. 0. 0. / -{angle_r} {angle_r} 0
300 copypts / mo_well / mo_tmp
301 cmo / delete / mo_tmp
303 cmo / create / mo_tmp / / / line
304 copypts / mo_tmp / mo_line
305 cmo / select / mo_tmp
306 trans / 1 0 0 / 0. 0. 0. / -{angle_r} -{angle_r} 0
307 copypts / mo_well / mo_tmp
308 cmo / delete / mo_tmp
310 cmo / create / mo_tmp / / / line
311 copypts / mo_tmp / mo_line
312 cmo / select / mo_tmp
313 trans / 1 0 0 / 0. 0. 0. / 0 {angle_r} {angle_r}
314 copypts / mo_well / mo_tmp
315 cmo / delete / mo_tmp
317 cmo / create / mo_tmp / / / line
318 copypts / mo_tmp / mo_line
319 cmo / select / mo_tmp
320 trans / 1 0 0 / 0. 0. 0. / 0 {angle_r} -{angle_r}
321 copypts / mo_well / mo_tmp
322 cmo / delete / mo_tmp
324 cmo / create / mo_tmp / / / line
325 copypts / mo_tmp / mo_line
326 cmo / select / mo_tmp
327 trans / 1 0 0 / 0. 0. 0. / 0 -{angle_r} {angle_r}
328 copypts / mo_well / mo_tmp
329 cmo / delete / mo_tmp
331 cmo / create / mo_tmp / / / line
332 copypts / mo_tmp / mo_line
333 cmo / select / mo_tmp
334 trans / 1 0 0 / 0. 0. 0. / 0 -{angle_r} -{angle_r}
335 copypts / mo_well / mo_tmp
336 cmo / delete / mo_tmp
338 cmo / create / mo_tmp / / / line
339 copypts / mo_tmp / mo_line
340 cmo / select / mo_tmp
341 trans / 1 0 0 / 0. 0. 0. / {angle_r} 0 {angle_r}
342 copypts / mo_well / mo_tmp
343 cmo / delete / mo_tmp
345 cmo / create / mo_tmp / / / line
346 copypts / mo_tmp / mo_line
347 cmo / select / mo_tmp
348 trans / 1 0 0 / 0. 0. 0. / {angle_r} 0 -{angle_r}
349 copypts / mo_well / mo_tmp
350 cmo / delete / mo_tmp
352 cmo / create / mo_tmp / / / line
353 copypts / mo_tmp / mo_line
354 cmo / select / mo_tmp
355 trans / 1 0 0 / 0. 0. 0. / -{angle_r} 0 {angle_r}
356 copypts / mo_well / mo_tmp
357 cmo / delete / mo_tmp
359 cmo / create / mo_tmp / / / line
360 copypts / mo_tmp / mo_line
361 cmo / select / mo_tmp
362 trans / 1 0 0 / 0. 0. 0. / -{angle_r} 0 -{angle_r}
363 copypts / mo_well / mo_tmp
364 cmo / delete / mo_tmp
366 ## Could add more permutations, but this looks good enough right now
369 ################## DEBUG ###########################
370 # dump / well_pts.inp / mo_well
371 ################## DEBUG ###########################
373 # filter out point that are too close
374 cmo / select / mo_well
375 filter / 1 0 0 / {0.1*r}
377 cmo / setatt / mo_well / imt / 1 0 0 / 1
379 # connect the point cloud and make a volume mesh
383 ################## DEBUG ###########################
384 # dump / well_{well["name"]}.inp / mo_well
385 ################## DEBUG ###########################
387 # add edge_max attribute and remove elements with big edges
388 quality / edge_max / y
389 eltset /big/ edgemax / gt / {np.sqrt(2)*r}
390 cmo / setatt / mo_well / itetclr / eltset, get, big / 2
394 dump / well_{well["name"]}_volume.inp / mo_well
396 ################## DEBUG ###########################
397 # # extract the surface of the well
398 # # This is done to remove internal points and reduce
399 # # the total number of elements in the mesh
400 # # This speeds up the intersection checking later on
401 # # I couldn't get this to work in a robust way.
402 # # There were some weird LaGriT errors if I deleted
404 # # Works if we stop before this, but I'm leaving it to
405 # # revisit if need be.
408 # extract / surfmesh / 1,0,0 /mo_shell / mo_well
409 # cmo / select / mo_shell
410 # cmo / delete / mo_well
412 # ################## DEBUG ###########################
413 # dump / well_{well["name"]}_shell.inp / mo_shell
414 # ################## DEBUG ###########################
416 # # Copy the surface of the well into a tet mesh
417 # cmo / create / mo_well2 / / / tet
418 # copypts / mo_well2 / mo_shell
419 # cmo / select / mo_well2
420 # # cmo / delete / mo_shell
422 # # filter out point that are too close
423 # filter / 1 0 0 / {0.1*r}
425 # cmo / setatt / mo_well2 / imt / 1 0 0 / 1
427 # # connect the point cloud and make a volume mesh
431 # # add edge_max attribute and remove elements with big edges
432 # quality / edge_max / y
433 # eltset /big/ edgemax / gt / {np.sqrt(2)*r}
434 # cmo / setatt / mo_well2 / itetclr / eltset, get, big / 2
438 # # write out final well mesh
439 # dump / well_{well["name"]}_volume.inp / mo_well2
445 with open(f
"expand_well_{well['name']}.lgi",
"w")
as fp:
446 fp.write(lagrit_script)
450 mh.run_lagrit_script(f
"expand_well_{well['name']}.lgi",
451 output_file=f
"expand_well_{well['name']}.out",
454 print(
"--> Expanding well complete.")
458 """Identifies nodes in a DFN for nodes the intersect a well with radius r [m]
459 First, all elements that intersect the well are identified.
460 Second, all nodes of those elements are tagged.
461 Third, that collection of nodes are dumped as a zone file (well_{well["name"]}.zone)
468 dictionary of information about the well. Contains the following:
470 well["name"] : string
473 well["filename"] : string
474 filename of the well coordinates. "well_coords.dat" for example.
502 # read in well volume
503 read / well_{well["name"]}_volume.inp / mo_well
506 read / {inp_file} / mo_dfn
508 # find intersecting cells
509 cmo / select / mo_dfn
510 intersect_elements / mo_dfn / mo_well / well_{well["name"]}_inter
512 eltset / ewell / well_{well["name"]}_inter / gt / 0
514 # dump dfn mesh with intersections tagged
515 #dump / avs / {inp_file[:-3]}_tagged.inp / mo_dfn
517 # gather nodes of intersecting cells
518 pset / well_{well["name"]} / eltset / ewell
520 # dump nodes from intersecting cells
521 pset / well_{well["name"]} / zone / well_{well["name"]}.zone
527 with open(f
"get_well_{well['name']}_zone.lgi",
"w")
as fp:
528 fp.write(lagrit_script)
532 mh.run_lagrit_script(f
"get_well_{well['name']}_zone.lgi",
533 output_file=f
"create_well_{well['name']}.out",
536 with open(f
"well_{well['name']}.zone",
"r")
as fp:
537 number_of_nodes = int(fp.readlines()[3])
538 if number_of_nodes > 0:
539 print(f
"--> There are {number_of_nodes} nodes in the well zone")
541 print(
"--> WARNING!!! The well did not intersect the DFN!!!")
545 """ Identifies points on a DFN where the well intersects the network.
546 These points are used in meshing the network to have higher resolution in the mesh in these points.
547 Calls a sub-routine run_find_well_intersection_points.
554 dictionary of information about the well. Contains the following:
556 well["name"] : string
559 well["filename"] : string
560 filename of the well coordinates. "well_coords.dat" for example.
576 Wells can be a list of well dictionaries.
577 Calls the subroutine run_find_well_intersection_points to remove redundant code.
581 print(
"--> Checking for reduced_mesh.inp")
582 if not os.path.isfile(
"reduced_mesh.inp"):
583 print(
"--> reduced_mesh.inp not found. Creating it now.")
584 self.mesh_network(visual_mode=
True)
586 print(
"--> reduced_mesh.inp found. Moving on.")
589 if type(wells)
is dict:
592 elif type(wells)
is list:
601 """ Runs the workflow for finding the point of intersection of the DFN with the well.
606 dictionary of information about the well. Contains the following:
608 well["name"] : string
611 well["filename"] : string
612 filename of the well coordinates. "well_coords.dat" for example.
622 Minimum h length scale in the network
630 This function was designed to minimize redundancy in the workflow. It's called
631 within find_well_intersection_points()
634 print(f
"\n\n--> Working on well {well['name']}")
637 if not os.path.isfile(f
"well_{well['name']}_line.inp"):
647 """ LaGriT script to identify the points of intersection between the DFN and the well.
652 dictionary of information about the well. Contains the following:
654 well["name"] : string
657 well["filename"] : string
658 filename of the well coordinates. "well_coords.dat" for example.
674 points of intersection are written into the avs file well_{well['name']}_intersect.inp
676 OUTPUT: well_segments_intersect.inp is a subset of the well line segments that intersect fractures.
677 The segments are tagged so itetclr and imt are set to the value of the fracture they intersect.
682 # OUTPUT: intersected_fracture.list tells you the list of fractures intersected by the well.
683 # OUTPUT: well_segments_intersect.inp is a subset of the well line segments that intersect fractures.
684 # The segments are tagged so itetclr and imt are set to the value of the fracture they intersect.
686 define / INPUT_DFN / reduced_mesh.inp
687 define / INPUT_WELL / well_{well['name']}_line.inp
688 define / OUTPUT_WELL_SEGMENTS / well_{well['name']}_intersect.inp
689 # define / OUTPUT_FRACTURE_LIST / {well['name']}_fracture.list
691 read / avs / INPUT_DFN / mo_tri
692 read / avs / INPUT_WELL / mo_line
694 # Find the triangles of the DFN mesh that intersect the well lines.
695 # Get rid of all the non-intersecting triangles.
697 intersect_elements / mo_tri / mo_line / if_intersect
698 eltset / e_not_intersect / if_intersect / eq / 0
699 rmpoint / element / eltset get e_not_intersect
701 cmo / DELATT / mo_tri / if_intersect
703 # dump / avs / reduced_reduced_mesh.inp / mo_tri
704 cmo / addatt / mo_tri / id_fracture / vint / scalar / nelements
705 cmo / copyatt / mo_tri / mo_tri / id_fracture / itetclr
706 # dump / avs / OUTPUT_FRACTURE_LIST / mo_tri / 0 0 0 1
708 # Find the segments of the well (line object) that intersect the fracture planes (triangles)
710 intersect_elements / mo_line / mo_tri / if_intersect
711 eltset / e_not_intersect / if_intersect / eq / 0
712 rmpoint / element / eltset get e_not_intersect
714 cmo / DELATT / mo_line / if_intersect
716 # dump / avs / OUTPUT_WELL_SEGMENTS / mo_line
719 # Reduce the size of the triangles so interpolation works.
721 cmo / select / mo_tri
724 intersect_elements / mo_tri / mo_line / if_intersect
725 eltset / e_not_intersect / if_intersect / eq / 0
726 rmpoint / element / eltset get e_not_intersect
728 cmo / DELATT / mo_tri / if_intersect
731 intersect_elements / mo_tri / mo_line / if_intersect
732 eltset / e_not_intersect / if_intersect / eq / 0
733 rmpoint / element / eltset get e_not_intersect
735 cmo / DELATT / mo_tri / if_intersect
738 intersect_elements / mo_tri / mo_line / if_intersect
739 eltset / e_not_intersect / if_intersect / eq / 0
740 rmpoint / element / eltset get e_not_intersect
742 cmo / DELATT / mo_tri / if_intersect
745 intersect_elements / mo_tri / mo_line / if_intersect
746 eltset / e_not_intersect / if_intersect / eq / 0
747 rmpoint / element / eltset get e_not_intersect
749 cmo / DELATT / mo_tri / if_intersect
752 intersect_elements / mo_tri / mo_line / if_intersect
753 eltset / e_not_intersect / if_intersect / eq / 0
754 rmpoint / element / eltset get e_not_intersect
756 cmo / DELATT / mo_tri / if_intersect
759 intersect_elements / mo_tri / mo_line / if_intersect
760 eltset / e_not_intersect / if_intersect / eq / 0
761 rmpoint / element / eltset get e_not_intersect
763 cmo / DELATT / mo_tri / if_intersect
766 intersect_elements / mo_tri / mo_line / if_intersect
767 eltset / e_not_intersect / if_intersect / eq / 0
768 rmpoint / element / eltset get e_not_intersect
770 cmo / DELATT / mo_tri / if_intersect
773 # dump / avs / tmp_refine.inp / mo_tri
776 interpolate / voronoi / mo_line itetclr / 1 0 0 / mo_tri imt
777 interpolate / voronoi / mo_line imt / 1 0 0 / mo_tri imt
779 cmo / modatt / mo_line / itp / ioflag / l
780 cmo / modatt / mo_line / icr / ioflag / l
781 cmo / modatt / mo_line / isn / ioflag / l
783 dump / avs / OUTPUT_WELL_SEGMENTS / mo_line
790 with open(f
"find_well_{well['name']}_segment.lgi",
"w")
as fp:
791 fp.write(lagrit_script)
795 mh.run_lagrit_script(f
"find_well_{well['name']}_segment.lgi",
796 output_file=f
"find_well_{well['name']}_segment.out",
801 """ Takes the well points found using find_segments and projects the points onto the fracture plane. These points are written into well_points.dat file. During meshing, these points are read in and a higher resolution mesh is created near by them. well_points.dat has the format
806 for every intersection point.
811 dictionary of information about the well. Contains the following:
813 well["name"] : string
816 well["filename"] : string
817 filename of the well coordinates. "well_coords.dat" for example.
836 print(f
"--> Finding well points on DFN for {well['name']}")
838 if not os.path.isfile(
"well_points.dat"):
839 fwell = open(
"well_points.dat",
"w")
840 fwell.write(
"fracture_id x y z\n")
842 fwell = open(
"well_points.dat",
"a")
844 well_line_file = f
"well_{well['name']}_intersect.inp"
846 pts, elems, fracture_list =
get_segments(well_line_file)
848 if len(fracture_list) == 0:
850 f
"\n--> WARNING!!! The well {well['name']} did not intersect the DFN!!!\n"
855 l0[0] = pts[elem[
"pt1"] - 1][
"x"]
856 l0[1] = pts[elem[
"pt1"] - 1][
"y"]
857 l0[2] = pts[elem[
"pt1"] - 1][
"z"]
859 l1[0] = pts[elem[
"pt2"] - 1][
"x"]
860 l1[1] = pts[elem[
"pt2"] - 1][
"y"]
861 l1[2] = pts[elem[
"pt2"] - 1][
"z"]
871 d = np.dot((p0 - l0), n) / (np.dot(l, n))
874 fwell.write(f
"{f} {v[0]} {v[1]} {v[2]}\n")
879 """ Sometimes multiple points of intersection are identified on the same fracture. This can occur if the discretized well has points close to the fracture plane. This function walks through well_points.dat and removes duplicate points that are within h of one another and on the same fracture plane.
885 Minimum length scale in the network.
896 print(
"\n--> Cross Checking well points")
897 pts = np.genfromtxt(
"well_points.dat", skip_header=1)
898 num_pts, _ = np.shape(pts)
904 for i
in range(num_pts):
905 fracture_number = pts[i, 0]
906 for j
in range(i + 1, num_pts):
908 if fracture_number == pts[j, 0]:
909 dist = abs(pts[i, 1] - pts[j, 1]) + abs(
910 pts[i, 2] - pts[j, 2]) + abs(pts[i, 3] - pts[j, 3])
916 keep_pt_indes = list(set(range(num_pts)) - set(remove_idx))
918 pts = pts[keep_pt_indes]
922 with open(
"well_points.dat",
"w")
as fwell:
923 fwell.write(
"fracture_id x y z\n")
924 for i
in range(num_pts):
925 fwell.write(f
"{int(pts[i,0])} {pts[i,1]} {pts[i,2]} {pts[i,3]}\n")
926 print(
"--> Cross Checking Complete")
930 """ Parses well_line_file (avs) to get point information, element information, and list of fractures that intersect the well.
934 well_line_file : string
935 filename of well_line_file written by find_segments()
940 list of dictionaries of intersection points. dictionary contains fracture id and x,y,z coordinates
941 elems: list of dictionaries
942 Information about elements of the discretized well that intersect the DFN
944 list of fractures that the well intersects
951 with open(well_line_file,
"r")
as fp:
952 header = fp.readline().split()
953 num_pts = int(header[0])
954 num_elem = int(header[1])
956 for i
in range(num_pts):
957 pt = fp.readline().split()
958 tmp = {
"id":
None,
"x":
None,
"y":
None,
"z":
None}
959 tmp[
"id"] = int(pt[0])
960 tmp[
"x"] = float(pt[1])
961 tmp[
"y"] = float(pt[2])
962 tmp[
"z"] = float(pt[3])
965 for i
in range(num_elem):
966 elem = fp.readline().split()
967 tmp = {
"pt1":
None,
"pt2":
None,
"frac":
None}
968 tmp[
"pt1"] = int(elem[3])
969 tmp[
"pt2"] = int(elem[4])
970 tmp[
"frac"] = int(elem[1])
974 for i
in range(num_elem):
975 if not elems[i][
"frac"]
in fracture_list:
976 fracture_list.append(elems[i][
"frac"])
978 return pts, elems, fracture_list
982 """ Returns Normal vector of a fracture
992 normal vector of a fracture
999 normals = np.genfromtxt(
"normal_vectors.dat")
1000 return normals[fracture_id - 1, :]
1004 """ Returns center of a fracture
1013 points : numpy array
1014 x,y,z coordinates of a fracture
1020 with open(
'translations.dat')
as old, open(
'points.dat',
'w')
as new:
1025 points = np.genfromtxt(
'points.dat', skip_header=0, delimiter=
' ')
1026 return points[fracture_id - 1, :]
1030 """ Create a Rotation matrix to transform normal vector A to normal vector B
1034 normalA : numpy array
1036 normalB : numpy array
1050 comparison = normalA == normalB
1051 equal_arrays = comparison.all()
1068 xProd = np.cross(normalA, normalB)
1069 sin = np.sqrt(xProd[0] * xProd[0] + xProd[1] * xProd[1] +
1070 xProd[2] * xProd[2])
1071 cos = np.dot(normalA, normalB)
1074 0, -xProd[2], xProd[1], xProd[2], 0, -xProd[0], -xProd[1],
1077 scalar = (1.0 - cos) / (sin * sin)
1078 vSquared = np.zeros(9)
1079 vSquared[0] = (v[0] * v[0] + v[1] * v[3] + v[2] * v[6]) * scalar
1080 vSquared[1] = (v[0] * v[1] + v[1] * v[4] + v[2] * v[7]) * scalar
1081 vSquared[2] = (v[0] * v[2] + v[1] * v[5] + v[2] * v[8]) * scalar
1082 vSquared[3] = (v[3] * v[0] + v[4] * v[3] + v[5] * v[6]) * scalar
1083 vSquared[4] = (v[3] * v[1] + v[4] * v[4] + v[5] * v[7]) * scalar
1084 vSquared[5] = (v[3] * v[2] + v[4] * v[5] + v[5] * v[8]) * scalar
1085 vSquared[6] = (v[6] * v[0] + v[7] * v[3] + v[8] * v[6]) * scalar
1086 vSquared[7] = (v[6] * v[1] + v[7] * v[4] + v[8] * v[7]) * scalar
1087 vSquared[8] = (v[6] * v[2] + v[7] * v[5] + v[8] * v[8]) * scalar
1089 R[0] = 1 + v[0] + vSquared[0]
1090 R[1] = 0 + v[1] + vSquared[1]
1091 R[2] = 0 + v[2] + vSquared[2]
1092 R[3] = 0 + v[3] + vSquared[3]
1093 R[4] = 1 + v[4] + vSquared[4]
1094 R[5] = 0 + v[5] + vSquared[5]
1095 R[6] = 0 + v[6] + vSquared[6]
1096 R[7] = 0 + v[7] + vSquared[7]
1097 R[8] = 1 + v[8] + vSquared[8]
1103 """ Apply Rotation matrix R to the point p
1114 The point p with the rotation matrix applied
1121 v[0] = p[0] * R[0] + p[1] * R[1] + p[2] * R[2]
1122 v[1] = p[0] * R[3] + p[1] * R[4] + p[2] * R[5]
1123 v[2] = p[0] * R[6] + p[1] * R[7] + p[2] * R[8]
1128 """ Moves working files created while making wells into well_data directory
1135 dictionary of information about the well. Contains the following:
1137 well["name"] : string
1140 well["filename"] : string
1141 filename of the well coordinates. "well_coords.dat" for example.
1157 Wells can be a list of well dictionaries
1160 if not os.path.isdir(
"well_data"):
1161 os.mkdir(
"well_data")
1163 files = [
"well_{0}_line.inp",
"expand_well_{0}.lgi", \
1164 "well_{0}_volume.inp",
"expand_well_{0}.out",\
1165 "get_well_{0}_zone.lgi",
"create_well_{0}.out",\
1166 "well_{0}_intersect.inp"]
1168 if type(wells)
is dict:
1171 shutil.move(file.format(well[
'name']),
1172 "well_data/" + file.format(well[
'name']))
1174 if type(wells)
is list:
1177 shutil.move(file.format(well[
'name']),
1178 "well_data/" + file.format(well[
'name']))
1182 """ Processes zone files for particle tracking. All zone files are combined into allboundaries.zone
1197 if type(wells)
is dict:
1198 os.symlink(f
"well_{well['name']}.zone",
"well_nodes.zone")
1200 if type(wells)
is list:
1201 number_of_wells = len(wells)
1202 fall = open(
"well_nodes.zone",
"w")
1203 for index, well
in enumerate(wells):
1205 print(f
"Working on well {well['name']}")
1206 fzone = open(f
"well_{well['name']}.zone",
"r")
1207 lines = fzone.readlines()
1209 fall.writelines(lines)
1210 if index > 0
and index < number_of_wells - 1:
1211 print(f
"Working on well {well['name']}")
1212 fzone = open(f
"well_{well['name']}.zone",
"r")
1213 lines = fzone.readlines()
1215 lines[0] = f
"{index+1:06d}\t\t{well['name']}\n"
1217 fall.writelines(lines)
1218 if index == number_of_wells - 1:
1219 print(f
"Working on well {well['name']}")
1220 fzone = open(f
"well_{well['name']}.zone",
"r")
1221 lines = fzone.readlines()
1223 lines[0] = f
"{index+1:06d}\t\t{well['name']}\n"
1225 fall.writelines(lines)
def well_point_of_intersection(well)
def rotation_matrix(normalA, normalB)
def get_center(fracture_id)
def get_segments(well_line_file)
def cleanup_wells(self, wells)
def get_normal(fracture_id)
def combine_well_boundary_zones(self, wells)
def find_well_intersection_points(self, wells)
def convert_well_to_polyline_avs(well, h=None)
def get_well_zone(well, inp_file)
def run_find_well_intersection_points(well, h)
def tag_well_in_mesh(self, wells)