Skip to content

Commit

Permalink
fix: Add source value array for fwi in wave solvers (#3502)
Browse files Browse the repository at this point in the history
This PR is adding an array to store the values of the sources in time to the acoustic wave solver.
This array is useful for FWI and pygeos.

---------

Co-authored-by: j0405284 <[email protected]>
Co-authored-by: BESSET Julien <[email protected]>
Co-authored-by: Stefano Frambati <[email protected]>
  • Loading branch information
4 people authored Feb 5, 2025
1 parent 9cfb92a commit 0b8a7e2
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 81 deletions.
4 changes: 2 additions & 2 deletions .integrated_tests.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
baselines:
bucket: geosx
baseline: integratedTests/baseline_integratedTests-pr3395-9832-31f145e
baseline: integratedTests/baseline_integratedTests-pr3502-10013-5b4e015

allow_fail:
all: ''
streak: ''
6 changes: 5 additions & 1 deletion BASELINE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines.
Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining.
These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD).

PR #3502 (2025-02-04)
=====================
Add array to store the source values in time inside wave solvers

PR #3395 (2024-01-22)
=====================
Add new fields and change the default input for some tests.
Expand Down Expand Up @@ -128,7 +132,7 @@ Add routine for automatic time steps in waveSolvers with new attributes

PR #3156 (2024-10-29)
====================
Restart check errors due to 1) schema node added to enable thermal option in well model and 2) arrays removed/added for option. Max difference errors due treatment of shutin wells. Previously non-zero rate value reported for shutin well, new code will set rate arrays to zero.
Restart check errors due to 1) schema node added to enable thermal option in well model and 2) arrays removed/added for option. Max difference errors due treatment of shutin wells. Previously non-zero rate value reported for shutin well, new code will set rate arrays to zero.

PR #2878 (2024-10-17)
=====================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,35 @@ void AcousticWaveEquationSEM::precomputeSourceAndReceiverTerm( MeshLevel & baseM
receiverConstants.setValues< EXEC_POLICY >( -1 );
receiverIsLocal.zero();

arrayView1d< TableFunction::KernelWrapper const > const sourceWaveletTableWrappers = m_sourceWaveletTableWrappers.toViewConst();
bool useSourceWaveletTables = m_useSourceWaveletTables;

//Correct size for sourceValue
EventManager const & event = getGroupByPath< EventManager >( "/Problem/Events" );
real64 const & maxTime = event.getReference< real64 >( EventManager::viewKeyStruct::maxTimeString() );
real64 const & minTime = event.getReference< real64 >( EventManager::viewKeyStruct::minTimeString() );
real64 dt = 0;
for( localIndex numSubEvent = 0; numSubEvent < event.numSubGroups(); ++numSubEvent )
{
EventBase const * subEvent = static_cast< EventBase const * >( event.getSubGroups()[numSubEvent] );
if( subEvent->getEventName() == "/Solvers/" + this->getName() )
{
dt = subEvent->getReference< real64 >( EventBase::viewKeyStruct::forceDtString() );
}
}

real64 dtCompute;

localIndex nSubSteps = (int) ceil( dt/m_timeStep );
dtCompute = dt/nSubSteps;

localIndex const nsamples = int( (maxTime - minTime) / dtCompute) + 1;

localIndex const numSourcesGlobal = m_sourceCoordinates.size( 0 );
m_sourceValue.resize( nsamples, numSourcesGlobal );

arrayView2d< real32 > const sourceValue = m_sourceValue.toView();

mesh.getElemManager().forElementSubRegionsComplete< CellElementSubRegion >( regionNames, [&]( localIndex const,
localIndex const er,
localIndex const esr,
Expand Down Expand Up @@ -192,7 +221,14 @@ void AcousticWaveEquationSEM::precomputeSourceAndReceiverTerm( MeshLevel & baseM
receiverCoordinates,
receiverIsLocal,
receiverNodeIds,
receiverConstants );
receiverConstants,
sourceValue,
dtCompute,
m_timeSourceFrequency,
m_timeSourceDelay,
m_rickerOrder,
sourceWaveletTableWrappers,
useSourceWaveletTables );
}
} );
elementSubRegion.faceList().freeOnDevice();
Expand All @@ -209,25 +245,24 @@ void AcousticWaveEquationSEM::precomputeSourceAndReceiverTerm( MeshLevel & baseM
nodesToElements.freeOnDevice();
}

