diff --git a/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json index 64745fec..5e74ec3e 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json @@ -135,7 +135,7 @@ "parent": "mesh", "label": "Value(s)", "property": "", - "value": 0.0 + "value": 0.0001 }, "topography_object": { "main": true, diff --git a/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json index 206ea89e..32ad12a6 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json @@ -154,7 +154,7 @@ "parent": "mesh", "label": "Initial chargeability (V/V)", "property": "", - "value": 0.0 + "value": 0.0001 }, "reference_model": { "association": "Cell", diff --git a/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json index daac3d7a..0467722b 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json @@ -68,7 +68,7 @@ "property": "", "min": 0.0, "max": 10000.0, - "value": 0.0 + "value": 0.0001 }, "topography_object": { "main": true, diff --git a/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json index 3fa21d19..cb66b44e 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json @@ -93,7 +93,7 @@ "property": "", "min": 0.0, "max": 10000.0, - "value": 0.0 + "value": 0.0001 }, "reference_model": { "association": [ diff --git a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json index 6ec63e35..d0ced561 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json @@ -117,7 +117,7 @@ "parent": "mesh", "label": "Value(s)", "property": "", - "value": 0.001 + "value": 0.0001 }, "topography_object": { "main": true, diff --git a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json index 62a55c56..32257f61 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json @@ -136,7 +136,7 @@ "parent": "mesh", "label": "Initial chargeability (V/V)", "property": "", - "value": 0.001 + "value": 0.0001 }, "reference_model": { "association": "Cell", diff --git a/simpeg_drivers/components/factories/__init__.py b/simpeg_drivers/components/factories/__init__.py index b1317380..0b7451f3 100644 --- a/simpeg_drivers/components/factories/__init__.py +++ b/simpeg_drivers/components/factories/__init__.py @@ -19,7 +19,7 @@ from .entity_factory import EntityFactory from .misfit_factory import MisfitFactory from .simulation_factory import SimulationFactory -from .survey_factory import SurveyFactory, receiver_group +from .survey_factory import SurveyFactory # pylint: disable=unused-import # flake8: noqa diff --git a/simpeg_drivers/components/factories/survey_factory.py b/simpeg_drivers/components/factories/survey_factory.py index ca78655d..5ba1b035 100644 --- a/simpeg_drivers/components/factories/survey_factory.py +++ b/simpeg_drivers/components/factories/survey_factory.py @@ -33,39 +33,6 @@ from simpeg_drivers.components.factories.source_factory import SourcesFactory -def receiver_group(txi, potential_electrodes): - """ - Group receivers by common transmitter id. - - :param: txi : transmitter index number. - :param: potential_electrodes : geoh5py object that holds potential electrodes - ab_map and ab_cell_id for a dc survey. - - :return: ids : list of ids of potential electrodes used with transmitter txi. - """ - - index_map = potential_electrodes.ab_map() - index_map = {int(v): k for k, v in index_map.items() if v != "Unknown"} - ids = np.where( - potential_electrodes.ab_cell_id.values.astype(int) == index_map[txi] - )[0] - - return ids - - -def group_locations(obj, ids): - """ - Return vertex locations for possible group of cells. - - :param obj : geoh5py object containing cells, vertices structure. - :param ids : list of ids (or possibly single id) that indexes cells array. - - :return locations : tuple of n locations arrays where n is length of second - dimension of cells array. - """ - return (obj.vertices[obj.cells[ids, i]] for i in range(obj.cells.shape[1])) - - class SurveyFactory(SimPEGFactory): """Build SimPEG sources objects based on factory type.""" @@ -289,7 +256,9 @@ def _dcip_arguments(self, data=None, local_index=None): sources = [] self.local_index = [] for source_id in source_ids[np.argsort(order)]: # Cycle in original order - receiver_indices = receiver_group(source_id, receiver_entity) + receiver_indices = np.where(receiver_entity.ab_cell_id.values == source_id)[ + 0 + ] if local_index is not None: receiver_indices = list(set(receiver_indices).intersection(local_index)) diff --git a/simpeg_drivers/components/topography.py b/simpeg_drivers/components/topography.py index 34ff9ecb..62cf0e8f 100644 --- a/simpeg_drivers/components/topography.py +++ b/simpeg_drivers/components/topography.py @@ -164,13 +164,16 @@ def expand_actives( neighbours = get_neighbouring_cells(mesh.mesh, containing_cells) neighbours_xy = np.r_[neighbours[0] + neighbours[1]] + neighbours_xy = neighbours_xy[neighbours_xy != -1] # Make sure the new actives are connected to the old actives new_actives = ~active_cells[neighbours_xy] if np.any(new_actives): neighbours = get_neighbouring_cells( mesh.mesh, neighbours_xy[new_actives] ) - active_cells[np.r_[neighbours[2][0]]] = True # z-axis neighbours + neighbours_z = np.r_[neighbours[2][0]] + neighbours_z = neighbours_z[neighbours_z != -1] + active_cells[neighbours_z] = True # z-axis neighbours active_cells[neighbours_xy] = True # xy-axis neighbours diff --git a/simpeg_drivers/options.py b/simpeg_drivers/options.py index f19ad176..403ffaeb 100644 --- a/simpeg_drivers/options.py +++ b/simpeg_drivers/options.py @@ -27,7 +27,7 @@ ReferencedData, ) from geoh5py.groups import PropertyGroup, SimPEGGroup, UIJsonGroup -from geoh5py.objects import DrapeModel, Octree, Points +from geoh5py.objects import DrapeModel, Grid2D, Octree, Points from geoh5py.shared.utils import fetch_active_workspace from geoh5py.ui_json import InputFile from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -54,7 +54,7 @@ class ActiveCellsOptions(BaseModel): model_config = ConfigDict( arbitrary_types_allowed=True, ) - topography_object: Points | None = None + topography_object: Points | Grid2D | None = None topography: FloatData | float | None = None active_model: BooleanData | IntegerData | None = None diff --git a/tests/topography_test.py b/tests/topography_test.py index dfb96024..e0f5114c 100644 --- a/tests/topography_test.py +++ b/tests/topography_test.py @@ -14,14 +14,14 @@ import numpy as np -from simpeg_drivers.components import InversionTopography +from simpeg_drivers.components import InversionData, InversionMesh, InversionTopography from simpeg_drivers.options import ActiveCellsOptions from simpeg_drivers.potential_fields import MVIInversionOptions from simpeg_drivers.utils.testing import Geoh5Tester, setup_inversion_workspace def test_get_locations(tmp_path: Path): - geoh5, entity, model, survey, topography = setup_inversion_workspace( + geoh5, mesh, model, survey, topography = setup_inversion_workspace( tmp_path, background=0.0, anomaly=0.05, @@ -31,7 +31,6 @@ def test_get_locations(tmp_path: Path): inversion_type="magnetic_vector", ) with geoh5.open(): - mesh = model.parent tmi_channel, gyz_channel = survey.add_data( { "tmi": {"values": np.random.rand(survey.n_vertices)}, @@ -51,6 +50,7 @@ def test_get_locations(tmp_path: Path): ), starting_model=1.0, ) + geoh5 = params.geoh5 with geoh5.open(): topo = InversionTopography(geoh5, params) @@ -60,6 +60,25 @@ def test_get_locations(tmp_path: Path): params.active_cells.topography.values, ) + # Check that boundary cells are handled properly + # Shift one of the survey vertices to the corner + survey.vertices[0, :] = mesh.centroids[0, :] + geoh5.update_attribute(survey, "vertices") + inversion_mesh = InversionMesh(geoh5, params) + inversion_data = InversionData(geoh5, params) + params.inversion_type = "magnetotellurics" + active_cells = topo.active_cells(inversion_mesh, inversion_data) + + mesh.add_data( + { + "active_cells": { + "values": active_cells, + } + } + ) + assert not active_cells[-1] + + # Test flat topo params.active_cells.topography = 199.0 locs = topo.get_locations(params.active_cells.topography_object) np.testing.assert_allclose(locs[:, 2], np.ones_like(locs[:, 2]) * 199.0)