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)