GEOS
FieldSpecificationImpl.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONIMPL_HPP
21 #define GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONIMPL_HPP
22 
23 #include "FieldSpecification.hpp"
24 #include "common/DataTypes.hpp"
25 #include "common/TypeDispatch.hpp"
26 #include "dataRepository/Group.hpp"
30 #include "mesh/MeshObjectPath.hpp"
32 #include "common/GEOS_RAJA_Interface.hpp"
33 
34 namespace geos
35 {
36 class Function;
37 
38 
44 {
45 public:
46 
58  template< typename OBJECT_TYPE, typename BC_TYPE = FieldSpecification, typename LAMBDA >
59  static void apply( BC_TYPE const & fs, MeshLevel & mesh, LAMBDA && lambda );
60 
83  template< typename OBJECT_TYPE, typename BC_TYPE = FieldSpecification, typename LAMBDA >
84  static void apply( BC_TYPE const & fs,
85  MeshLevel & mesh,
86  LAMBDA && lambda,
87  real64 const & time,
88  string const & fieldName );
89 
101  template< typename FIELD_OP, typename POLICY, typename T, int N, int USD >
102  static void applyFieldValueKernel( FieldSpecification const & fs,
103  ArrayView< T, N, USD > const & field,
104  SortedArrayView< localIndex const > const & targetSet,
105  real64 const time,
106  dataRepository::Group & dataGroup );
107 
120  template< typename FIELD_OP, typename POLICY=parallelHostPolicy >
121  static void applyFieldValue( FieldSpecification const & fs,
122  SortedArrayView< localIndex const > const & targetSet,
123  real64 const time,
124  dataRepository::Group & dataGroup,
125  string const & fieldName );
126 
150  template< typename FIELD_OP, typename POLICY, typename T, int NDIM, int USD >
151  static void
153  SortedArrayView< localIndex const > const & targetSet,
154  real64 const time,
155  dataRepository::Group const & dataGroup,
156  arrayView1d< globalIndex const > const & dofMap,
157  globalIndex const dofRankOffset,
159  arrayView1d< real64 > const & rhs,
160  ArrayView< T const, NDIM, USD > const & fieldView );
161 
183  template< typename FIELD_OP, typename POLICY >
184  static void
186  SortedArrayView< localIndex const > const & targetSet,
187  real64 const time,
188  dataRepository::Group const & dataGroup,
189  string const & fieldName,
190  string const & dofMapName,
191  globalIndex const dofRankOffset,
193  arrayView1d< real64 > const & rhs );
194 
218  template< typename FIELD_OP, typename POLICY, typename LAMBDA >
219  static void
221  SortedArrayView< localIndex const > const & targetSet,
222  real64 const time,
223  dataRepository::Group const & dataGroup,
224  arrayView1d< globalIndex const > const & dofMap,
225  globalIndex const dofRankOffset,
227  arrayView1d< real64 > const & rhs,
228  LAMBDA && lambda );
229 
254  template< typename FIELD_OP, typename POLICY, typename LAMBDA >
255  static void
257  SortedArrayView< localIndex const > const & targetSet,
258  real64 const time,
259  real64 const dt,
260  dataRepository::Group const & dataGroup,
261  arrayView1d< globalIndex const > const & dofMap,
262  globalIndex const dofRankOffset,
264  arrayView1d< real64 > const & rhs,
265  LAMBDA && lambda );
266 
303  template< typename FIELD_OP, typename POLICY, typename LAMBDA >
304  static void
306  SortedArrayView< localIndex const > const & targetSet,
307  real64 const time,
308  real64 const dt,
309  dataRepository::Group const & dataGroup,
310  arrayView1d< globalIndex const > const & dofMap,
311  globalIndex const dofRankOffset,
313  arrayView1d< globalIndex > const & dof,
314  arrayView1d< real64 > const & rhsContribution,
315  LAMBDA && lambda );
316 
328  template< typename POLICY >
329  static void
331  SortedArrayView< localIndex const > const & targetSet,
332  arrayView1d< globalIndex const > const & dofMap,
334 };
335 
336 template< typename OBJECT_TYPE, typename BC_TYPE, typename LAMBDA >
337 void FieldSpecificationImpl::apply( BC_TYPE const & fs,
338  MeshLevel & mesh,
339  LAMBDA && lambda )
340 {
341  MeshObjectPath const & meshObjectPaths = fs.getMeshObjectPaths();
342  meshObjectPaths.forObjectsInPath< OBJECT_TYPE >( mesh,
343  [&] ( OBJECT_TYPE & object )
344  {
345  {
347  string_array setNames = fs.getSetNames();
348  for( auto & setName : setNames )
349  {
350  if( setGroup.hasWrapper( setName ) )
351  {
352  SortedArrayView< localIndex const > const & targetSet =
353  setGroup.getReference< SortedArray< localIndex > >( setName );
354  lambda( fs, setName, targetSet, object, fs.getFieldName() );
355  }
356  }
357  }
358  } );
359 }
360 
361 template< typename OBJECT_TYPE, typename BC_TYPE, typename LAMBDA >
362 void FieldSpecificationImpl::apply( BC_TYPE const & fs,
363  MeshLevel & mesh,
364  LAMBDA && lambda,
365  real64 const & time,
366  string const & fieldName )
367 {
368  integer const isInitialCondition = fs.initialCondition();
369  if( ( isInitialCondition && fieldName=="") || // this only use case for this line is in the unit test for field specification
370  ( !isInitialCondition && time >= fs.getStartTime()
371  && time < fs.getEndTime()
372  && fieldName == fs.getFieldName() ) )
373  {
374  FieldSpecificationImpl::apply< OBJECT_TYPE >( fs, mesh, std::forward< LAMBDA >( lambda ) );
375  }
376 }
377 
378 template< typename FIELD_OP, typename POLICY, typename T, int N, int USD >
379 void
382  ArrayView< T, N, USD > const & field,
383  SortedArrayView< localIndex const > const & targetSet,
384  real64 const time,
385  dataRepository::Group & dataGroup )
386 {
387  integer const component = fs.getComponent();
388  string const & functionName = fs.getFunctionName();
389  FunctionManager & functionManager = FunctionManager::getInstance();
390 
391  if( functionName.empty() )
392  {
393  real64 const value = fs.getScale();
394  forAll< POLICY >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const i )
395  {
396  localIndex const a = targetSet[ i ];
397  FIELD_OP::SpecifyFieldValue( field, a, component, value );
398  } );
399  }
400  else
401  {
402  FunctionBase const & function = [&]() -> FunctionBase const &
403  {
404  try
405  {
406  return functionManager.getGroup< FunctionBase >( functionName );
407  }
408  catch( std::exception const & e )
409  {
410  string const errorMsg = GEOS_FMT( "Error while reading {}:\n",
412  viewKeyStruct::
413  functionNameString() ) );
415  .addToMsg( errorMsg )
417  .getContextInfo()
418  .setPriority( 1 ) );
419  throw InputError( e, errorMsg );
420  }
421  }();
422 
423  if( function.isFunctionOfTime()==2 )
424  {
425  real64 const value = fs.getScale() * function.evaluate( &time );
426  forAll< POLICY >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const i )
427  {
428  localIndex const a = targetSet[ i ];
429  FIELD_OP::SpecifyFieldValue( field, a, component, value );
430  } );
431  }
432  else
433  {
434  real64_array result( static_cast< localIndex >( targetSet.size() ) );
435  function.evaluate( dataGroup, time, targetSet, result );
436  arrayView1d< real64 const > const & resultView = result.toViewConst();
437  real64 const scale = fs.getScale();
438  forAll< POLICY >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const i )
439  {
440  localIndex const a = targetSet[ i ];
441  FIELD_OP::SpecifyFieldValue( field, a, component, scale * resultView[i] );
442  } );
443  }
444  }
445 }
446 
447 template< typename FIELD_OP, typename POLICY >
448 void
451  SortedArrayView< localIndex const > const & targetSet,
452  real64 const time,
453  dataRepository::Group & dataGroup,
454  string const & fieldName )
455 {
456  dataRepository::WrapperBase & wrapper = dataGroup.getWrapperBase( fieldName );
457 
458  // This function is used in setting boundary/initial conditions on simulation fields.
459  // This is meaningful for 1/2/3D real arrays and sometimes 1D integer (indicator) arrays.
462 
463 
464  types::dispatch( FieldTypes{}, [&]( auto tupleOfTypes )
465  {
466  using ArrayType = camp::first< decltype( tupleOfTypes ) >;
467  auto & wrapperT = dataRepository::Wrapper< ArrayType >::cast( wrapper );
468  applyFieldValueKernel< FIELD_OP, POLICY >( fs,
469  wrapperT.reference().toView(),
470  targetSet,
471  time,
472  dataGroup );
473  }, wrapper );
474 }
475 
476 template< typename FIELD_OP, typename POLICY, typename T, int NDIM, int USD >
477 void
480  SortedArrayView< localIndex const > const & targetSet,
481  real64 const time,
482  dataRepository::Group const & dataGroup,
483  arrayView1d< globalIndex const > const & dofMap,
484  globalIndex const dofRankOffset,
486  arrayView1d< real64 > const & rhs,
487  ArrayView< T const, NDIM, USD > const & fieldView )
488 {
489  integer const component = fs.getComponent();
490  applyBoundaryConditionToSystem< FIELD_OP, POLICY >( fs,
491  targetSet,
492  time,
493  dataGroup,
494  dofMap,
495  dofRankOffset,
496  matrix,
497  rhs,
498  [fieldView, component] GEOS_HOST_DEVICE ( localIndex const a )
499  {
500  real64 value = 0.0;
501  FieldSpecificationEqual::readFieldValue( fieldView, a, component, value );
502  return value;
503  } );
504 }
505 
506 template< typename FIELD_OP, typename POLICY >
507 void
510  SortedArrayView< localIndex const > const & targetSet,
511  real64 const time,
512  dataRepository::Group const & dataGroup,
513  string const & fieldName,
514  string const & dofMapName,
515  globalIndex const dofRankOffset,
517  arrayView1d< real64 > const & rhs )
518 {
519  dataRepository::WrapperBase const & wrapper = dataGroup.getWrapperBase( fieldName );
520  arrayView1d< globalIndex const > const & dofMap = dataGroup.getReference< array1d< globalIndex > >( dofMapName );
521 
522  // We're reading values from a field, which is only well-defined for dims 1 and 2
524  types::dispatch( FieldTypes{}, [&]( auto tupleOfTypes )
525  {
526  using ArrayType = camp::first< decltype( tupleOfTypes ) >;
527  auto const & wrapperT = dataRepository::Wrapper< ArrayType >::cast( wrapper );
528  applyBoundaryConditionToSystemKernel< FIELD_OP, POLICY >( fs,
529  targetSet,
530  time,
531  dataGroup,
532  dofMap,
533  dofRankOffset,
534  matrix,
535  rhs,
536  wrapperT.reference() );
537  }, wrapper );
538 }
539 
540 template< typename FIELD_OP, typename POLICY, typename LAMBDA >
541 void
544  SortedArrayView< localIndex const > const & targetSet,
545  real64 const time,
546  dataRepository::Group const & dataGroup,
547  arrayView1d< globalIndex const > const & dofMap,
548  globalIndex const dofRankOffset,
550  arrayView1d< real64 > const & rhs,
551  LAMBDA && lambda )
552 {
553  return applyBoundaryConditionToSystem< FIELD_OP, POLICY >( fs,
554  targetSet,
555  time,
556  1.0,
557  dataGroup,
558  dofMap,
559  dofRankOffset,
560  matrix,
561  rhs,
562  std::forward< LAMBDA >( lambda ) );
563 }
564 
565 template< typename FIELD_OP, typename POLICY, typename LAMBDA >
566 void
569  SortedArrayView< localIndex const > const & targetSet,
570  real64 const time,
571  real64 const dt,
572  dataRepository::Group const & dataGroup,
573  arrayView1d< globalIndex const > const & dofMap,
574  globalIndex const dofRankOffset,
576  arrayView1d< real64 > const & rhs,
577  LAMBDA && lambda )
578 {
579  array1d< globalIndex > dofArray( targetSet.size() );
580  arrayView1d< globalIndex > const & dof = dofArray.toView();
581 
582  array1d< real64 > rhsContributionArray( targetSet.size() );
583  arrayView1d< real64 > const & rhsContribution = rhsContributionArray.toView();
584 
585  computeRhsContribution< FIELD_OP, POLICY, LAMBDA >( fs,
586  targetSet,
587  time,
588  dt,
589  dataGroup,
590  dofMap,
591  dofRankOffset,
592  matrix,
593  dof,
594  rhsContribution,
595  std::forward< LAMBDA >( lambda ) );
596 
597  FIELD_OP::template prescribeRhsValues< POLICY >( rhs, dof, dofRankOffset, rhsContribution );
598 }
599 
600 template< typename FIELD_OP, typename POLICY, typename LAMBDA >
601 void
604  SortedArrayView< localIndex const > const & targetSet,
605  real64 const time,
606  real64 const dt,
607  dataRepository::Group const & dataGroup,
608  arrayView1d< globalIndex const > const & dofMap,
609  globalIndex const dofRankOffset,
611  arrayView1d< globalIndex > const & dof,
612  arrayView1d< real64 > const & rhsContribution,
613  LAMBDA && lambda )
614 {
615  integer const component = ( fs.getComponent() >= 0 ) ? fs.getComponent() : 0;
616  string const & functionName = fs.getFunctionName();
617  FunctionManager & functionManager = FunctionManager::getInstance();
618 
619  // Compute the value of the rhs terms, and collect the dof numbers
620  // The rhs terms will be assembled in applyBoundaryConditionToSystem
621  // (or in the solver for CompositionalMultiphaseBase)
622 
623  if( functionName.empty() ||
624  functionManager.getGroup< FunctionBase >( functionName ).isFunctionOfTime() == 2 )
625  {
626  real64 value = fs.getScale() * dt;
627  if( !functionName.empty() )
628  {
629  FunctionBase const & function = functionManager.getGroup< FunctionBase >( functionName );
630  value *= function.evaluate( &time );
631  }
632 
633  forAll< POLICY >( targetSet.size(),
634  [targetSet,
635  dof,
636  dofMap,
637  dofRankOffset,
638  component,
639  matrix,
640  rhsContribution,
641  value,
642  lambda] GEOS_HOST_DEVICE ( localIndex const i )
643  {
644  localIndex const a = targetSet[ i ];
645  dof[ i ] = dofMap[ a ] + component;
646  FIELD_OP::SpecifyFieldValue( dof[ i ],
647  dofRankOffset,
648  matrix,
649  rhsContribution[ i ],
650  value,
651  lambda( a ) );
652  } );
653  }
654  else
655  {
656  FunctionBase const & function = functionManager.getGroup< FunctionBase >( functionName );
657 
658  real64_array resultsArray( targetSet.size() );
659  function.evaluate( dataGroup, time, targetSet, resultsArray );
660  arrayView1d< real64 const > const & results = resultsArray.toViewConst();
661  real64 const value = fs.getScale() * dt;
662 
663  forAll< POLICY >( targetSet.size(),
664  [targetSet,
665  dof,
666  dofMap,
667  dofRankOffset,
668  component,
669  matrix,
670  rhsContribution,
671  results,
672  value,
673  lambda] GEOS_HOST_DEVICE ( localIndex const i )
674  {
675  localIndex const a = targetSet[ i ];
676  dof[ i ] = dofMap[ a ] + component;
677  FIELD_OP::SpecifyFieldValue( dof[ i ],
678  dofRankOffset,
679  matrix,
680  rhsContribution[ i ],
681  value * results[ i ],
682  lambda( a ) );
683  } );
684  }
685 }
686 
687 template< typename POLICY >
688 void
691  SortedArrayView< localIndex const > const & targetSet,
692  arrayView1d< globalIndex const > const & dofMap,
694 {
695  integer const component = ( fs.getComponent() >= 0 ) ? fs.getComponent() : 0;
696  forAll< POLICY >( targetSet.size(),
697  [targetSet, dofMap, matrix, component] GEOS_HOST_DEVICE ( localIndex const i )
698  {
699  localIndex const a = targetSet[ i ];
700  globalIndex const dof = dofMap[ a ] + component;
701 
702  arraySlice1d< real64 > const entries = matrix.getEntries( dof );
703  localIndex const numEntries = matrix.numNonZeros( dof );
704 
705  for( localIndex j = 0; j < numEntries; ++j )
706  {
707  entries[ j ] = 0;
708  }
709  } );
710 }
711 
712 
713 } /* namespace geos */
714 
715 #endif //GEOS_FIELDSPECIFICATION_FIELDSPECIFICATIONIMPL_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
DiagnosticMsgBuilder & addContextInfo(Args &&... args)
Adds one or more context elements to the error.
DiagnosticMsgBuilder & addToMsg(std::exception const &e, bool toEnd=false)
Append exception text to the message.
DiagnosticMsgBuilder modifyCurrentExceptionMessage()
Modify/Continue building the current exception message.
static GEOS_HOST ErrorLogger & global()
string const & getFunctionName() const
virtual int getComponent() const
Methods to apply field specifications.
static void applyBoundaryConditionToSystemKernel(FieldSpecification const &fs, SortedArrayView< localIndex const > const &targetSet, real64 const time, dataRepository::Group const &dataGroup, arrayView1d< globalIndex const > const &dofMap, globalIndex const dofRankOffset, CRSMatrixView< real64, globalIndex const > const &matrix, arrayView1d< real64 > const &rhs, ArrayView< T const, NDIM, USD > const &fieldView)
Apply a boundary condition to a system of equations.
static void applyFieldValue(FieldSpecification const &fs, SortedArrayView< localIndex const > const &targetSet, real64 const time, dataRepository::Group &dataGroup, string const &fieldName)
static void apply(BC_TYPE const &fs, MeshLevel &mesh, LAMBDA &&lambda)
Apply this field specification to the discretization.
static void applyBoundaryConditionToSystem(FieldSpecification const &fs, SortedArrayView< localIndex const > const &targetSet, real64 const time, dataRepository::Group const &dataGroup, string const &fieldName, string const &dofMapName, globalIndex const dofRankOffset, CRSMatrixView< real64, globalIndex const > const &matrix, arrayView1d< real64 > const &rhs)
Apply a boundary condition to a system of equations.
static void computeRhsContribution(FieldSpecification const &fs, SortedArrayView< localIndex const > const &targetSet, real64 const time, real64 const dt, dataRepository::Group const &dataGroup, arrayView1d< globalIndex const > const &dofMap, globalIndex const dofRankOffset, CRSMatrixView< real64, globalIndex const > const &matrix, arrayView1d< globalIndex > const &dof, arrayView1d< real64 > const &rhsContribution, LAMBDA &&lambda)
Compute the contributions that will be added/enforced to the right-hand side, and collect the corresp...
static void applyFieldValueKernel(FieldSpecification const &fs, ArrayView< T, N, USD > const &field, SortedArrayView< localIndex const > const &targetSet, real64 const time, dataRepository::Group &dataGroup)
static void zeroSystemRowsForBoundaryCondition(FieldSpecification const &fs, SortedArrayView< localIndex const > const &targetSet, arrayView1d< globalIndex const > const &dofMap, CRSMatrixView< real64, globalIndex const > const &matrix)
Function to zero matrix rows to apply boundary conditions.
integer isFunctionOfTime() const
Test to see if the function is a 1D function of time.
static FunctionManager & getInstance()
Class facilitating the representation of a multi-level discretization of a MeshBody.
Definition: MeshLevel.hpp:42
Class to hold the path to a collection of mesh objects.
void forObjectsInPath(dataRepository::Group &meshBodies, FUNC &&func) const
LLoop over objects in the path and execute a callback function.
virtual ErrorContext getContextInfo() const =0
Returns contextual information, including the file name and the line number.
bool hasWrapper(LOOKUP_TYPE const &lookup) const
Check if a wrapper exists.
Definition: Group.hpp:1202
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
Definition: Group.hpp:1273
WrapperBase const & getWrapperBase(KEY const &key) const
Return a reference to a WrapperBase stored in this group.
Definition: Group.hpp:1123
T & getGroup(KEY const &key)
Return a reference to a sub-group of the current Group.
Definition: Group.hpp:318
DataContext const & getWrapperDataContext(KEY key) const
Definition: Group.hpp:1354
Base class for all wrappers containing common operations.
Definition: WrapperBase.hpp:56
static Wrapper & cast(WrapperBase &wrapper)
Downcast base to a typed wrapper.
Definition: Wrapper.hpp:221
internal::Apply< internal::ArrayType, camp::cartesian_product< TYPES, internal::AddLayouts< NDIMS > > > ArrayTypes
Construct a list of GEOSX multidimensional array types (geos::Array), containing all value types in t...
DimsRange< N, N > DimsSingle
Generate a list of types representing array dimensionality exactly N.
bool dispatch(LIST const combinations, LAMBDA &&lambda, Ts &&... objects)
Dispatch a generic worker function lambda based on runtime type.
internal::Apply< camp::list, LIST > ListofTypeList
Construct a list of list type.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
stdVector< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:361
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
double real64
64-bit floating point type.
Definition: DataTypes.hpp:98
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:84
ArraySlice< T, 1, USD > arraySlice1d
Alias for 1D array slice.
Definition: DataTypes.hpp:183
LvArray::CRSMatrixView< T, COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:309
array1d< real64 > real64_array
A 1-dimensional array of geos::real64 types.
Definition: DataTypes.hpp:357
LvArray::SortedArray< T, localIndex, LvArray::ChaiBuffer > SortedArray
A sorted array of local indices.
Definition: DataTypes.hpp:266
LvArray::SortedArrayView< T, localIndex, LvArray::ChaiBuffer > SortedArrayView
A sorted array view of local indices.
Definition: DataTypes.hpp:270
int integer
Signed integer type.
Definition: DataTypes.hpp:81
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:175
LvArray::ArrayView< T, NDIM, USD, localIndex, LvArray::ChaiBuffer > ArrayView
Multidimensional array view type. See LvArray:ArrayView for details.
Definition: DataTypes.hpp:147
ErrorContext & setPriority(integer priority)
Set the priority value of the current error context information. This way the different context infor...
constexpr static char const * functionNameString()
static GEOS_HOST_DEVICE std::enable_if< !traits::is_tensorT< T >, void >::type readFieldValue(arrayView1d< T const > const &field, localIndex const index, integer const component, real64 &value)
Read a field value.
Exception class used to report errors in user input.
static constexpr char const * setsString()