void AcousticWaveEquationSEM::addSourceToRightHandSide( real64 const & time_n, arrayView1d< real32 > const rhs )
void AcousticWaveEquationSEM::addSourceToRightHandSide( integer const & cycleNumber, arrayView1d< real32 > const rhs )
{
arrayView2d< localIndex const > const sourceNodeIds = m_sourceNodeIds.toViewConst();
arrayView2d< real64 const > const sourceConstants = m_sourceConstants.toViewConst();
arrayView1d< localIndex const > const sourceIsAccessible = m_sourceIsAccessible.toViewConst();
real32 const timeSourceFrequency = m_timeSourceFrequency;
real32 const timeSourceDelay = m_timeSourceDelay;
localIndex const rickerOrder = m_rickerOrder;
bool useSourceWaveletTables = m_useSourceWaveletTables;
arrayView1d< TableFunction::KernelWrapper const > const sourceWaveletTableWrappers = m_sourceWaveletTableWrappers.toViewConst();
arrayView2d< real32 const > const sourceValue = m_sourceValue.toViewConst();

GEOS_THROW_IF( cycleNumber > sourceValue.size( 0 ),
getDataContext() << ": Too many steps compared to array size",
std::runtime_error );
forAll< EXEC_POLICY >( sourceConstants.size( 0 ), [=] GEOS_HOST_DEVICE ( localIndex const isrc )
{
if( sourceIsAccessible[isrc] == 1 )
{
real64 const srcValue =
useSourceWaveletTables ? sourceWaveletTableWrappers[ isrc ].compute( &time_n ) : WaveSolverUtils::evaluateRicker( time_n, timeSourceFrequency, timeSourceDelay, rickerOrder );

for( localIndex inode = 0; inode < sourceConstants.size( 1 ); ++inode )
{
real32 const localIncrement = sourceConstants[isrc][inode] * srcValue;
real32 const localIncrement = sourceConstants[isrc][inode] * sourceValue[cycleNumber][isrc];
RAJA::atomicAdd< ATOMIC_POLICY >( &rhs[sourceNodeIds[isrc][inode]], localIncrement );
}
}
Expand All @@ -252,12 +287,10 @@ void AcousticWaveEquationSEM::initializePostInitialConditionsPreSubGroups()



forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const & meshBodyName,
forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &,
MeshLevel & mesh,
arrayView1d< string const > const & regionNames )
{
MeshLevel & baseMesh = domain.getMeshBodies().getGroup< MeshBody >( meshBodyName ).getBaseDiscretization();
precomputeSourceAndReceiverTerm( baseMesh, mesh, regionNames );

NodeManager & nodeManager = mesh.getNodeManager();
FaceManager & faceManager = mesh.getFaceManager();
Expand Down Expand Up @@ -338,6 +371,16 @@ void AcousticWaveEquationSEM::initializePostInitialConditionsPreSubGroups()
m_timeStep=dtOut;
}

forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const & meshBodyName,
MeshLevel & mesh,
arrayView1d< string const > const & regionNames )
{
GEOS_UNUSED_VAR( meshBodyName );
MeshLevel & baseMesh = domain.getMeshBodies().getGroup< MeshBody >( meshBodyName ).getBaseDiscretization();
precomputeSourceAndReceiverTerm( baseMesh, mesh, regionNames );

} );


