LoopStructural 1.0.1__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of LoopStructural might be problematic. Click here for more details.

Files changed (119) hide show
  1. Miniconda/envs/loop/Lib/site-packages/LoopStructural/__init__.py +33 -0
  2. Miniconda/envs/loop/Lib/site-packages/LoopStructural/__pycache__/__init__.cpython-37.pyc +0 -0
  3. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__init__.py +12 -0
  4. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/__init__.cpython-37.pyc +0 -0
  5. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/_base.cpython-37.pyc +0 -0
  6. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/_base.py +65 -0
  7. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudius.csv +21049 -0
  8. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudiusbb.txt +2 -0
  9. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplex.csv +126 -0
  10. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplexbb.txt +2 -0
  11. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusion.csv +1017 -0
  12. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusionbb.txt +2 -0
  13. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefoldbb.txt +2 -0
  14. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefolddata.csv +2226 -0
  15. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_bb.txt +2 -0
  16. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_fold.csv +2126 -0
  17. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__init__.py +31 -0
  18. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/__init__.cpython-37.pyc +0 -0
  19. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_fold_interpolator.cpython-37.pyc +0 -0
  20. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_interpolator.cpython-37.pyc +0 -0
  21. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/finite_difference_interpolator.cpython-37.pyc +0 -0
  22. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/geological_interpolator.cpython-37.pyc +0 -0
  23. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/operator.cpython-37.pyc +0 -0
  24. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/piecewiselinear_interpolator.cpython-37.pyc +0 -0
  25. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_grid.cpython-37.pyc +0 -0
  26. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_tetra.cpython-37.pyc +0 -0
  27. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/surfe_wrapper.cpython-37.pyc +0 -0
  28. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__init__.py +0 -0
  29. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__pycache__/__init__.cpython-37.pyc +0 -0
  30. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.c +27805 -0
  31. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.cp37-win_amd64.pyd +0 -0
  32. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_fold_interpolator.py +168 -0
  33. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_interpolator.py +551 -0
  34. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/finite_difference_interpolator.py +339 -0
  35. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/geological_interpolator.py +178 -0
  36. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/operator.py +46 -0
  37. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/piecewiselinear_interpolator.py +300 -0
  38. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_grid.py +460 -0
  39. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_tetra.py +637 -0
  40. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/surfe_wrapper.py +119 -0
  41. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__init__.py +46 -0
  42. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__pycache__/__init__.cpython-37.pyc +0 -0
  43. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__init__.py +0 -0
  44. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/__init__.cpython-37.pyc +0 -0
  45. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model.cpython-37.pyc +0 -0
  46. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/geological_model.py +1179 -0
  47. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__init__.py +3 -0
  48. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/__init__.cpython-37.pyc +0 -0
  49. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function.cpython-37.pyc +0 -0
  50. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function_feature.cpython-37.pyc +0 -0
  51. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_segment.cpython-37.pyc +0 -0
  52. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function.py +187 -0
  53. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function_feature.py +75 -0
  54. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_segment.py +270 -0
  55. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__init__.py +7 -0
  56. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/__init__.cpython-37.pyc +0 -0
  57. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/cross_product_geological_feature.cpython-37.pyc +0 -0
  58. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature.cpython-37.pyc +0 -0
  59. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature_builder.cpython-37.pyc +0 -0
  60. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/region_feature.cpython-37.pyc +0 -0
  61. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame.cpython-37.pyc +0 -0
  62. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame_builder.cpython-37.pyc +0 -0
  63. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/unconformity_feature.cpython-37.pyc +0 -0
  64. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/cross_product_geological_feature.py +77 -0
  65. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature.py +276 -0
  66. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature_builder.py +289 -0
  67. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/region_feature.py +31 -0
  68. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame.py +116 -0
  69. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame_builder.py +179 -0
  70. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/unconformity_feature.py +69 -0
  71. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__init__.py +8 -0
  72. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/__init__.cpython-37.pyc +0 -0
  73. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold.cpython-37.pyc +0 -0
  74. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle.cpython-37.pyc +0 -0
  75. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle_feature.cpython-37.pyc +0 -0
  76. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/foldframe.cpython-37.pyc +0 -0
  77. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/svariogram.cpython-37.pyc +0 -0
  78. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold.py +135 -0
  79. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle.py +132 -0
  80. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle_feature.py +57 -0
  81. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/foldframe.py +191 -0
  82. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/svariogram.py +179 -0
  83. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__init__.py +14 -0
  84. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/__init__.cpython-37.pyc +0 -0
  85. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/exceptions.cpython-37.pyc +0 -0
  86. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/helper.cpython-37.pyc +0 -0
  87. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/map2loop.cpython-37.pyc +0 -0
  88. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/utils.cpython-37.pyc +0 -0
  89. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/exceptions.py +9 -0
  90. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/helper.py +373 -0
  91. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/map2loop.py +229 -0
  92. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/utils.py +76 -0
  93. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__init__.py +19 -0
  94. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/__init__.cpython-37.pyc +0 -0
  95. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/map_viewer.cpython-37.pyc +0 -0
  96. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_plotter.cpython-37.pyc +0 -0
  97. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_visualisation.cpython-37.pyc +0 -0
  98. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/rotation_angle_plotter.cpython-37.pyc +0 -0
  99. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/sphinx_scraper.cpython-37.pyc +0 -0
  100. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/map_viewer.py +122 -0
  101. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_plotter.py +16 -0
  102. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_visualisation.py +704 -0
  103. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/rotation_angle_plotter.py +66 -0
  104. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/sphinx_scraper.py +34 -0
  105. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/PKG-INFO +10 -0
  106. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/SOURCES.txt +60 -0
  107. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/dependency_links.txt +1 -0
  108. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/requires.txt +3 -0
  109. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/top_level.txt +2 -0
  110. Miniconda/envs/loop/Lib/site-packages/tests/__init__.py +0 -0
  111. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/__init__.cpython-37.pyc +0 -0
  112. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_faults.cpython-37.pyc +0 -0
  113. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_fold.cpython-37.pyc +0 -0
  114. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_interpolator.cpython-37.pyc +0 -0
  115. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_refolded.cpython-37.pyc +0 -0
  116. Miniconda/envs/loop/Lib/site-packages/tests/test_faults.py +17 -0
  117. Miniconda/envs/loop/Lib/site-packages/tests/test_fold.py +57 -0
  118. Miniconda/envs/loop/Lib/site-packages/tests/test_interpolator.py +88 -0
  119. Miniconda/envs/loop/Lib/site-packages/tests/test_refolded.py +22 -0
