Source code for geos.pygeos_tools.solvers.ElasticSolver

# ------------------------------------------------------------------------------------------------------------
# SPDX-License-Identifier: LGPL-2.1-only
#
# Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
# Copyright (c) 2018-2024 TotalEnergies
# Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
# Copyright (c) 2023-2024 Chevron
# Copyright (c) 2019-     GEOS/GEOSX Contributors
# Copyright (c) 2019-     INRIA project-team Makutu
# All rights reserved
#
# See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
# ------------------------------------------------------------------------------------------------------------
import numpy.typing as npt
from typing import Tuple, Union
from typing_extensions import Self
from geos.pygeos_tools.solvers.WaveSolver import WaveSolver

__doc__ = """
AcousticSolver class inherits from WaveSolver class.

This adds method to read / set displacements at receiver.
"""


[docs] class ElasticSolver( WaveSolver ): """ ElasticSolver Object containing all methods to run ElasticSEM simulation with GEOSX Attributes ----------- The ones inherited from WaveSolver class """ def __init__( self: Self, solverType: str = "ElasticSEM", dt: float = None, minTime: float = 0.0, maxTime: float = None, dtSeismo: float = None, dtWaveField: float = None, sourceType: str = None, sourceFreq: float = None, **kwargs ): """ Parameters ---------- solverType: str The solverType targeted in GEOS XML deck. Defaults to "ElasticSEM" dt : float Time step for simulation minTime : float Starting time of simulation Default is 0 maxTime : float End Time of simulation dtSeismo : float Time step to save pressure for seismic trace dtWaveField : float Time step to save fields sourceType : str Type of source Default is None sourceFreq : float Frequency of the source Default is None kwargs : keyword args geosx_argv : list GEOSX arguments or command line as a splitted line """ super().__init__( solverType=solverType, dt=dt, minTime=minTime, maxTime=maxTime, dtSeismo=dtSeismo, dtWaveField=dtWaveField, sourceType=sourceType, sourceFreq=sourceFreq, **kwargs ) def __repr__( self: Self ): string_list = [] string_list.append( "Solver type : " + type( self ).__name__ + "\n" ) string_list.append( "dt : " + str( self.dt ) + "\n" ) string_list.append( "maxTime : " + str( self.maxTime ) + "\n" ) string_list.append( "dtSeismo : " + str( self.dtSeismo ) + "\n" ) string_list.append( "Outputs : " + str( self.hdf5Targets ) + "\n" + str( self.vtkTargets ) + "\n" ) rep = "" for string in string_list: rep += string return rep
[docs] def initialize( self: Self, rank: int = 0, xml=None ) -> None: super().initialize( rank, xml ) try: useDAS = self.xml.getAttribute( parentElement=self.type, attributeTag="useDAS" ) except AttributeError: useDAS = None if useDAS == "none": try: linearGEO = bool( self.xml.getAttribute( self.type, "linearDASGeometry" ) ) except AttributeError: linearGEO = False if linearGEO is True: self.useDAS = True
""" Accessors """
[docs] def getAllDisplacementAtReceivers( self: Self ) -> Tuple[ npt.NDArray, npt.NDArray, npt.NDArray ]: """ Get the displacement for the x, y and z directions at all time step and all receivers coordinates Returns -------- displacementX : numpy array Component X of the displacement displacementY : numpy array Component Y of the displacement displacementZ : numpy array Component Z of the displacement """ displacementX: npt.NDArray = self.getDisplacementAtReceivers( "X" ) displacementY: npt.NDArray = self.getDisplacementAtReceivers( "Y" ) displacementZ: npt.NDArray = self.getDisplacementAtReceivers( "Z" ) return displacementX, displacementY, displacementZ
[docs] def getDASSignalAtReceivers( self: Self ) -> npt.NDArray: """ Get the DAS signal values at receivers coordinates Returns -------- dassignal : numpy array Array containing the DAS signal values at all time step at all receivers coordinates """ if self.type != "ElasticSEM": raise TypeError( f"DAS signal not implemented for solver of type {self.type}." ) else: dassignal: npt.NDArray = self.getGeosWrapperByName( "dasSignalNp1AtReceivers" ) return dassignal
[docs] def getDisplacementAtReceivers( self: Self, component: str = "X" ) -> npt.NDArray: """ Get the displacement values at receivers coordinates for a given direction Returns -------- displacement : numpy array Array containing the displacements values at all time step at all receivers coordinates """ assert component.upper() in ( "X", "Y", "Z" ) if self.type == "ElasticFirstOrderSEM": displacement: npt.NDArray = self.getGeosWrapperByName( f"displacement{component.lower()}Np1AtReceivers" ) elif self.type == "ElasticSEM": displacement = self.getGeosWrapperByName( f"displacement{component.upper()}Np1AtReceivers" ) return displacement
[docs] def getWaveField( self: Self ) -> Union[ npt.NDArray, Tuple[ npt.NDArray, npt.NDArray, npt.NDArray ] ]: if self.useDAS: return self.getDASSignalAtReceivers() else: return self.getAllDisplacementAtReceivers()
# TODO # def getFullWaveFieldAtReceivers( self: Self, comm ): # print( "This method is not implemented yet" ) """ Update methods """
[docs] def updateDensityModel( self: Self, density: npt.NDArray ) -> None: """ Update density values in GEOS Parameters ----------- density : array New values for the density """ self.setGeosWrapperValueByName( "elasticDensity", value=density, filters=[ self.discretization ] )
[docs] def updateVelocityModel( self: Self, vel: npt.NDArray, component: str ) -> None: """ Update velocity value in GEOS Parameters ---------- vel : float/array Value(s) for velocity field component : str Vs or Vp """ assert component.lower() in ( "vs", "vp" ), "Only Vs or Vp component accepted" self.setGeosWrapperValueByName( "elasticVelocity" + component.title(), vel, filters=[ self.discretization ] )
""" Methods for reset of values """
[docs] def resetWaveField( self: Self, **kwargs ) -> None: """Reinitialize all displacement values on the Wavefield to zero in GEOSX""" self.setGeosWrapperValueByTargetKey( "Solvers/" + self.name + "/indexSeismoTrace", value=0 ) nodeManagerPath = f"domain/MeshBodies/{self.meshName}/meshLevels/{self.discretization}/nodeManager/" if self.type == "ElasticSEM": for component in ( "x", "y", "z" ): for ts in ( "nm1", "n", "np1" ): self.setGeosWrapperValueByTargetKey( nodeManagerPath + f"displacement{component}_{ts}", value=0.0 ) elif self.type == "ElasticFirstOrderSEM": component = ( "x", "y", "z" ) for c in component: self.setGeosWrapperValueByTargetKey( nodeManagerPath + f"displacement{c}_np1", value=0.0 ) prefix = self._getPrefixPathFor1RegionWith1CellBlock( **kwargs ) for i, c in enumerate( component ): for j in range( i, len( component ) ): cc = c + component[ j ] self.setGeosWrapperValueByTargetKey( prefix + f"stresstensor{cc}", value=0.0 )
[docs] def resetDisplacementAtReceivers( self: Self ) -> None: """Reinitialize displacement values at receivers to 0 """ for component in ( "X", "Y", "Z" ): self.setGeosWrapperValueByTargetKey( f"displacement{component}Np1AtReceivers", value=0.0 )