From 854db0e5fd9c0a49f04cd545aec3e731ca284adf Mon Sep 17 00:00:00 2001 From: mlemayTTE Date: Thu, 3 Apr 2025 17:05:25 +0200 Subject: [PATCH 1/3] change dependency of geos-posp --- README.md | 145 +++++++++++++++++---------------------- geos-posp/pyproject.toml | 13 +++- geos-posp/setup.py | 16 ----- 3 files changed, 75 insertions(+), 99 deletions(-) delete mode 100644 geos-posp/setup.py diff --git a/README.md b/README.md index 9d45d82f9..86215fee8 100644 --- a/README.md +++ b/README.md @@ -49,53 +49,53 @@ The following package defines [Paraview](https://docs.paraview.org/) plugins tha GEOS Python packages dependency tree (inter-dependency and main external dependencies) is the following: ``` -|-- geos-ats -|-- pygeos-tools -|-- geos-utils -|-- geos-geomechanics -| |-- geos-utils -| -|-- hdf5-wrapper -| |-- h5py -| -|-- geos-xml-tools -| |-- lxml -| -|-- geos-mesh -| |-- geos-utils -| |-- vtk -| -|-- geos-prep -| |-- geos-mesh -| |-- geos-xml-tools -| -|-- geos-posp -| |-- geos-mesh -| |-- geos-geomechanics -| -|-- time-history -| |-- hdf5-wrapper -| -|-- mesh-doctor -| |-- geos-prep -| |-- pyvista -| -|-- geos-trame -| |-- geos-xml-tools -| |-- geos-mesh -| |-- pyvista -| |-- trame -| -|-- geos-xml-viewer -| |-- geos-xml-tools -| |-- geos-mesh -| |-- pyvista -| -|-- geos-pv - |-- geos-prep - |-- geos-posp - |-- geos-xml-tools - |-- paraview +├── geos-ats +├── pygeos-tools +├── geos-utils +├── geos-geomechanics +│ ├── geos-utils +│ +├── hdf5-wrapper +│ ├── h5py +│ +├── geos-xml-tools +│ ├── lxml +│ +├── geos-mesh +│ ├── geos-utils +│ ├── vtk +│ +├── geos-prep +│ ├── geos-mesh +│ ├── geos-xml-tools +│ +├── geos-posp +│ ├── geos-mesh +│ ├── geos-geomechanics +│ +├── time-history +│ ├── hdf5-wrapper +│ +├── mesh-doctor +│ ├── geos-prep +│ ├── pyvista +│ +├── geos-trame +│ ├── geos-xml-tools +│ ├── geos-mesh +│ ├── pyvista +│ ├── trame +│ +├── geos-xml-viewer +│ ├── geos-xml-tools +│ ├── geos-mesh +│ ├── pyvista +│ +├── geos-pv + ├── geos-prep + ├── geos-posp + ├── geos-xml-tools + ├── paraview ``` See the [documentation](https://geosx-geosx.readthedocs-hosted.com/projects/geosx-geospythonpackages/en/latest/) for additional details about the packages and how to use them. @@ -149,43 +149,26 @@ If you do not have the rights to push the code and open new PRs, consider openin Any new package must have the following architecture: ``` -package-name -|-- pyproject.toml -|-- setup.py -|-- src -| |-- geos -| |-- package_name -| |-- file1.py -| |-- file1.py -|-- tests - |-- test1.py - |-- test2.py +package-name/ +├── pyproject.toml +├── src +│ ├── geos +│ ├── package_name +│ ├── file1.py +│ ├── file1.py +├── tests + ├── test1.py + ├── test2.py ``` -The *setup.py* file is optional. It is required if the package depends on another GEOS Python package located in the root directory. If you want a package1 to depend on package2, follow this [procedure](https://stackoverflow.com/questions/75159453/specifying-local-relative-dependency-in-pyproject-toml): - -* in the *package1/pyproject.py*, replace the tag `dependencies = ["external_packageX", "external_packageY",]` with `dynamic = ["dependencies"]` -* create the *package1/setup.py* file -* copy the following lines in the *setup.py* and update the dependencies - ``` - from pathlib import Path - from setuptools import setup - - # This is where you add any fancy path resolution to the local lib: - package_name = "geos-utils" - geos_utils_path: str = (Path(__file__).parent.parent / package_name).as_uri() - - setup( - install_requires=[ - "vtk >= 9.3", - "numpy >= 1.26", - "pandas >= 2.2", - "typing_extensions >= 4.12", - f"{package_name} @ {geos_utils_path}", - ] - ) - ``` +If you want a package to depend on another GEOS Python package (let's say `geos-utils`), in the pyproject.toml the dependency takes the form: +``` +dependencies = [ + ... + "geos-utils @ file:./geos-utils", +] +``` Release ------- diff --git a/geos-posp/pyproject.toml b/geos-posp/pyproject.toml index fe85ebc80..0b3aa428d 100644 --- a/geos-posp/pyproject.toml +++ b/geos-posp/pyproject.toml @@ -29,8 +29,17 @@ keywords = [ "GEOS", "Simulation", ] -dynamic = ["dependencies"] -requires-python = ">= 3.9" + +requires-python = ">= 3.10" + +dependencies = [ + "vtk >= 9.3", + "numpy >= 1.26", + "pandas >= 2.2", + "typing_extensions >= 4.12", + "geos-utils @ file:./geos-utils", +] + [project.urls] Homepage = "https://github.com/GEOS-DEV/geosPythonPackages" diff --git a/geos-posp/setup.py b/geos-posp/setup.py deleted file mode 100644 index d933e5f64..000000000 --- a/geos-posp/setup.py +++ /dev/null @@ -1,16 +0,0 @@ -from pathlib import Path -from setuptools import setup - -# This is where you add any fancy path resolution to the local lib: -package_name = "geos-utils" -geos_utils_path: str = (Path(__file__).parent.parent / package_name).as_uri() - -setup( - install_requires=[ - "vtk >= 9.3", - "numpy >= 1.26", - "pandas >= 2.2", - "typing_extensions >= 4.12", - f"{package_name} @ {geos_utils_path}", - ] -) \ No newline at end of file From 66b111757cfc79c962db27f8a43ca8845246f6e0 Mon Sep 17 00:00:00 2001 From: mlemayTTE Date: Fri, 4 Apr 2025 10:08:12 +0200 Subject: [PATCH 2/3] Linting and typing fix --- .../geos/geomechanics/model/MohrCoulomb.py | 2 +- .../geomechanicsCalculatorFunctions.py | 18 +++++++++-------- .../testsFunctionsGeomechanicsCalculator.py | 4 ++-- geos-geomechanics/tests/testsMohrCircle.py | 20 +++++++++++++------ 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/geos-geomechanics/src/geos/geomechanics/model/MohrCoulomb.py b/geos-geomechanics/src/geos/geomechanics/model/MohrCoulomb.py index 934091490..f18d1f630 100644 --- a/geos-geomechanics/src/geos/geomechanics/model/MohrCoulomb.py +++ b/geos-geomechanics/src/geos/geomechanics/model/MohrCoulomb.py @@ -92,5 +92,5 @@ def computeFailureEnvelop( element is the ordinates. """ sigmaMin: float = ( self.m_sigmaMin if stressNormalMin is None else stressNormalMin ) - stressNormal: npt.NDArray[ np.float64 ] = np.linspace( sigmaMin, stressNormalMax, n ) + stressNormal: npt.NDArray[ np.float64 ] = np.linspace( sigmaMin, stressNormalMax, n ).astype( np.float64 ) return ( stressNormal, np.array( self.computeShearStress( stressNormal ) ) ) diff --git a/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py b/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py index 48317c341..6053c2191 100644 --- a/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py +++ b/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Alexandre Benedicto, Martin Lemay +from typing import Any import numpy as np import numpy.typing as npt @@ -30,7 +31,7 @@ def specificGravity( density: npt.NDArray[ np.float64 ], specificDensity: float if abs( specificDensity ) < EPSILON: return np.full_like( density, np.nan ) - return density / specificDensity + return ( density / specificDensity ).astype( float ) # https://en.wikipedia.org/wiki/Elastic_modulus @@ -625,7 +626,7 @@ def criticalPorePressure( stressVector: npt.NDArray[ np.float64 ], rockCohesion: float, frictionAngle: float = 0.0, -) -> npt.NDArray[ np.float64 ]: +) -> npt.NDArray[ np.floating[ Any ] ]: r"""Compute the critical pore pressure. Fracturing can occur in areas where Critical pore pressure is greater than @@ -664,9 +665,9 @@ def criticalPorePressure( maximumPrincipalStress[ i ] = p1 # assertion frictionAngle < np.pi/2., so sin(frictionAngle) != 1 - cohesiveTerm: npt.NDArray[ np.float64 ] = ( rockCohesion * np.cos( frictionAngle ) / - ( 1 - np.sin( frictionAngle ) ) ) - residualTerm: npt.NDArray[ np.float64 ] = ( 3 * minimumPrincipalStress - maximumPrincipalStress ) / 2.0 + cohesiveTerm: npt.NDArray[ np.floating[ Any ] ] = ( rockCohesion * np.cos( frictionAngle ) / + ( 1.0 - np.sin( frictionAngle ) ) ) + residualTerm: npt.NDArray[ np.floating[ Any ] ] = ( 3.0 * minimumPrincipalStress - maximumPrincipalStress ) / 2.0 return cohesiveTerm + residualTerm @@ -848,16 +849,17 @@ def shearCapacityUtilization( traction: npt.NDArray[ np.float64 ], rockCohesion: assert traction.shape[ 1 ] == 3, "Traction vector must have 3 components." scu: npt.NDArray[ np.float64 ] = np.full( traction.shape[ 0 ], np.nan ) - for i, tractionVec in enumerate( traction ): + for i in range( traction.shape[ 0 ] ): + tractionVec: npt.NDArray[ np.float64 ] = traction[ i ] # use -1 to agree with Geos convention (i.e., compression with negative stress) - stressNormal: npt.NDArray[ np.float64 ] = -1.0 * tractionVec[ 0 ] + stressNormal: float = -1.0 * tractionVec[ 0 ] # compute failure envelope mohrCoulomb: MohrCoulomb = MohrCoulomb( rockCohesion, frictionAngle ) tauFailure: float = float( mohrCoulomb.computeShearStress( stressNormal ) ) scu_i: float = np.nan if tauFailure > 0: - scu_i = np.abs( tractionVec[ 1 ] ) / tauFailure + scu_i = abs( tractionVec[ 1 ] ) / tauFailure # compute SCU scu[ i ] = scu_i return scu diff --git a/geos-geomechanics/tests/testsFunctionsGeomechanicsCalculator.py b/geos-geomechanics/tests/testsFunctionsGeomechanicsCalculator.py index 82b90bffb..7c55c323e 100644 --- a/geos-geomechanics/tests/testsFunctionsGeomechanicsCalculator.py +++ b/geos-geomechanics/tests/testsFunctionsGeomechanicsCalculator.py @@ -247,9 +247,9 @@ def test_shearCapacityUtilization( self: Self ) -> None: # calculation obtained: npt.NDArray[ np.float64 ] = fcts.shearCapacityUtilization( traction, rockCohesion, frictionAngle ) - expected: npt.NDArray[ np.float64 ] = np.array( [ 0.899, 0.923, 0.982, 1.004, 1.048 ] ) + expected: list[ float ] = [ 0.899, 0.923, 0.982, 1.004, 1.048 ] - self.assertSequenceEqual( np.round( obtained, 3 ).flatten().tolist(), expected.tolist() ) + self.assertSequenceEqual( np.round( obtained, 3 ).flatten().tolist(), expected ) def test_computeStressPrincipalComponents( self: Self ) -> None: """Test calculation of stress principal components from stress tensor.""" diff --git a/geos-geomechanics/tests/testsMohrCircle.py b/geos-geomechanics/tests/testsMohrCircle.py index cd3b2e55c..ee1ee92ad 100644 --- a/geos-geomechanics/tests/testsMohrCircle.py +++ b/geos-geomechanics/tests/testsMohrCircle.py @@ -75,7 +75,7 @@ def test_MohrCoulombInit( self: Self ) -> None: def test_computeShearStress( self: Self ) -> None: """Test calculation of shear stress from normal stress.""" # inputs - stressNormal: npt.NDArray[ np.float64 ] = np.linspace( 5.0e8, 1.0e9, 100 ) + stressNormal: npt.NDArray[ np.float64 ] = np.linspace( 5.0e8, 1.0e9, 100 ).astype( float ) # expected values expectedValues: npt.NDArray[ np.float64 ] = np.array( [ 888163490.0, @@ -184,7 +184,7 @@ def test_computeShearStress( self: Self ) -> None: obtained: npt.NDArray[ np.float64 ] = np.array( mohrCoulomb.computeShearStress( stressNormal ) ) # test results - self.assertSequenceEqual( expectedValues.tolist(), np.round( obtained ).tolist() ) + self.assertSequenceEqual( expectedValues.tolist(), np.round( obtained ).tolist() ) #type: ignore[arg-type] def test_computeFailureEnvelop1( self: Self ) -> None: """Test calculation of failure envelop from minimum normal stress.""" @@ -221,8 +221,12 @@ def test_computeFailureEnvelop1( self: Self ) -> None: normalStressObtained, shearStressObtained = mohrCoulomb.computeFailureEnvelop( stressNormalMax, n=10 ) # test results - self.assertSequenceEqual( normalStressExpected.tolist(), np.round( normalStressObtained ).tolist() ) - self.assertSequenceEqual( shearStressExpected.tolist(), np.round( shearStressObtained ).tolist() ) + self.assertSequenceEqual( + normalStressExpected.tolist(), #type: ignore[arg-type] + np.round( normalStressObtained ).tolist() ) + self.assertSequenceEqual( + shearStressExpected.tolist(), #type: ignore[arg-type] + np.round( shearStressObtained ).tolist() ) def test_computeFailureEnvelop2( self: Self ) -> None: """Test calculation of failure envelop in user-defined range.""" @@ -262,5 +266,9 @@ def test_computeFailureEnvelop2( self: Self ) -> None: n=10 ) # test results - self.assertSequenceEqual( normalStressExpected.tolist(), np.round( normalStressObtained ).tolist() ) - self.assertSequenceEqual( shearStressExpected.tolist(), np.round( shearStressObtained ).tolist() ) + self.assertSequenceEqual( + normalStressExpected.tolist(), #type: ignore[arg-type] + np.round( normalStressObtained ).tolist() ) + self.assertSequenceEqual( + shearStressExpected.tolist(), #type: ignore[arg-type] + np.round( shearStressObtained ).tolist() ) From 288e4ea7ad28e24b3db3b4722ca3cc32effe674d Mon Sep 17 00:00:00 2001 From: mlemayTTE Date: Mon, 7 Apr 2025 15:38:07 +0200 Subject: [PATCH 3/3] update timehistory dependency --- .github/workflows/typing-check.yml | 2 +- .../processing/geomechanicsCalculatorFunctions.py | 1 - geos-timehistory/pyproject.toml | 7 ++++++- geos-timehistory/setup.py | 13 ------------- 4 files changed, 7 insertions(+), 16 deletions(-) delete mode 100644 geos-timehistory/setup.py diff --git a/.github/workflows/typing-check.yml b/.github/workflows/typing-check.yml index 4de561718..553404730 100644 --- a/.github/workflows/typing-check.yml +++ b/.github/workflows/typing-check.yml @@ -16,7 +16,7 @@ jobs: max-parallel: 3 matrix: # add packages to check typing - package-name: ["hdf5-geomechanics", "geos-posp", "geos-timehistory", "geos-utils", "geos-xml-tools", "hdf5-wrapper"] + package-name: ["geos-geomechanics", "geos-posp", "geos-timehistory", "geos-utils", "geos-xml-tools", "hdf5-wrapper"] steps: - uses: actions/checkout@v3 diff --git a/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py b/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py index 388a0dd7e..f436c8144 100644 --- a/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py +++ b/geos-geomechanics/src/geos/geomechanics/processing/geomechanicsCalculatorFunctions.py @@ -35,7 +35,6 @@ def specificGravity( density: npt.NDArray[ np.float64 ], specificDensity: float return ( density / specificDensity ).astype( float ) - # https://en.wikipedia.org/wiki/Elastic_modulus def youngModulus( bulkModulus: npt.NDArray[ np.float64 ], shearModulus: npt.NDArray[ np.float64 ] ) -> npt.NDArray[ np.float64 ]: diff --git a/geos-timehistory/pyproject.toml b/geos-timehistory/pyproject.toml index 0a2694817..d9da1cac4 100644 --- a/geos-timehistory/pyproject.toml +++ b/geos-timehistory/pyproject.toml @@ -17,7 +17,12 @@ classifiers = [ ] requires-python = ">=3.9" -dynamic = ["dependencies"] +dependencies = [ + "matplotlib", + "h5py", + "numpy", + "hdf5-wrapper @ file:./hdf5-wrapper", +] [project.scripts] plot-timehistory = "geos.timehistory.plot:main" diff --git a/geos-timehistory/setup.py b/geos-timehistory/setup.py deleted file mode 100644 index cf224cd79..000000000 --- a/geos-timehistory/setup.py +++ /dev/null @@ -1,13 +0,0 @@ -from pathlib import Path -from setuptools import setup - -# This is where you add any fancy path resolution to the local lib: -package_name = "hdf5-wrapper" -geos_utils_path: str = ( Path( __file__ ).parent.parent / package_name ).as_uri() - -setup( install_requires=[ - "matplotlib", - "h5py", - "numpy", - f"{package_name} @ {geos_utils_path}", -] )