@@ -0,0 +1,637 @@
1
+ import logging
2
+
3
+ import numpy as np
4
+ from LoopStructural.interpolators.cython.dsi_helper import cg
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ class TetMesh:
9
+ """
10
+
11
+ """
12
+ def __init__(self, origin = [0,0,0], nsteps = [10,10,10], step_vector = [1,1,1]):
13
+ self.origin = np.array(origin)
14
+ self.step_vector = np.array(step_vector)
15
+ self.nsteps = np.array(nsteps)
16
+ self.nsteps_cells = self.nsteps - 1
17
+ self.n_cell_x = self.nsteps[0] - 1
18
+ self.n_cell_y = self.nsteps[1] - 1
19
+ self.n_cell_z = self.nsteps[2] - 1
20
+ self.n_cells = self.n_cell_x * self.n_cell_y * self.n_cell_z
21
+ self.n_nodes = self.nsteps[0]*self.nsteps[1]*self.nsteps[2]
22
+
23
+ self.tetra_mask_even = np.array([
24
+ [7,1,2,4],
25
+ [6,2,4,7],
26
+ [5,1,4,7],
27
+ [0,1,2,4],
28
+ [3,1,2,7]
29
+ ])
30
+
31
+ self.tetra_mask = np.array([
32
+ [0,6,5,3],
33
+ [7,3,5,6],
34
+ [4,0,5,6],
35
+ [2,0,3,6],
36
+ [1,0,3,5]
37
+ ])
38
+ self.ntetra = self.n_cells * 5
39
+ self.properties = {}
40
+ self.property_gradients = {}
41
+ self.n_elements = self.ntetra
42
+ self.cg = None
43
+
44
+ @property
45
+ def nodes(self):
46
+ """
47
+ Gets the nodes of the mesh as a property rather than using a function, accessible as a property! Python magic!
48
+
49
+ Returns
50
+ -------
51
+ nodes : np.array((N,3))
52
+ Fortran ordered
53
+ """
54
+ max = self.origin + self.nsteps_cells * self.step_vector
55
+ x = np.linspace(self.origin[0], max[0], self.nsteps[0])
56
+ y = np.linspace(self.origin[1], max[1], self.nsteps[1])
57
+ z = np.linspace(self.origin[2], max[2], self.nsteps[2])
58
+ xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
59
+ return np.array([xx.flatten(order='F'), yy.flatten(order='F'),
60
+ zz.flatten(order='F')]).T
61
+
62
+ def barycentre(self, elements = None):
63
+ """
64
+ Return the barycentres of all tetrahedrons or of specified tetras using
65
+ global index
66
+
67
+ Parameters
68
+ ----------
69
+ elements - numpy array
70
+ global index
71
+
72
+ Returns
73
+ -------
74
+
75
+ """
76
+ if elements is None:
77
+ elements = np.arange(0,self.ntetra)
78
+ tetra = self.get_elements()[elements]
79
+ barycentre = np.sum(self.nodes[tetra][:, :, :],
80
+ axis=1) / 4.
81
+ return barycentre
82
+
83
+ def update_property(self, name, value):
84
+
85
+ self.properties[name] = value
86
+
87
+ def evaluate_value(self, pos, prop):
88
+ """
89
+ Evaluate value of interpolant
90
+
91
+ Parameters
92
+ ----------
93
+ pos - numpy array
94
+ locations
95
+ prop - string
96
+ property name
97
+
98
+ Returns
99
+ -------
100
+
101
+ """
102
+ values = np.zeros(pos.shape[0])
103
+ values[:] = np.nan
104
+ vertices, c, tetras, inside = self.get_tetra_for_location(pos)
105
+ values[inside] = np.sum(c[inside,:]*self.properties[prop][tetras[inside,:]],axis=1)
106
+ return values
107
+
108
+ def evaluate_gradient(self, pos, prop):
109
+ """
110
+ Evaluate the gradient of an interpolant at the locations
111
+
112
+ Parameters
113
+ ----------
114
+ pos - numpy array
115
+ locations
116
+ prop - string
117
+ property to evaluate
118
+
119
+
120
+ Returns
121
+ -------
122
+
123
+ """
124
+ values = np.zeros(pos.shape)
125
+ values[:] = np.nan
126
+ vertices, element_gradients, tetras, inside = self.get_tetra_gradient_for_location(pos)
127
+ vertex_vals = self.properties[prop][tetras]
128
+ #grads = np.zeros(tetras.shape)
129
+ values[inside,:] = (element_gradients[inside,:,:]*vertex_vals[inside, None, :]).sum(2)
130
+ length = np.sum(values[inside,:],axis=1)
131
+ values[inside,:] /= length[:,None]
132
+ return values
133
+
134
+ def get_tetra_for_location(self, pos):
135
+ """
136
+ Determine the tetrahedron from a numpy array of points
137
+
138
+ Parameters
139
+ ----------
140
+ pos : np.array
141
+
142
+
143
+
144
+ Returns
145
+ -------
146
+
147
+ """
148
+ pos = np.array(pos)
149
+ # initialise array for tetrahedron vertices
150
+ vertices = np.zeros((5, 4, pos.shape[0], 3))
151
+ vertices[:] = np.nan
152
+ # get cell indexes
153
+ c_xi, c_yi, c_zi = self.position_to_cell_index(pos)
154
+ # determine if using +ve or -ve mask
155
+ even_mask = (c_xi + c_yi + c_zi) % 2 == 0
156
+ # get cell corners
157
+ xi, yi, zi = self.cell_corner_indexes(c_xi, c_yi, c_zi) # global_index_to_node_index(gi)
158
+ # convert to node locations
159
+ nodes = self.node_indexes_to_position(xi, yi, zi).T
160
+
161
+ vertices[:, :, even_mask, :] = nodes[:, even_mask, :][self.tetra_mask_even, :, :]
162
+ vertices[:, :, ~even_mask, :] = nodes[:, ~even_mask, :][self.tetra_mask, :, :]
163
+ # changing order to points, tetra, nodes, coord
164
+ vertices = vertices.swapaxes(0, 2)
165
+ vertices = vertices.swapaxes(1, 2)
166
+ # use scalar triple product to calculate barycentric coords
167
+
168
+ vap = pos[:, None, :] - vertices[:, :, 0, :]
169
+ vbp = pos[:, None, :] - vertices[:, :, 1, :]
170
+ # # vcp = p - points[:, 2, :]
171
+ # # vdp = p - points[:, 3, :]
172
+ vab = vertices[:, :, 1, :] - vertices[:, :, 0, :]
173
+ vac = vertices[:, :, 2, :] - vertices[:, :, 0, :]
174
+ vad = vertices[:, :, 3, :] - vertices[:, :, 0, :]
175
+ vbc = vertices[:, :, 2, :] - vertices[:, :, 1, :]
176
+ vbd = vertices[:, :, 3, :] - vertices[:, :, 1, :]
177
+ va = np.einsum('ikj, ikj->ik', vbp, np.cross(vbd, vbc, axisa=2, axisb=2)) / 6.
178
+ vb = np.einsum('ikj, ikj->ik', vap, np.cross(vac, vad, axisa=2, axisb=2)) / 6.
179
+ vc = np.einsum('ikj, ikj->ik', vap, np.cross(vad, vab, axisa=2, axisb=2)) / 6.
180
+ vd = np.einsum('ikj, ikj->ik', vap, np.cross(vab, vac, axisa=2, axisb=2)) / 6.
181
+ v = np.einsum('ikj, ikj->ik', vab, np.cross(vac, vad, axisa=2, axisb=2)) / 6.
182
+ c = np.zeros((va.shape[0], va.shape[1], 4))
183
+ c[:, :, 0] = va / v
184
+ c[:, :, 1] = vb / v
185
+ c[:, :, 2] = vc / v
186
+ c[:, :, 3] = vd / v
187
+
188
+ # if all coords are +ve then point is inside cell
189
+ mask = np.all(c > 0, axis=2)
190
+
191
+ inside = np.any(mask,axis=1)
192
+ # get cell corners
193
+ xi, yi, zi = self.cell_corner_indexes(c_xi, c_yi, c_zi)
194
+
195
+ #create mask to see which cells are even
196
+ even_mask = (c_xi + c_yi + c_zi) % 2 == 0
197
+ # create global node index list
198
+ gi = xi + yi * self.nsteps[0] + zi * self.nsteps[0] * self.nsteps[1]
199
+
200
+ # container for tetras
201
+ tetras = np.zeros((xi.shape[0], 5, 4)).astype(int)
202
+
203
+ tetras[even_mask, :, :] = gi[even_mask, :][:, self.tetra_mask_even]
204
+ tetras[~even_mask, :, :] = gi[~even_mask, :][:, self.tetra_mask]
205
+ inside = np.logical_and(inside,self.inside(pos))
206
+ vertices_return = np.zeros((pos.shape[0],4,3))
207
+ vertices_return[:] = np.nan
208
+ # set all masks not inside to False
209
+ mask[~inside,:] = False
210
+ #print(mask.shape,inside.shape,vertices.shape,vertices_return.shape,vertices[mask,:,:].shape)
211
+ vertices_return[inside,:,:] = vertices[mask,:,:]#[mask,:,:]#[inside,:,:]
212
+ c_return = np.zeros((pos.shape[0],4))
213
+ c_return[:] = np.nan
214
+ c_return[inside] = c[mask]
215
+ tetra_return = np.zeros((pos.shape[0],4)).astype(int)
216
+ tetra_return[:] = -1
217
+ tetra_return[inside,:] = tetras[mask,:]
218
+ return vertices_return, c_return, tetra_return, inside
219
+
220
+ def get_constant_gradient(self, region):
221
+ """
222
+ Get the constant gradient for the specified nodes
223
+
224
+ Parameters
225
+ ----------
226
+ region : np.array(dtype=bool)
227
+ mask of nodes to calculate cg for
228
+
229
+ Returns
230
+ -------
231
+
232
+ """
233
+ if self.cg is None:
234
+ logger.info("Running constant gradient")
235
+ elements_gradients = self.get_element_gradients(np.arange(self.ntetra))
236
+ region = region.astype('int64')
237
+
238
+ neighbours = self.get_neighbours()
239
+ elements = self.get_elements()
240
+ idc, c, ncons = cg(elements_gradients, neighbours.astype('int64'), elements.astype('int64'), self.nodes,
241
+ region.astype('int64'))
242
+
243
+ idc = np.array(idc[:ncons, :])
244
+ c = np.array(c[:ncons, :])
245
+ B = np.zeros(c.shape[0])
246
+ self.cg = (c,idc,B)
247
+ return self.cg[0], self.cg[1], self.cg[2]
248
+
249
+ def get_elements(self):
250
+ """
251
+ Get a numpy array of all of the elements in the mesh
252
+
253
+ Returns
254
+ -------
255
+ numpy array elements
256
+
257
+ """
258
+
259
+ x = np.arange(0, self.n_cell_x)
260
+ y = np.arange(0, self.n_cell_y)
261
+ z = np.arange(0, self.n_cell_z)
262
+
263
+ c_xi, c_yi, c_zi = np.meshgrid(x, y, z,indexing='ij')
264
+ c_xi = c_xi.flatten(order='F')
265
+ c_yi = c_yi.flatten(order='F')
266
+ c_zi = c_zi.flatten(order='F')
267
+ # get cell corners
268
+ xi, yi, zi = self.cell_corner_indexes(c_xi, c_yi, c_zi)
269
+ even_mask = (c_xi + c_yi + c_zi) % 2 == 0
270
+ gi = xi + yi * self.nsteps[0] + zi * self.nsteps[0] * self.nsteps[1]
271
+ tetras = np.zeros((c_xi.shape[0], 5, 4)).astype('int64')
272
+ tetras[even_mask, :, :] = gi[even_mask, :][:, self.tetra_mask_even]
273
+ tetras[~even_mask, :, :] = gi[~even_mask, :][:, self.tetra_mask]
274
+
275
+ return tetras.reshape((tetras.shape[0]*tetras.shape[1],tetras.shape[2]))
276
+
277
+ def get_element_gradients(self, elements = None):
278
+ """
279
+ Get the gradients of all tetras
280
+
281
+ Parameters
282
+ ----------
283
+ elements
284
+
285
+ Returns
286
+ -------
287
+
288
+ """
289
+ if elements is None:
290
+ elements = np.arange(0,self.ntetra)
291
+ x = np.arange(0, self.n_cell_x)
292
+ y = np.arange(0, self.n_cell_y)
293
+ z = np.arange(0, self.n_cell_z)
294
+
295
+ c_xi, c_yi, c_zi = np.meshgrid(x, y, z, indexing='ij')
296
+ c_xi = c_xi.flatten(order='F')
297
+ c_yi = c_yi.flatten(order='F')
298
+ c_zi = c_zi.flatten(order='F')
299
+ even_mask = (c_xi + c_yi + c_zi) % 2 == 0
300
+ # get cell corners
301
+ xi, yi, zi = self.cell_corner_indexes(c_xi, c_yi, c_zi) # global_index_to_node_index(gi)
302
+ # convert to node locations
303
+ nodes = self.node_indexes_to_position(xi, yi, zi).T
304
+
305
+ points = np.zeros((5, 4, self.n_cells, 3))
306
+ points[:, :, even_mask, :] = nodes[:, even_mask, :][self.tetra_mask_even, :, :]
307
+ points[:, :, ~even_mask, :] = nodes[:, ~even_mask, :][self.tetra_mask, :, :]
308
+
309
+ # changing order to points, tetra, nodes, coord
310
+ points = points.swapaxes(0, 2)
311
+ points = points.swapaxes(1, 2)
312
+
313
+ ps = points.reshape(points.shape[0] * points.shape[1], points.shape[2], points.shape[3])
314
+
315
+ m = np.array(
316
+ [[(ps[:, 1, 0] - ps[:, 0, 0]), (ps[:, 1, 1] - ps[:, 0, 1]),
317
+ (ps[:, 1, 2] - ps[:, 0, 2])],
318
+ [(ps[:, 2, 0] - ps[:, 0, 0]), (ps[:, 2, 1] - ps[:, 0, 1]),
319
+ (ps[:, 2, 2] - ps[:, 0, 2])],
320
+ [(ps[:, 3, 0] - ps[:, 0, 0]), (ps[:, 3, 1] - ps[:, 0, 1]),
321
+ (ps[:, 3, 2] - ps[:, 0, 2])]])
322
+ I = np.array(
323
+ [[-1., 1., 0., 0.],
324
+ [-1., 0., 1., 0.],
325
+ [-1., 0., 0., 1.]])
326
+ m = np.swapaxes(m, 0, 2)
327
+ element_gradients = np.linalg.inv(m)
328
+
329
+ element_gradients = element_gradients.swapaxes(1, 2)
330
+ element_gradients = element_gradients @ I
331
+
332
+ return element_gradients[elements,:,:]
333
+
334
+ def get_tetra_gradient_for_location(self, pos):
335
+ """
336
+ Get the gradient of the tetra for a location
337
+
338
+ Parameters
339
+ ----------
340
+ pos
341
+
342
+ Returns
343
+ -------
344
+
345
+ """
346
+ vertices, bc, tetras, inside = self.get_tetra_for_location(pos)
347
+ ps = vertices
348
+ m = np.array(
349
+ [[(ps[:, 1, 0] - ps[:, 0, 0]), (ps[:, 1, 1] - ps[:, 0, 1]),
350
+ (ps[:, 1, 2] - ps[:, 0, 2])],
351
+ [(ps[:, 2, 0] - ps[:, 0, 0]), (ps[:, 2, 1] - ps[:, 0, 1]),
352
+ (ps[:, 2, 2] - ps[:, 0, 2])],
353
+ [(ps[:, 3, 0] - ps[:, 0, 0]), (ps[:, 3, 1] - ps[:, 0, 1]),
354
+ (ps[:, 3, 2] - ps[:, 0, 2])]])
355
+ I = np.array(
356
+ [[-1., 1., 0., 0.],
357
+ [-1., 0., 1., 0.],
358
+ [-1., 0., 0., 1.]])
359
+ m = np.swapaxes(m, 0, 2)
360
+ element_gradients = np.linalg.inv(m)
361
+
362
+ element_gradients = element_gradients.swapaxes(1, 2)
363
+ element_gradients = element_gradients @ I
364
+ return vertices, element_gradients, tetras, inside
365
+
366
+ def inside(self, pos):
367
+ """
368
+ Check if a point is inside the structured grid
369
+
370
+ Parameters
371
+ ----------
372
+ pos
373
+
374
+ Returns
375
+ -------
376
+
377
+ """
378
+ # check whether point is inside box
379
+ inside = np.ones(pos.shape[0]).astype(bool)
380
+ for i in range(3):
381
+ inside *= pos[:, i] > self.origin[None, i]
382
+ inside *= pos[:, i] < self.origin[None, i] + \
383
+ self.step_vector[None, i] * self.nsteps_cells[None, i]
384
+ return inside
385
+
386
+ def global_node_indicies(self, indexes):
387
+ """
388
+ Convert from node indexes to global node index
389
+
390
+ Parameters
391
+ ----------
392
+ indexes
393
+
394
+ Returns
395
+ -------
396
+
397
+ """
398
+ indexes = np.array(indexes).swapaxes(0, 2)
399
+ return indexes[:, :, 0] + self.nsteps[None, None, 0] \
400
+ * indexes[:, :, 1] + self.nsteps[None, None, 0] * \
401
+ self.nsteps[None, None, 1] * indexes[:, :, 2]
402
+
403
+ def global_cell_indicies(self, indexes):
404
+ """
405
+ Convert from cell indexes to global cell index
406
+
407
+ Parameters
408
+ ----------
409
+ indexes
410
+
411
+ Returns
412
+ -------
413
+
414
+ """
415
+ indexes = np.array(indexes).swapaxes(0, 2)
416
+ return indexes[:, :, 0] + self.nsteps_cells[None, None, 0] \
417
+ * indexes[:, :, 1] + self.nsteps_cells[None, None, 0] * \
418
+ self.nsteps_cells[None, None, 1] * indexes[:, :, 2]
419
+
420
+ def cell_corner_indexes(self, x_cell_index, y_cell_index, z_cell_index):
421
+ """
422
+ Returns the indexes of the corners of a cell given its location xi,
423
+ yi, zi
424
+
425
+ Parameters
426
+ ----------
427
+ x_cell_index
428
+ y_cell_index
429
+ z_cell_index
430
+
431
+ Returns
432
+ -------
433
+
434
+ """
435
+ x_cell_index = np.array(x_cell_index)
436
+ y_cell_index = np.array(y_cell_index)
437
+ z_cell_index = np.array(z_cell_index)
438
+
439
+ xcorner = np.array([0, 1, 0, 1, 0, 1, 0, 1])
440
+ ycorner = np.array([0, 0, 1, 1, 0, 0, 1, 1])
441
+ zcorner = np.array([0, 0, 0, 0, 1, 1, 1, 1])
442
+ xcorners = x_cell_index[:, None] + xcorner[None, :]
443
+ ycorners = y_cell_index[:, None] + ycorner[None, :]
444
+ zcorners = z_cell_index[:, None] + zcorner[None, :]
445
+ return xcorners, ycorners, zcorners
446
+
447
+ def position_to_cell_corners(self, pos):
448
+ """
449
+ Find the nodes that belong to a cell which contains a point
450
+
451
+ Parameters
452
+ ----------
453
+ pos
454
+
455
+ Returns
456
+ -------
457
+
458
+ """
459
+ inside = self.inside(pos)
460
+ ix, iy, iz = self.position_to_cell_index(pos)
461
+ cornersx, cornersy, cornersz = self.cell_corner_indexes(ix, iy, iz)
462
+ globalidx = self.global_cell_indicies(
463
+ np.dstack([cornersx, cornersy, cornersz]).T)
464
+ return globalidx, inside
465
+
466
+ def position_to_cell_index(self, pos):
467
+ """
468
+ Find which cell a point is in
469
+
470
+ Parameters
471
+ ----------
472
+ pos
473
+
474
+ Returns
475
+ -------
476
+
477
+ """
478
+ ix = pos[:, 0] - self.origin[None, 0]
479
+ iy = pos[:, 1] - self.origin[None, 1]
480
+ iz = pos[:, 2] - self.origin[None, 2]
481
+ ix = ix // self.step_vector[None, 0]
482
+ iy = iy // self.step_vector[None, 1]
483
+ iz = iz // self.step_vector[None, 2]
484
+ return ix.astype(int), iy.astype(int), iz.astype(int)
485
+
486
+ def node_indexes_to_position(self, xindex, yindex, zindex):
487
+ """
488
+ Get the xyz position from the node coordinates
489
+
490
+ Parameters
491
+ ----------
492
+ xindex
493
+ yindex
494
+ zindex
495
+
496
+ Returns
497
+ -------
498
+
499
+ """
500
+ x = self.origin[0] + self.step_vector[0] * xindex
501
+ y = self.origin[1] + self.step_vector[1] * yindex
502
+ z = self.origin[2] + self.step_vector[2] * zindex
503
+
504
+ return np.array([x, y, z])
505
+
506
+ def global_index_to_node_index(self, global_index):
507
+ """
508
+ Convert from global indexes to xi,yi,zi
509
+
510
+ Parameters
511
+ ----------
512
+ global_index
513
+
514
+ Returns
515
+ -------
516
+
517
+ """
518
+ # determine the ijk indices for the global index.
519
+ # remainder when dividing by nx = i
520
+ # remained when dividing modulus of nx by ny is j
521
+ x_index = global_index % self.nsteps[0, None]
522
+ y_index = global_index // self.nsteps[0, None] % \
523
+ self.nsteps[1, None]
524
+ z_index = global_index // self.nsteps[0, None] // \
525
+ self.nsteps[1, None]
526
+ return x_index, y_index, z_index
527
+
528
+ def global_index_to_cell_index(self, global_index):
529
+ """
530
+ Convert from global indexes to xi,yi,zi
531
+
532
+ Parameters
533
+ ----------
534
+ global_index
535
+
536
+ Returns
537
+ -------
538
+
539
+ """
540
+ # determine the ijk indices for the global index.
541
+ # remainder when dividing by nx = i
542
+ # remained when dividing modulus of nx by ny is j
543
+
544
+ x_index = global_index % self.nsteps_cells[0, None]
545
+ y_index = global_index // self.nsteps_cells[0, None] % \
546
+ self.nsteps_cells[1, None]
547
+ z_index = global_index // self.nsteps_cells[0, None] // \
548
+ self.nsteps_cells[1, None]
549
+ return x_index, y_index, z_index
550
+
551
+ def get_neighbours(self):
552
+ """
553
+ This function goes through all of the elements in the mesh and assembles a numpy array
554
+ with the neighbours for each element
555
+
556
+ Returns
557
+ -------
558
+
559
+ """
560
+ # elements = self.get_elements()
561
+ # neighbours = np.zeros((self.ntetra,4)).astype('int64')
562
+ # neighbours[:] = -1
563
+ # tetra_neighbours(elements,neighbours)
564
+ # return neighbours
565
+ tetra_index = np.arange(0, self.ntetra)
566
+ neighbours = np.zeros((self.ntetra, 4)).astype('int64')
567
+ neighbours[:] = -9999
568
+ neighbours[tetra_index%5 == 0,:] = tetra_index[tetra_index%5 == 0,None] \
569
+ + np.arange(1,5)[None,:] # first tetra is the centre one so all of its neighbours are in the same cell
570
+ neighbours[tetra_index % 5 != 0, 0] = np.tile(
571
+ tetra_index[tetra_index % 5 == 0], (4, 1)).flatten(
572
+ order='F') # add first tetra to other neighbours
573
+
574
+ # now create masks for the different tetra indexes
575
+ one_mask = tetra_index % 5 == 1
576
+ two_mask = tetra_index % 5 == 2
577
+ three_mask = tetra_index % 5 == 3
578
+ four_mask = tetra_index % 5 == 4
579
+
580
+ # create masks for whether cell is odd or even
581
+ odd_mask = np.sum(self.global_index_to_cell_index(tetra_index // 5),
582
+ axis=0) % 2 == 1
583
+ odd_mask = ~odd_mask.astype(bool)
584
+
585
+ # apply masks to
586
+ masks = []
587
+ masks.append([np.logical_and(one_mask, odd_mask),
588
+ np.array([[-1, 0, 0, 1], [0, 1, 0, 2], [0, 0, 1, 3]])])
589
+ masks.append([np.logical_and(two_mask, odd_mask),
590
+ np.array([[1, 0, 0, 2], [0, -1, 0, 1], [0, 0, 1, 4]])])
591
+ masks.append([np.logical_and(three_mask, odd_mask),
592
+ np.array([[-1, 0, 0, 4], [0, -1, 0, 3], [0, 0, -1, 2]])])
593
+ masks.append([np.logical_and(four_mask, odd_mask),
594
+ np.array([[1, 0, 0, 3], [0, 1, 0, 4], [0, 0, -1, 1]])])
595
+
596
+ masks.append([np.logical_and(one_mask, ~odd_mask),
597
+ np.array([[1, 0, 0, 1], [0, 1, 0, 2], [0, 0, 1, 4]])])
598
+ masks.append([np.logical_and(two_mask, ~odd_mask),
599
+ np.array([[-1, 0, 0, 2], [0, -1, 0, 1], [0, 0, 1, 3]])])
600
+ masks.append([np.logical_and(three_mask, ~odd_mask),
601
+ np.array([[-1, 0, 0, 4], [0, 1, 0, 3], [0, 0, -1, 1]])])
602
+ masks.append([np.logical_and(four_mask, ~odd_mask),
603
+ np.array([[1, 0, 0, 3], [0, -1, 0, 4], [0, 0, -1, 2]])])
604
+
605
+ for m in masks:
606
+ logic = m[0]
607
+ mask = m[1]
608
+ c_xi, c_yi, c_zi = self.global_index_to_cell_index(
609
+ tetra_index[logic] // 5)
610
+ # mask = np.array([[1,0,0,4],[0,0,-1,2],[0,1,0,3],[0,0,0,0]])
611
+ neigh_cell = np.zeros((c_xi.shape[0], 3, 3)).astype(int)
612
+ neigh_cell[:, :, 0] = c_xi[:, None] + mask[:, 0]
613
+ neigh_cell[:, :, 1] = c_yi[:, None] + mask[:, 1]
614
+ neigh_cell[:, :, 2] = c_zi[:, None] + mask[:, 2]
615
+ inside = neigh_cell[:, :, 0] >= 0
616
+ inside = np.logical_and(inside, neigh_cell[:, :, 1] >= 0)
617
+ inside = np.logical_and(inside, neigh_cell[:, :, 2] >= 0)
618
+ inside = np.logical_and(inside,
619
+ neigh_cell[:, :, 0] < self.n_cell_x)
620
+ inside = np.logical_and(inside,
621
+ neigh_cell[:, :, 1] < self.n_cell_y)
622
+ inside = np.logical_and(inside,
623
+ neigh_cell[:, :, 2] < self.n_cell_z)
624
+
625
+ global_neighbour_idx = np.zeros((c_xi.shape[0], 4)).astype(int)
626
+ global_neighbour_idx[:] = -1
627
+ global_neighbour_idx = (neigh_cell[:, :, 0] + neigh_cell[:, :, 1] *
628
+ self.n_cell_x + neigh_cell[:, :, 2] *
629
+ self.n_cell_x * self.n_cell_y) * 5 + mask[:, 3]
630
+
631
+ global_neighbour_idx[~inside] = -1
632
+ neighbours[logic, 1:] = global_neighbour_idx
633
+
634
+ return neighbours
635
+
636
+
637
+