Skip to content

Commit 82aea9d

Browse files
authored
feat: well time step selector based on rates/bhp tables and clarify well rates logic (#3427)
1 parent 3372c8f commit 82aea9d

31 files changed

+488
-183
lines changed

.integrated_tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
baselines:
22
bucket: geosx
3-
baseline: integratedTests/baseline_integratedTests-pr3485-10612-832f30e
3+
baseline: integratedTests/baseline_integratedTests-pr3427-10674-34d1de8
44

55
allow_fail:
66
all: ''

BASELINE_NOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines.
66
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.
77
These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD).
88

9+
PR #3427 (2024-03-10)
10+
=====================
11+
Well time step selector based on rates/bhp tables and clarify well rates logic.
12+
913
PR #3485 (2024-03-09)
1014
=====================
1115
Use mass and energy consistently for single phase solvers.

src/coreComponents/codingUtilities/Utilities.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ bool isZero( T const val, T const tol = LvArray::NumericLimits< T >::epsilon )
5959
return -tol <= val && val <= tol;
6060
}
6161

62+
template< typename ARRAY_TYPE >
63+
GEOS_FORCE_INLINE GEOS_HOST_DEVICE
64+
bool hasNonZero( ARRAY_TYPE const & array )
65+
{
66+
for( auto it = array.begin(); it != array.end() ; ++it )
67+
{
68+
if( !isZero( *it ) )
69+
{
70+
return true;
71+
}
72+
}
73+
return false;
74+
}
75+
6276
template< typename T >
6377
GEOS_FORCE_INLINE GEOS_HOST_DEVICE constexpr
6478
bool isOdd( T x )

src/coreComponents/functions/TableFunction.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,15 @@ real64 TableFunction::evaluate( real64 const * const input ) const
196196
return m_kernelWrapper.compute( input );
197197
}
198198

199+
real64 TableFunction::getCoord( real64 const * const input, localIndex const dim, InterpolationType interpolationMethod ) const
200+
{
201+
GEOS_ASSERT_MSG( interpolationMethod != InterpolationType::Linear,
202+
GEOS_FMT( "{}: TableFunction::getCoord should not be called with {} interpolation method",
203+
getDataContext(), EnumStrings< InterpolationType >::toString( interpolationMethod )));
204+
GEOS_ASSERT( dim >= 0 && dim < m_coordinates.size() );
205+
return m_kernelWrapper.getCoord( input, dim, interpolationMethod );
206+
}
207+
199208
TableFunction::KernelWrapper::KernelWrapper( InterpolationType const interpolationMethod,
200209
ArrayOfArraysView< real64 const > const & coordinates,
201210
arrayView1d< real64 const > const & values )

src/coreComponents/functions/TableFunction.hpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ class TableFunction : public FunctionBase
173173
real64
174174
interpolateRound( IN_ARRAY const & input ) const;
175175

176+
/**
177+
* @brief Method to get coordinates
178+
* @param input a scalar input
179+
* @param dim the table dimension
180+
* @param interpolationMethod the interpolation method
181+
* @return the coordinate
182+
*/
183+
template< typename IN_ARRAY >
184+
GEOS_HOST_DEVICE
185+
real64
186+
getCoord( IN_ARRAY const & input, localIndex dim, InterpolationType interpolationMethod ) const;
187+
176188
/**
177189
* @brief Interpolate in the table with derivatives using linear method.
178190
* @param[in] input vector of input value
@@ -240,6 +252,15 @@ class TableFunction : public FunctionBase
240252
*/
241253
virtual real64 evaluate( real64 const * const input ) const override final;
242254