WaveSolverUtils::initTrace( "seismoTraceReceiver", getName(), m_outputSeismoTrace, m_receiverConstants.size( 0 ), m_receiverIsLocal );
}
Expand Down Expand Up @@ -875,7 +918,7 @@ real64 AcousticWaveEquationSEM::explicitStepForward( real64 const & time_n,
DomainPartition & domain,
bool computeGradient )
{
real64 dtCompute = explicitStepInternal( time_n, dt, domain );
real64 dtCompute = explicitStepInternal( time_n, dt, cycleNumber, domain );

forDiscretizationOnMeshTargets( domain.getMeshBodies(),
[&] ( string const &,
Expand Down Expand Up @@ -946,7 +989,7 @@ real64 AcousticWaveEquationSEM::explicitStepBackward( real64 const & time_n,
DomainPartition & domain,
bool computeGradient )
{
real64 dtCompute = explicitStepInternal( time_n, dt, domain );
real64 dtCompute = explicitStepInternal( time_n, dt, cycleNumber, domain );
forDiscretizationOnMeshTargets( domain.getMeshBodies(),
[&] ( string const &,
MeshLevel & mesh,
Expand Down Expand Up @@ -1076,6 +1119,7 @@ void AcousticWaveEquationSEM::prepareNextTimestep( MeshLevel & mesh )

void AcousticWaveEquationSEM::computeUnknowns( real64 const & time_n,
real64 const & dt,
integer const & cycleNumber,
DomainPartition & domain,
MeshLevel & mesh,
arrayView1d< string const > const & regionNames )
Expand Down Expand Up @@ -1103,8 +1147,14 @@ void AcousticWaveEquationSEM::computeUnknowns( real64 const & time_n,
getDiscretizationName(),
"",
kernelFactory );

//Modification of cycleNember useful when minTime < 0
addSourceToRightHandSide( time_n, rhs );
EventManager const & event = getGroupByPath< EventManager >( "/Problem/Events" );
real64 const & minTime = event.getReference< real64 >( EventManager::viewKeyStruct::minTimeString() );
//localIndex const cycleNumber = time_n/dt;
integer const cycleForSource = int(round( -minTime / dt + cycleNumber ));

addSourceToRightHandSide( cycleForSource, rhs );

/// calculate your time integrators
real64 const dt2 = pow( dt, 2 );
Expand Down Expand Up @@ -1228,6 +1278,7 @@ void AcousticWaveEquationSEM::synchronizeUnknowns( real64 const & time_n,

real64 AcousticWaveEquationSEM::explicitStepInternal( real64 const & time_n,
real64 const & dt,
integer const & cycleNumber,
DomainPartition & domain )
{
GEOS_MARK_FUNCTION;
Expand All @@ -1241,7 +1292,7 @@ real64 AcousticWaveEquationSEM::explicitStepInternal( real64 const & time_n,
{
localIndex nSubSteps = (int) ceil( dt/m_timeStep );
dtCompute = dt/nSubSteps;
computeUnknowns( time_n, dtCompute, domain, mesh, regionNames );
computeUnknowns( time_n, dtCompute, cycleNumber, domain, mesh, regionNames );
synchronizeUnknowns( time_n, dtCompute, domain, mesh, regionNames );
} );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class AcousticWaveEquationSEM : public WaveSolverBase
* @param cycleNumber the cycle number/step number of evaluation of the source
* @param rhs the right hand side vector to be computed
*/
virtual void addSourceToRightHandSide( real64 const & time_n, arrayView1d< real32 > const rhs );
virtual void addSourceToRightHandSide( integer const & cycleNumber, arrayView1d< real32 > const rhs );


/**
Expand Down Expand Up @@ -123,10 +123,12 @@ class AcousticWaveEquationSEM : public WaveSolverBase
*/
real64 explicitStepInternal( real64 const & time_n,
real64 const & dt,
integer const & cycleNumber,
DomainPartition & domain );

void computeUnknowns( real64 const & time_n,
real64 const & dt,
integer const & cycleNumber,
DomainPartition & domain,
MeshLevel & mesh,
arrayView1d< string const > const & regionNames );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ void AcousticElasticWaveEquationSEM::initializePostInitialConditionsPreSubGroups

real64 AcousticElasticWaveEquationSEM::solverStep( real64 const & time_n,
real64 const & dt,
int const,
integer const cycleNumber,
DomainPartition & domain )
{
GEOS_MARK_FUNCTION;
Expand Down Expand Up @@ -174,7 +174,7 @@ real64 AcousticElasticWaveEquationSEM::solverStep( real64 const & time_n,

elasSolver->synchronizeUnknowns( time_n, dt, domain, mesh, m_elasRegions );

acousSolver->computeUnknowns( time_n, dt, domain, mesh, m_acousRegions );
acousSolver->computeUnknowns( time_n, dt, cycleNumber, domain, mesh, m_acousRegions );

forAll< EXEC_POLICY >( interfaceNodesSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const in )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,14 @@ struct PreComputeSourcesAndReceivers
arrayView2d< real64 const > const receiverCoordinates,
arrayView1d< localIndex > const receiverIsLocal,
arrayView2d< localIndex > const receiverNodeIds,
arrayView2d< real64 > const receiverConstants )
arrayView2d< real64 > const receiverConstants,
arrayView2d< real32 > const sourceValue,
real64 const dt,
real32 const timeSourceFrequency,
real32 const timeSourceDelay,
localIndex const rickerOrder,
arrayView1d< TableFunction::KernelWrapper const > const sourceWaveletTableWrappers,
bool useSourceWaveletTables )
{
constexpr localIndex numNodesPerElem = FE_TYPE::numNodes;

Expand Down Expand Up @@ -121,6 +128,20 @@ struct PreComputeSourcesAndReceivers
sourceNodeIds[isrc][a] = elemsToNodes( k, a );
sourceConstants[isrc][a] = Ntest[a];
}

for( localIndex cycle = 0; cycle < sourceValue.size( 0 ); ++cycle )
{
real64 const time_n = cycle * dt;
if( useSourceWaveletTables )
{
sourceValue[cycle][isrc]= sourceWaveletTableWrappers[ isrc ].compute( &time_n );
}
else
{
sourceValue[cycle][isrc] = WaveSolverUtils::evaluateRicker( cycle * dt, timeSourceFrequency, timeSourceDelay, rickerOrder );
}
}

}
}
} // end loop over all sources
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ WaveSolverBase::WaveSolverBase( const std::string & name,
setSizedFromParent( 0 ).
setDescription( "Coordinates (x,y,z) of the receivers" );

registerWrapper( viewKeyStruct::sourceValueString(), &m_sourceValue ).
setInputFlag( InputFlags::FALSE ).
setRestartFlags( RestartFlags::NO_WRITE ).
setSizedFromParent( 0 ).
setDescription( "Array which contains the value of the Ricker wavelets at each time-steps" );


registerWrapper( viewKeyStruct::timeSourceDelayString(), &m_timeSourceDelay ).
setInputFlag( InputFlags::OPTIONAL ).
setApplyDefaultValue( -1 ).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class WaveSolverBase : public PhysicsSolverBase
struct viewKeyStruct : PhysicsSolverBase::viewKeyStruct
{
static constexpr char const * sourceCoordinatesString() { return "sourceCoordinates"; }
static constexpr char const * sourceValueString() { return "sourceValue"; }

static constexpr char const * timeSourceFrequencyString() { return "timeSourceFrequency"; }
static constexpr char const * timeSourceDelayString() { return "timeSourceDelay"; }
Expand Down Expand Up @@ -254,6 +255,9 @@ class WaveSolverBase : public PhysicsSolverBase

localIndex getNumNodesPerElem();

/// Precomputed value of the source terms
array2d< real32 > m_sourceValue;

/// Coordinates of the sources in the mesh
array2d< real64 > m_sourceCoordinates;

Expand Down
Loading

0 comments on commit 0b8a7e2

Please sign in to comment.