Source code for ogstools.meshlib.data_processing

# Copyright (c) 2012-2024, OpenGeoSys Community (http://www.opengeosys.org)
#            Distributed under a Modified BSD License.
#            See accompanying file LICENSE.txt or
#            http://www.opengeosys.org/project/license
#

from itertools import product
from typing import TypeVar

import numpy as np
import pyvista as pv
from typeguard import typechecked

from ogstools.variables import Variable

Mesh = TypeVar("Mesh", bound=pv.UnstructuredGrid)


def _raw_differences_all_data(base_mesh: Mesh, subtract_mesh: Mesh) -> Mesh:
    diff = base_mesh.copy(deep=True)
    sampled_subtract_mesh = base_mesh.sample(subtract_mesh)
    for point_data_key in base_mesh.point_data:
        diff.point_data[point_data_key] -= sampled_subtract_mesh.point_data[
            point_data_key
        ]
    for cell_data_key in base_mesh.cell_data:
        if cell_data_key == "MaterialIDs":
            continue
        diff.cell_data[cell_data_key] -= sampled_subtract_mesh.cell_data[
            cell_data_key
        ]
    return diff


[docs] def difference( base_mesh: Mesh, subtract_mesh: Mesh, variable: Variable | str | None = None, ) -> Mesh: """ Compute the difference of variables between two meshes. :param base_mesh: The mesh to subtract from. :param subtract_mesh: The mesh whose data is to be subtracted. :param variable: The variable of interest. If not given, all point and cell_data will be processed raw. :returns: A new mesh containing the difference of `variable` or of all datasets between both meshes. """ if variable is None: return _raw_differences_all_data(base_mesh, subtract_mesh) if isinstance(variable, str): variable = Variable(data_name=variable, output_name=variable) var_key = variable.data_name if isinstance(variable, Variable) else variable is_same_topology = ( base_mesh.points.shape == subtract_mesh.points.shape and base_mesh.cells.shape == subtract_mesh.cells.shape and np.all(np.equal(base_mesh.points, subtract_mesh.points)) and np.all(np.equal(base_mesh.cells, subtract_mesh.cells)) ) if is_same_topology: sub_mesh = subtract_mesh mask = None else: sub_mesh = base_mesh.sample(subtract_mesh) mask = sub_mesh[var_key] == 0.0 diff_mesh = base_mesh.copy(deep=True) diff_mesh.clear_point_data() diff_mesh.clear_cell_data() outname = variable.difference.output_name vals = np.asarray( [variable.transform(mesh) for mesh in [base_mesh, sub_mesh]] ) diff_mesh[outname] = np.empty(vals.shape[1:]) diff_mesh[outname] = vals[0] - vals[1] if mask is not None: diff_mesh[outname][mask] = np.nan return diff_mesh
[docs] def difference_pairwise( meshes_1: list | np.ndarray, meshes_2: list | np.ndarray, variable: Variable | str | None = None, ) -> np.ndarray: """ Compute pairwise difference between meshes from two lists/arrays (they have to be of the same length). :param meshes_1: The first list/array of meshes to be subtracted from. :param meshes_2: The second list/array of meshes whose data is subtracted from the first list/array of meshes - meshes_1. :param variable: The variable of interest. If not given, all point and cell_data will be processed raw. :returns: An array of meshes containing the differences of `variable` or all datasets between meshes_1 and meshes_2. """ meshes_1 = np.asarray(meshes_1).ravel() meshes_2 = np.asarray(meshes_2).ravel() if len(meshes_1) != len(meshes_2): msg = "Mismatch in length of provided lists/arrays. \ Their length has to be identical to calculate pairwise \ difference. Did you intend to use difference_matrix()?" raise RuntimeError(msg) return np.asarray( [ difference(m1, m2, variable) for m1, m2 in zip(meshes_1, meshes_2, strict=False) ] )
[docs] @typechecked def difference_matrix( meshes_1: list | np.ndarray, meshes_2: list | np.ndarray | None = None, variable: Variable | str | None = None, ) -> np.ndarray: """ Compute the difference between all combinations of two meshes from one or two arrays based on a specified variable. :param meshes_1: The first list/array of meshes to be subtracted from. :param meshes_2: The second list/array of meshes, it is subtracted from the first list/array of meshes - meshes_1 (optional). :param variable: The variable of interest. If not given, all point and cell_data will be processed raw. :returns: An array of meshes containing the differences of `variable` or all datasets between meshes_1 and meshes_2 for all possible combinations. """ meshes_1 = np.asarray(meshes_1).ravel() if meshes_2 is None: meshes_2 = meshes_1.copy() meshes_2 = np.asarray(meshes_2).ravel() diff_meshes = [ difference(m1, m2, variable) for m1, m2 in product(meshes_1, meshes_2) ] return np.asarray(diff_meshes).reshape((len(meshes_1), len(meshes_2)))