255+
/**
256+
* @brief Method to get coordinates
257+
* @param input a scalar input
258+
* @param dim the table dimension
259+
* @param interpolationMethod the interpolation method
260+
* @return the coordinate
261+
*/
262+
real64 getCoord( real64 const * const input, localIndex dim, InterpolationType interpolationMethod ) const;
263+
243264
/**
244265
* @brief Check if the given coordinate is in the bounds of the table coordinates in the
245266
* specified dimension, throw an exception otherwise.
@@ -554,6 +575,57 @@ TableFunction::KernelWrapper::interpolateRound( IN_ARRAY const & input ) const
554575
return m_values[tableIndex];
555576
}
556577

578+
template< typename IN_ARRAY >
579+
GEOS_HOST_DEVICE
580+
GEOS_FORCE_INLINE
581+
real64
582+
TableFunction::KernelWrapper::getCoord( IN_ARRAY const & input, localIndex const dim, InterpolationType interpolationMethod ) const
583+
{
584+
// Determine the index to the nearest table entry
585+
localIndex subIndex;
586+
arraySlice1d< real64 const > const coords = m_coordinates[dim];
587+
// Determine the index along each table axis
588+
if( input[dim] <= coords[0] )
589+
{
590+
// Coordinate is to the left of the table axis
591+
subIndex = 0;
592+
}
593+
else if( input[dim] >= coords[coords.size() - 1] )
594+
{
595+
// Coordinate is to the right of the table axis
596+
subIndex = coords.size() - 1;
597+
}
598+
else
599+
{
600+
// Coordinate is within the table axis
601+
// Note: find() will return the index of the upper table vertex
602+
auto const lower = LvArray::sortedArrayManipulation::find( coords.begin(), coords.size(), input[dim] );
603+
subIndex = LvArray::integerConversion< localIndex >( lower );
604+
605+
// Interpolation types:
606+
// - Nearest returns the value of the closest table vertex
607+
// - Upper returns the value of the next table vertex
608+
// - Lower returns the value of the previous table vertex
609+
if( interpolationMethod == TableFunction::InterpolationType::Nearest )
610+
{
611+
if( ( input[dim] - coords[subIndex - 1]) <= ( coords[subIndex] - input[dim]) )
612+
{
613+
--subIndex;
614+
}
615+
}
616+
else if( interpolationMethod == TableFunction::InterpolationType::Lower )
617+
{
618+
if( subIndex > 0 )
619+
{
620+
--subIndex;
621+
}
622+
}
623+
}
624+
625+
// Retrieve the nearest coordinate
626+
return coords[subIndex];
627+
}
628+
557629
template< typename IN_ARRAY, typename OUT_ARRAY >
558630
GEOS_HOST_DEVICE
559631
GEOS_FORCE_INLINE

src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ bool PhysicsSolverBase::execute( real64 const time_n,
303303

304304
if( dtRemaining > 0.0 )
305305
{
306-
nextDt = setNextDt( dtAccepted, domain );
306+
nextDt = setNextDt( time_n + (dt - dtRemaining), dtAccepted, domain );
307307
if( nextDt < dtRemaining )
308308
{
309309
// better to do two equal steps than one big and one small (even potentially tiny)
@@ -333,7 +333,7 @@ bool PhysicsSolverBase::execute( real64 const time_n,
333333
" reached. Consider increasing maxSubSteps." );
334334

335335
// Decide what to do with the next Dt for the event running the solver.
336-
m_nextDt = setNextDt( nextDt, domain );
336+
m_nextDt = setNextDt( time_n + dt, nextDt, domain );
337337

338338
// Increase counter to indicate how many cycles since the last timestep cut
339339
if( m_numTimestepsSinceLastDtCut >= 0 )
@@ -364,15 +364,16 @@ void PhysicsSolverBase::logEndOfCycleInformation( integer const cycleNumber,
364364
GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, "------------------------------------------------------------------\n" );
365365
}
366366

367-
real64 PhysicsSolverBase::setNextDt( real64 const & currentDt,
367+
real64 PhysicsSolverBase::setNextDt( real64 const & GEOS_UNUSED_PARAM( currentTime ),
368+
real64 const & currentDt,
368369
DomainPartition & domain )
369370
{
370371
integer const minTimeStepIncreaseInterval = m_nonlinearSolverParameters.minTimeStepIncreaseInterval();
371-
real64 const nextDtNewton = setNextDtBasedOnNewtonIter( currentDt );
372-
if( m_nonlinearSolverParameters.getLogLevel() > 0 )
373-
GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on Newton iterations = {}", getName(), nextDtNewton ));
372+
real64 const nextDtIter = setNextDtBasedOnIterNumber( currentDt );
373+
if( m_nonlinearSolverParameters.getLogLevel() > 0 && nextDtIter < LvArray::NumericLimits< real64 >::max )
374+
GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on number of iterations = {}", getName(), nextDtIter ));
374375
real64 const nextDtStateChange = setNextDtBasedOnStateChange( currentDt, domain );
375-
if( m_nonlinearSolverParameters.getLogLevel() > 0 )
376+
if( m_nonlinearSolverParameters.getLogLevel() > 0 && nextDtStateChange < LvArray::NumericLimits< real64 >::max )
376377
GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on state change = {}", getName(), nextDtStateChange ));
377378

378379
if( ( m_numTimestepsSinceLastDtCut >= 0 ) && ( m_numTimestepsSinceLastDtCut < minTimeStepIncreaseInterval ) )
@@ -382,14 +383,14 @@ real64 PhysicsSolverBase::setNextDt( real64 const & currentDt,
382383
return currentDt;
383384
}
384385

385-
if( nextDtNewton < nextDtStateChange ) // time step size decided based on convergence
386+
if( nextDtIter < nextDtStateChange ) // time step size decided based on convergence
386387
{
387-
if( nextDtNewton > currentDt )
388+
if( nextDtIter > currentDt )
388389
{
389390
GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: time-step required will be increased based on number of iterations.",
390391
getName() ) );
391392
}
392-
else if( nextDtNewton < currentDt )
393+
else if( nextDtIter < currentDt )
393394
{
394395
GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: time-step required will be decreased based on number of iterations.",
395396
getName() ) );
@@ -419,7 +420,7 @@ real64 PhysicsSolverBase::setNextDt( real64 const & currentDt,
419420
}
420421
}
421422

422-
return std::min( nextDtNewton, nextDtStateChange );
423+
return std::min( nextDtIter, nextDtStateChange );
423424
}
424425

425426
real64 PhysicsSolverBase::setNextDtBasedOnStateChange( real64 const & currentDt,
@@ -429,7 +430,7 @@ real64 PhysicsSolverBase::setNextDtBasedOnStateChange( real64 const & currentDt,
429430
return LvArray::NumericLimits< real64 >::max; // i.e., not implemented
430431
}
431432

432-
real64 PhysicsSolverBase::setNextDtBasedOnNewtonIter( real64 const & currentDt )
433+
real64 PhysicsSolverBase::setNextDtBasedOnIterNumber( real64 const & currentDt )
433434
{
434435
integer & newtonIter = m_nonlinearSolverParameters.m_numNewtonIterations;
435436
integer const iterDecreaseLimit = m_nonlinearSolverParameters.timeStepDecreaseIterLimit();

src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,19 +216,21 @@ class PhysicsSolverBase : public ExecutableGroup
216216

217217
/**
218218
* @brief function to set the next time step size
219+
* @param[in] currentTime the current time
219220
* @param[in] currentDt the current time step size
220221
* @param[in] domain the domain object
221222
* @return the prescribed time step size
222223
*/
223-
virtual real64 setNextDt( real64 const & currentDt,
224+
virtual real64 setNextDt( real64 const & currentTime,
225+
real64 const & currentDt,
224226
DomainPartition & domain );
225227

226228
/**
227-
* @brief function to set the next time step size based on Newton convergence
229+
* @brief function to set the next time step size based on convergence
228230
* @param[in] currentDt the current time step size
229231
* @return the prescribed time step size
230232
*/
231-
virtual real64 setNextDtBasedOnNewtonIter( real64 const & currentDt );
233+
virtual real64 setNextDtBasedOnIterNumber( real64 const & currentDt );
232234

233235
/**
234236
* @brief function to set the next dt based on state change

src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,10 +1554,12 @@ void CompositionalMultiphaseFVM::assembleHydrofracFluxTerms( real64 const GEOS_U
15541554
} );
15551555
}
15561556

1557-
real64 CompositionalMultiphaseFVM::setNextDt( const geos::real64 & currentDt, geos::DomainPartition & domain )
1557+
real64 CompositionalMultiphaseFVM::setNextDt( real64 const & currentTime,
1558+
real64 const & currentDt,
1559+
DomainPartition & domain )
15581560
{
15591561
if( m_targetFlowCFL < 0 )
1560-
return CompositionalMultiphaseBase::setNextDt( currentDt, domain );
1562+
return CompositionalMultiphaseBase::setNextDt( currentTime, currentDt, domain );
15611563
else
15621564
return setNextDtBasedOnCFL( currentDt, domain );
15631565
}

src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,13 @@ class CompositionalMultiphaseFVM : public CompositionalMultiphaseBase
195195

196196
/**
197197
* @brief function to set the next time step size
198+
* @param[in] currentTime the current time
198199
* @param[in] currentDt the current time step size
199200
* @param[in] domain the domain object
200201
* @return the prescribed time step size
201202
*/
202-
real64 setNextDt( real64 const & currentDt,
203+
real64 setNextDt( real64 const & currentTime,
204+
real64 const & currentDt,
203205
DomainPartition & domain ) override;
204206

205207
struct viewKeyStruct : CompositionalMultiphaseBase::viewKeyStruct

0 commit comments

Comments
 (0)