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