grid-apps 0.1.0b1__tar.gz
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.
- grid_apps-0.1.0b1/LICENSE +21 -0
- grid_apps-0.1.0b1/PKG-INFO +105 -0
- grid_apps-0.1.0b1/docs/source/THIRD_PARTY_SOFTWARE.rst +28 -0
- grid_apps-0.1.0b1/grid_apps/__init__.py +37 -0
- grid_apps-0.1.0b1/grid_apps/_version.py +2 -0
- grid_apps-0.1.0b1/grid_apps/block_model_to_octree/__init__.py +8 -0
- grid_apps-0.1.0b1/grid_apps/block_model_to_octree/driver.py +234 -0
- grid_apps-0.1.0b1/grid_apps/block_model_to_octree/options.py +60 -0
- grid_apps-0.1.0b1/grid_apps/block_models/__init__.py +8 -0
- grid_apps-0.1.0b1/grid_apps/block_models/driver.py +207 -0
- grid_apps-0.1.0b1/grid_apps/block_models/options.py +104 -0
- grid_apps-0.1.0b1/grid_apps/driver.py +91 -0
- grid_apps-0.1.0b1/grid_apps/octree_creation/__init__.py +8 -0
- grid_apps-0.1.0b1/grid_apps/octree_creation/driver.py +460 -0
- grid_apps-0.1.0b1/grid_apps/octree_creation/options.py +212 -0
- grid_apps-0.1.0b1/grid_apps/utils.py +498 -0
- grid_apps-0.1.0b1/grid_apps-assets/__init__.py +8 -0
- grid_apps-0.1.0b1/grid_apps-assets/uijson/block_model_to_octree.ui.json +47 -0
- grid_apps-0.1.0b1/grid_apps-assets/uijson/block_models.ui.json +87 -0
- grid_apps-0.1.0b1/grid_apps-assets/uijson/octree_mesh.ui.json +241 -0
- grid_apps-0.1.0b1/package.rst +63 -0
- grid_apps-0.1.0b1/pyproject.toml +209 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2025 Mira Geoscience
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: grid-apps
|
|
3
|
+
Version: 0.1.0b1
|
|
4
|
+
Summary: Grid creation and manipulation using GEOH5 format.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
License-File: docs/source/THIRD_PARTY_SOFTWARE.rst
|
|
8
|
+
Keywords: geology,geophysics,earth sciences
|
|
9
|
+
Author: Mira Geoscience
|
|
10
|
+
Author-email: support@mirageoscience.com
|
|
11
|
+
Maintainer: Benjamin Kary
|
|
12
|
+
Maintainer-email: benjamink@mirageoscience.com
|
|
13
|
+
Requires-Python: >=3.10,<4.0
|
|
14
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Natural Language :: English
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
19
|
+
Classifier: Operating System :: POSIX
|
|
20
|
+
Classifier: Operating System :: Unix
|
|
21
|
+
Classifier: Programming Language :: Python
|
|
22
|
+
Classifier: Programming Language :: Python :: 3
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
28
|
+
Classifier: Topic :: Scientific/Engineering
|
|
29
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
30
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
31
|
+
Requires-Dist: discretize (>=0.11.0,<0.12.dev)
|
|
32
|
+
Requires-Dist: geoapps-utils (>=0.6.0b1,<0.7.dev)
|
|
33
|
+
Requires-Dist: geoh5py (>=0.12.0b1,<0.13.dev)
|
|
34
|
+
Requires-Dist: numpy (>=1.26.0,<1.27.0)
|
|
35
|
+
Requires-Dist: pydantic (>=2.5.2,<3.0.0)
|
|
36
|
+
Requires-Dist: scipy (>=1.14.0,<1.15.0)
|
|
37
|
+
Project-URL: Documentation, https://mirageoscience-grid-apps.readthedocs-hosted.com/
|
|
38
|
+
Project-URL: Homepage, https://www.mirageoscience.com/mining-industry-software/python-integration/
|
|
39
|
+
Project-URL: Repository, https://github.com/MiraGeoscience/grid-apps
|
|
40
|
+
Description-Content-Type: text/x-rst
|
|
41
|
+
|
|
42
|
+
grid-apps
|
|
43
|
+
=========
|
|
44
|
+
|
|
45
|
+
The **grid-apps** library offers tools for the creation and manipulation of grid objects (Octree, BlockModel, Grid2D, DrapeModel) using various Python libraries and `geoh5py <https://mirageoscience-geoh5py.readthedocs-hosted.com/>`_.
|
|
46
|
+
|
|
47
|
+
Installation
|
|
48
|
+
^^^^^^^^^^^^
|
|
49
|
+
**grid-apps** is currently written for Python 3.10 or higher.
|
|
50
|
+
|
|
51
|
+
Install **grid-apps** from PyPI::
|
|
52
|
+
|
|
53
|
+
$ pip install grid-apps
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
Feedback
|
|
57
|
+
^^^^^^^^
|
|
58
|
+
Have comments or suggestions? Submit feedback.
|
|
59
|
+
All the content can be found on the github_ repository.
|
|
60
|
+
|
|
61
|
+
.. _github: https://github.com/MiraGeoscience/grid-apps
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Visit `Mira Geoscience website <https://mirageoscience.com/>`_ to learn more about our products
|
|
65
|
+
and services.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
License
|
|
69
|
+
^^^^^^^
|
|
70
|
+
MIT License
|
|
71
|
+
|
|
72
|
+
Copyright (c) 2024-2025 Mira Geoscience
|
|
73
|
+
|
|
74
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
75
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
76
|
+
in the Software without restriction, including without limitation the rights
|
|
77
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
78
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
79
|
+
furnished to do so, subject to the following conditions:
|
|
80
|
+
|
|
81
|
+
The above copyright notice and this permission notice shall be included in all
|
|
82
|
+
copies or substantial portions of the Software.
|
|
83
|
+
|
|
84
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
85
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
86
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
87
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
88
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
89
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
90
|
+
SOFTWARE.
|
|
91
|
+
|
|
92
|
+
Third Party Software
|
|
93
|
+
^^^^^^^^^^^^^^^^^^^^
|
|
94
|
+
The grid-apps Software may provide links to third party libraries or code (collectively “Third Party Software”)
|
|
95
|
+
to implement various functions. Third Party Software does not comprise part of the Software.
|
|
96
|
+
The use of Third Party Software is governed by the terms of such software license(s).
|
|
97
|
+
Third Party Software notices and/or additional terms and conditions are located in the
|
|
98
|
+
`THIRD_PARTY_SOFTWARE.rst`_ file.
|
|
99
|
+
|
|
100
|
+
.. _THIRD_PARTY_SOFTWARE.rst: docs/source/THIRD_PARTY_SOFTWARE.rst
|
|
101
|
+
|
|
102
|
+
Copyright
|
|
103
|
+
^^^^^^^^^
|
|
104
|
+
Copyright (c) 2024-2025 Mira Geoscience Ltd.
|
|
105
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Third Party Software
|
|
2
|
+
====================
|
|
3
|
+
|
|
4
|
+
The octree-creation-app repository and source distributions bundle several libraries that are
|
|
5
|
+
compatibly licensed. We list these here.
|
|
6
|
+
|
|
7
|
+
.. list-table::
|
|
8
|
+
:widths: 30 30 60
|
|
9
|
+
:header-rows: 1
|
|
10
|
+
|
|
11
|
+
* - Name
|
|
12
|
+
- License
|
|
13
|
+
- Description
|
|
14
|
+
* - `discretize <https://simpeg.xyz/>`_
|
|
15
|
+
- MIT
|
|
16
|
+
- Discretization tools for finite volume and inverse problems
|
|
17
|
+
* - `geoh5py <https://github.com/MiraGeoscience/geoh5py>`_
|
|
18
|
+
- LGPL-3.0-or-later
|
|
19
|
+
- Python API for geoh5, an open file format for geoscientific data
|
|
20
|
+
* - `geoapps-utils <https://github.com/MiraGeoscience/geoapps-utils>`_
|
|
21
|
+
- MIT
|
|
22
|
+
- Utilities for geoscientific applications.
|
|
23
|
+
* - `numpy <https://github.com/numpy/numpy>`_
|
|
24
|
+
- BSD-3-Clause
|
|
25
|
+
- Fundamental package for array computing in Python
|
|
26
|
+
* - `scipy <https://github.com/scipy/scipy>`_
|
|
27
|
+
- BSD-3-Clause
|
|
28
|
+
- Fundamental algorithms for scientific computing in Python
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
2
|
+
# Copyright (c) 2022-2025 Mira Geoscience Ltd. '
|
|
3
|
+
# '
|
|
4
|
+
# This file is part of grid-apps package. '
|
|
5
|
+
# '
|
|
6
|
+
# grid-apps is distributed under the terms and conditions of the MIT License '
|
|
7
|
+
# (see LICENSE file at the root of this source code package). '
|
|
8
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
from ._version import __version__
|
|
18
|
+
except ModuleNotFoundError:
|
|
19
|
+
from datetime import datetime
|
|
20
|
+
|
|
21
|
+
__date_str = datetime.today().strftime("%Y%m%d")
|
|
22
|
+
__version__ = "0.0.0.dev0+" + __date_str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
logging.basicConfig(level=logging.INFO)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def assets_path() -> Path:
|
|
29
|
+
"""Return the path to the assets folder."""
|
|
30
|
+
|
|
31
|
+
parent = Path(__file__).parent
|
|
32
|
+
folder_name = f"{parent.name}-assets"
|
|
33
|
+
assets_folder = parent.parent / folder_name
|
|
34
|
+
if not assets_folder.is_dir():
|
|
35
|
+
raise RuntimeError(f"Assets folder not found: {assets_folder}")
|
|
36
|
+
|
|
37
|
+
return assets_folder
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
2
|
+
# Copyright (c) 2024-2025 Mira Geoscience Ltd. '
|
|
3
|
+
# '
|
|
4
|
+
# This file is part of grid-apps package. '
|
|
5
|
+
# '
|
|
6
|
+
# grid-apps is distributed under the terms and conditions of the MIT License '
|
|
7
|
+
# (see LICENSE file at the root of this source code package). '
|
|
8
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
2
|
+
# Copyright (c) 2024-2025 Mira Geoscience Ltd. '
|
|
3
|
+
# '
|
|
4
|
+
# This file is part of grid-apps package. '
|
|
5
|
+
# '
|
|
6
|
+
# grid-apps is distributed under the terms and conditions of the MIT License '
|
|
7
|
+
# (see LICENSE file at the root of this source code package). '
|
|
8
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
from discretize import TreeMesh
|
|
18
|
+
from geoh5py.data import FloatData, ReferencedData
|
|
19
|
+
from geoh5py.objects import BlockModel, Octree
|
|
20
|
+
from geoh5py.ui_json.utils import fetch_active_workspace
|
|
21
|
+
from scipy.spatial import cKDTree
|
|
22
|
+
|
|
23
|
+
from grid_apps.block_model_to_octree.options import BlockModel2OctreeOptions
|
|
24
|
+
from grid_apps.driver import BaseGridDriver
|
|
25
|
+
from grid_apps.utils import (
|
|
26
|
+
block_model_to_discretize,
|
|
27
|
+
boundary_value_indices,
|
|
28
|
+
tensor_mesh_ordering,
|
|
29
|
+
treemesh_2_octree,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Driver(BaseGridDriver):
|
|
37
|
+
"""
|
|
38
|
+
Convert a BlockModel object to Octree with various refinement strategies.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
_params_class = BlockModel2OctreeOptions
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def block_model_to_treemesh(
|
|
45
|
+
entity: BlockModel, diagonal_balance=True, finalize=True
|
|
46
|
+
) -> TreeMesh:
|
|
47
|
+
"""
|
|
48
|
+
Convert a block model to an octree mesh with the same base cell size and
|
|
49
|
+
centered.
|
|
50
|
+
|
|
51
|
+
:param entity: BlockModel object to be converted
|
|
52
|
+
:param diagonal_balance: Whether to balance the mesh diagonally.
|
|
53
|
+
:param finalize: Whether to finalize the treemesh after creation.
|
|
54
|
+
|
|
55
|
+
:return: TreeMesh object.
|
|
56
|
+
"""
|
|
57
|
+
origin = []
|
|
58
|
+
octree_cells = []
|
|
59
|
+
for ii, ax in zip("xyz", "uvz", strict=True):
|
|
60
|
+
cell_sizes = np.abs(getattr(entity, f"{ax}_cells"))
|
|
61
|
+
h_core = cell_sizes.min()
|
|
62
|
+
|
|
63
|
+
# Compute number of octree cells to span the extent
|
|
64
|
+
n_c = np.ceil(np.log2(np.sum(cell_sizes) / h_core))
|
|
65
|
+
cell_sizes_octree = np.ones(int(2**n_c)) * h_core
|
|
66
|
+
octree_cells.append(cell_sizes_octree)
|
|
67
|
+
|
|
68
|
+
# Colocate the center of the octree with the center of the block model
|
|
69
|
+
ind_core = np.where(cell_sizes == h_core)[0]
|
|
70
|
+
center = (
|
|
71
|
+
entity.origin[ii]
|
|
72
|
+
+ entity.local_axis_centers(ax)[ind_core[len(ind_core) // 2]]
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
axis_center = len(cell_sizes_octree) // 2
|
|
76
|
+
origin.append(center - np.sum(cell_sizes_octree[:axis_center]) - h_core / 2)
|
|
77
|
+
|
|
78
|
+
treemesh = TreeMesh(
|
|
79
|
+
octree_cells,
|
|
80
|
+
x0=origin,
|
|
81
|
+
finalize=finalize,
|
|
82
|
+
diagonal_balance=diagonal_balance,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return treemesh
|
|
86
|
+
|
|
87
|
+
def make_grid(self) -> Octree:
|
|
88
|
+
"""
|
|
89
|
+
Convert the block model and output the octree mesh.
|
|
90
|
+
|
|
91
|
+
:return: Octree object refined by the cell volumes or gradient of the data.
|
|
92
|
+
"""
|
|
93
|
+
with fetch_active_workspace(self.params.geoh5, mode="r+"):
|
|
94
|
+
entity = self.params.entity
|
|
95
|
+
|
|
96
|
+
treemesh = Driver.block_model_to_treemesh(entity, finalize=False)
|
|
97
|
+
model = None
|
|
98
|
+
if self.params.data is None:
|
|
99
|
+
treemesh = Driver.refine_by_cell_volumes(
|
|
100
|
+
treemesh, entity, finalize=True
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
treemesh = Driver.refine_by_values(
|
|
104
|
+
treemesh, self.params.data, finalize=True
|
|
105
|
+
)
|
|
106
|
+
# Transfer the model
|
|
107
|
+
ind = treemesh.get_containing_cells(entity.centroids)
|
|
108
|
+
model = (
|
|
109
|
+
np.ones(treemesh.n_cells, dtype=self.params.data.values.dtype)
|
|
110
|
+
* self.params.data.nan_value
|
|
111
|
+
)
|
|
112
|
+
model[ind] = self.params.data.values
|
|
113
|
+
|
|
114
|
+
nan_vals = (model == self.params.data.nan_value) | np.isnan(model)
|
|
115
|
+
if np.any(nan_vals):
|
|
116
|
+
tree = cKDTree(entity.centroids)
|
|
117
|
+
ind = tree.query(treemesh.cell_centers[nan_vals])[1]
|
|
118
|
+
model[nan_vals] = self.params.data.values[ind]
|
|
119
|
+
|
|
120
|
+
octree = treemesh_2_octree(
|
|
121
|
+
self.params.geoh5,
|
|
122
|
+
treemesh,
|
|
123
|
+
parent=self.params.output.out_group,
|
|
124
|
+
name=self.params.output.export_as or entity.name + "_octree",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
if model is not None and self.params.data is not None:
|
|
128
|
+
octree.add_data(
|
|
129
|
+
{
|
|
130
|
+
self.params.data.name: {
|
|
131
|
+
"values": model,
|
|
132
|
+
"entity_type": self.params.data.entity_type,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return octree
|
|
138
|
+
|
|
139
|
+
@staticmethod
|
|
140
|
+
def refine_by_cell_volumes(
|
|
141
|
+
mesh: TreeMesh,
|
|
142
|
+
entity: BlockModel,
|
|
143
|
+
finalize: bool = True,
|
|
144
|
+
mask: np.ndarray | None = None,
|
|
145
|
+
) -> TreeMesh:
|
|
146
|
+
"""
|
|
147
|
+
Refine the octree mesh by the cell volumes of the block model.
|
|
148
|
+
|
|
149
|
+
:param mesh: TreeMesh object to be refined.
|
|
150
|
+
:param entity: BlockModel object to be used for refinement.
|
|
151
|
+
:param finalize: Whether to finalize the treemesh after refinement.
|
|
152
|
+
:param mask: Optional mask on the block model centroids to apply the refinement over.
|
|
153
|
+
|
|
154
|
+
:return: TreeMesh object with refined levels.
|
|
155
|
+
"""
|
|
156
|
+
if not isinstance(entity, BlockModel):
|
|
157
|
+
raise TypeError("entity must be an instance of BlockModel.")
|
|
158
|
+
|
|
159
|
+
tensor_oct_level = []
|
|
160
|
+
for ax in "uvz":
|
|
161
|
+
cell_sizes = np.abs(getattr(entity, f"{ax}_cells"))
|
|
162
|
+
h_core = cell_sizes.min()
|
|
163
|
+
# Find the core region
|
|
164
|
+
tensor_oct_level.append(np.log2(cell_sizes / h_core).astype(int))
|
|
165
|
+
|
|
166
|
+
e_x, e_y, e_z = np.meshgrid(*tensor_oct_level)
|
|
167
|
+
max_level = np.c_[np.ravel(e_x), np.ravel(e_y), np.ravel(e_z)].max(axis=1)
|
|
168
|
+
|
|
169
|
+
locations = entity.centroids
|
|
170
|
+
if mask is not None:
|
|
171
|
+
locations = locations[mask]
|
|
172
|
+
max_level = max_level[mask]
|
|
173
|
+
|
|
174
|
+
mesh.insert_cells(locations, mesh.max_level - max_level, finalize=finalize)
|
|
175
|
+
|
|
176
|
+
return mesh
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def refine_by_values(
|
|
180
|
+
mesh: TreeMesh, data: FloatData | ReferencedData, finalize=True
|
|
181
|
+
) -> TreeMesh:
|
|
182
|
+
"""
|
|
183
|
+
Increase the mesh resolution based on the gradient of data values.
|
|
184
|
+
|
|
185
|
+
:param mesh: Input TreeMesh object.
|
|
186
|
+
:param data: FloatData or ReferencedData object containing the values to
|
|
187
|
+
be used for refinement.
|
|
188
|
+
:param finalize: Whether to finalize the treemesh after refinement.
|
|
189
|
+
|
|
190
|
+
:return: TreeMesh object with refined levels.
|
|
191
|
+
"""
|
|
192
|
+
if not isinstance(data, FloatData | ReferencedData):
|
|
193
|
+
raise TypeError(
|
|
194
|
+
"Argument 'data' must be an instance of FloatData or ReferencedData."
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
entity = data.parent
|
|
198
|
+
if not isinstance(entity, BlockModel):
|
|
199
|
+
raise TypeError("The parent of 'data' must be an instance of BlockModel.")
|
|
200
|
+
|
|
201
|
+
tensor = block_model_to_discretize(entity)
|
|
202
|
+
indices = tensor_mesh_ordering(entity)
|
|
203
|
+
|
|
204
|
+
gradients = np.abs(tensor.cell_gradient @ data.values[indices])
|
|
205
|
+
levels = np.zeros(gradients.shape, dtype=int)
|
|
206
|
+
isnan = np.isnan(gradients)
|
|
207
|
+
|
|
208
|
+
if isinstance(data, FloatData):
|
|
209
|
+
actives = gradients[~isnan]
|
|
210
|
+
bins = np.percentile(
|
|
211
|
+
actives[actives > 0], np.linspace(5, 95, mesh.max_level)
|
|
212
|
+
)
|
|
213
|
+
levels[~isnan] = np.searchsorted(bins, actives)
|
|
214
|
+
else:
|
|
215
|
+
levels[gradients > 0] = mesh.max_level
|
|
216
|
+
|
|
217
|
+
# Refine on the value/nan interface, without boundary cells
|
|
218
|
+
if any(isnan):
|
|
219
|
+
horizon = boundary_value_indices(
|
|
220
|
+
tensor, data.values[indices], data.nan_value
|
|
221
|
+
)
|
|
222
|
+
mesh = Driver.refine_by_cell_volumes(
|
|
223
|
+
mesh, entity, finalize=False, mask=horizon[np.argsort(indices)]
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
locs = tensor.average_cell_to_face @ tensor.cell_centers
|
|
227
|
+
mesh.insert_cells(locs[~isnan], levels[~isnan].astype(int), finalize=finalize)
|
|
228
|
+
|
|
229
|
+
return mesh
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
if __name__ == "__main__":
|
|
233
|
+
file = Path(sys.argv[1]).resolve()
|
|
234
|
+
Driver.start(file)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
2
|
+
# Copyright (c) 2024-2025 Mira Geoscience Ltd. '
|
|
3
|
+
# '
|
|
4
|
+
# This file is part of grid-apps package. '
|
|
5
|
+
# '
|
|
6
|
+
# grid-apps is distributed under the terms and conditions of the MIT License '
|
|
7
|
+
# (see LICENSE file at the root of this source code package). '
|
|
8
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import ClassVar
|
|
14
|
+
|
|
15
|
+
from geoapps_utils.driver.data import BaseData
|
|
16
|
+
from geoh5py.data import FloatData, ReferencedData
|
|
17
|
+
from geoh5py.groups import UIJsonGroup
|
|
18
|
+
from geoh5py.objects import BlockModel
|
|
19
|
+
from pydantic import BaseModel, ConfigDict
|
|
20
|
+
|
|
21
|
+
from grid_apps import assets_path
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class OutputOptions(BaseModel):
|
|
25
|
+
"""
|
|
26
|
+
Output parameters for block model creation.
|
|
27
|
+
|
|
28
|
+
:param export_as: Name of the output entity.
|
|
29
|
+
:param out_group: Output UIJson group.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
33
|
+
|
|
34
|
+
export_as: str | None = None
|
|
35
|
+
out_group: UIJsonGroup | None = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class BlockModel2OctreeOptions(BaseData):
|
|
39
|
+
"""
|
|
40
|
+
Block model parameters for use with `block_models.driver`.
|
|
41
|
+
|
|
42
|
+
:param entity: BlockModel source object.
|
|
43
|
+
:param data: Optional data to refine the octree mesh.
|
|
44
|
+
:param output: Output options.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
48
|
+
|
|
49
|
+
name: ClassVar[str] = "block_model_to_octree"
|
|
50
|
+
default_ui_json: ClassVar[Path] = (
|
|
51
|
+
assets_path() / "uijson/block_model_to_octree.ui.json"
|
|
52
|
+
)
|
|
53
|
+
title: ClassVar[str] = "Block Model to Octree Conversion"
|
|
54
|
+
run_command: ClassVar[str] = "grid_apps.block_model_to_octree.driver"
|
|
55
|
+
conda_environment: str = "grid_apps"
|
|
56
|
+
|
|
57
|
+
entity: BlockModel
|
|
58
|
+
data: FloatData | ReferencedData | None = None
|
|
59
|
+
|
|
60
|
+
output: OutputOptions = OutputOptions()
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
2
|
+
# Copyright (c) 2024-2025 Mira Geoscience Ltd. '
|
|
3
|
+
# '
|
|
4
|
+
# This file is part of grid-apps package. '
|
|
5
|
+
# '
|
|
6
|
+
# grid-apps is distributed under the terms and conditions of the MIT License '
|
|
7
|
+
# (see LICENSE file at the root of this source code package). '
|
|
8
|
+
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|