GEOS
KernelBase.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 
16 
21 #ifndef GEOS_FINITEELEMENT_KERNELBASE_HPP_
22 #define GEOS_FINITEELEMENT_KERNELBASE_HPP_
23 
24 #include "common/DataTypes.hpp"
25 #include "common/TimingMacros.hpp"
26 #include "constitutive/ConstitutivePassThru.hpp"
27 #include "finiteElement/FiniteElementDispatch.hpp"
28 #include "mesh/MeshLevel.hpp"
29 #include "common/GEOS_RAJA_Interface.hpp"
30 #include "common/TypeDispatch.hpp"
31 
36 #ifndef SELECTED_FE_TYPES
37 #define SELECTED_FE_TYPES BASE_FE_TYPES
38 #endif
39 
40 namespace geos
41 {
42 
46 namespace finiteElement
47 {
48 
82 template< typename SUBREGION_TYPE,
83  typename CONSTITUTIVE_TYPE,
84  typename FE_TYPE,
85  int NUM_DOF_PER_TEST_SP,
86  int NUM_DOF_PER_TRIAL_SP >
88 {
89 public:
92  static constexpr int maxNumTestSupportPointsPerElem = FE_TYPE::maxSupportPoints;
93 
96  static constexpr int maxNumTrialSupportPointsPerElem = FE_TYPE::maxSupportPoints;
97 
100  static constexpr int numDofPerTestSupportPoint = NUM_DOF_PER_TEST_SP;
101 
104  static constexpr int numDofPerTrialSupportPoint = NUM_DOF_PER_TRIAL_SP;
105 
107  static constexpr int numQuadraturePointsPerElem = FE_TYPE::numQuadraturePoints;
108 
117  KernelBase( SUBREGION_TYPE const & elementSubRegion,
118  FE_TYPE const & finiteElementSpace,
119  CONSTITUTIVE_TYPE & inputConstitutiveType ):
120  m_elemsToNodes( elementSubRegion.nodeList().toViewConst() ),
121  m_elemGhostRank( elementSubRegion.ghostRank() ),
122  m_constitutiveUpdate( inputConstitutiveType.createKernelUpdates() ),
123  m_finiteElementSpace( finiteElementSpace )
124  {}
125 
138  {};
139 
154  inline
155  void setup( localIndex const k,
156  StackVariables & stack ) const
157  {
158  GEOS_UNUSED_VAR( k );
159  GEOS_UNUSED_VAR( stack );
160  }
161 
181  localIndex const q,
182  StackVariables & stack ) const
183  {
184  GEOS_UNUSED_VAR( k );
185  GEOS_UNUSED_VAR( q );
186  GEOS_UNUSED_VAR( stack );
187  }
188 
204  inline
206  StackVariables & stack ) const
207  {
208  GEOS_UNUSED_VAR( k );
209  GEOS_UNUSED_VAR( stack );
210  return 0;
211  }
212 
213 
226  //START_kernelLauncher
227  template< typename POLICY,
228  typename KERNEL_TYPE >
229  static
230  real64
231  kernelLaunch( localIndex const numElems,
232  KERNEL_TYPE const & kernelComponent )
233  {
235 
236  // Define a RAJA reduction variable to get the maximum residual contribution.
237  RAJA::ReduceMax< ReducePolicy< POLICY >, real64 > maxResidual( 0 );
238 
239  forAll< POLICY >( numElems,
240  [=] GEOS_HOST_DEVICE ( localIndex const k )
241  {
242  typename KERNEL_TYPE::StackVariables stack;
243 
244  kernelComponent.setup( k, stack );
245  // #pragma unroll
246  for( integer q=0; q<numQuadraturePointsPerElem; ++q )
247  {
248  kernelComponent.quadraturePointKernel( k, q, stack );
249  }
250  maxResidual.max( kernelComponent.complete( k, stack ) );
251  } );
252  return maxResidual.get();
253  }
254  //END_kernelLauncher
255 
256 protected:
258  traits::ViewTypeConst< typename SUBREGION_TYPE::NodeMapType::base_type > const m_elemsToNodes;
259 
262 
265  typename CONSTITUTIVE_TYPE::KernelWrapper const m_constitutiveUpdate;
266 
269  FE_TYPE const m_finiteElementSpace;
270 };
271 
278 template< template< typename SUBREGION_TYPE,
279  typename CONSTITUTIVE_TYPE,
280  typename FE_TYPE > class KERNEL_TYPE,
281  typename ... ARGS >
283 {
284 public:
285 
290  KernelFactory( ARGS ... args ):
291  m_args( args ... )
292  {}
293 
308  template< typename SUBREGION_TYPE, typename CONSTITUTIVE_TYPE, typename FE_TYPE >
309  KERNEL_TYPE< SUBREGION_TYPE, CONSTITUTIVE_TYPE, FE_TYPE > createKernel(
310  NodeManager & nodeManager,
311  EdgeManager const & edgeManager,
312  FaceManager const & faceManager,
313  localIndex const targetRegionIndex,
314  SUBREGION_TYPE const & elementSubRegion,
315  FE_TYPE const & finiteElementSpace,
316  CONSTITUTIVE_TYPE & inputConstitutiveType )
317  {
318  camp::tuple< NodeManager &,
319  EdgeManager const &,
320  FaceManager const &,
321  localIndex const,
322  SUBREGION_TYPE const &,
323  FE_TYPE const &,
324  CONSTITUTIVE_TYPE & > standardArgs { nodeManager,
325  edgeManager,
326  faceManager,
327  targetRegionIndex,
328  elementSubRegion,
329  finiteElementSpace,
330  inputConstitutiveType };
331 
332  auto allArgs = camp::tuple_cat_pair( standardArgs, m_args );
333  return camp::make_from_tuple< KERNEL_TYPE< SUBREGION_TYPE, CONSTITUTIVE_TYPE, FE_TYPE > >( allArgs );
334  }
335 
336 private:
338  camp::tuple< ARGS ... > m_args;
339 };
340 
341 
342 //*****************************************************************************
343 //*****************************************************************************
344 //*****************************************************************************
345 
346 //START_regionBasedKernelApplication
368 template< typename POLICY,
369  typename CONSTITUTIVE_BASE,
370  typename SUBREGION_TYPE,
371  typename KERNEL_FACTORY >
372 static
374  string_array const & targetRegions,
375  string const & finiteElementName,
376  string const & constitutiveStringName,
377  KERNEL_FACTORY & kernelFactory )
378 {
380  // save the maximum residual contribution for scaling residuals for convergence criteria.
381  real64 maxResidualContribution = 0;
382 
383  NodeManager & nodeManager = mesh.getNodeManager();
384  EdgeManager & edgeManager = mesh.getEdgeManager();
385  FaceManager & faceManager = mesh.getFaceManager();
386  ElementRegionManager & elementRegionManager = mesh.getElemManager();
387 
388  // Loop over all sub-regions in regions of type SUBREGION_TYPE, that are listed in the targetRegions array.
389  elementRegionManager.forElementSubRegions< SUBREGION_TYPE >( targetRegions,
390  [&constitutiveStringName,
391  &maxResidualContribution,
392  &nodeManager,
393  &edgeManager,
394  &faceManager,
395  &kernelFactory,
396  &finiteElementName]
397  ( localIndex const targetRegionIndex, auto & elementSubRegion )
398  {
399  localIndex const numElems = elementSubRegion.size();
400 
401  // Get the constitutive model...and allocate a null constitutive model if required.
402 
403  constitutive::ConstitutiveBase * constitutiveRelation = nullptr;
404  constitutive::NullModel * nullConstitutiveModel = nullptr;
405  if( elementSubRegion.template hasWrapper< string >( constitutiveStringName ) )
406  {
407  string const & constitutiveName = elementSubRegion.template getReference< string >( constitutiveStringName );
408  constitutiveRelation = &elementSubRegion.getConstitutiveModel( constitutiveName );
409  }
410  else
411  {
412  nullConstitutiveModel = &elementSubRegion.template registerGroup< constitutive::NullModel >( "nullModelGroup" );
413  constitutiveRelation = nullConstitutiveModel;
414  }
415 
416  // Call the constitutive dispatch which converts the type of constitutive model into a compile time constant.
417  constitutive::ConstitutivePassThru< CONSTITUTIVE_BASE >::execute( *constitutiveRelation,
418  [&maxResidualContribution,
419  &nodeManager,
420  &edgeManager,
421  &faceManager,
422  targetRegionIndex,
423  &kernelFactory,
424  &elementSubRegion,
425  &finiteElementName,
426  numElems]
427  ( auto & castedConstitutiveRelation )
428  {
430  subRegionFE = elementSubRegion.template getReference< FiniteElementBase >( finiteElementName );
431 
432  finiteElement::FiniteElementDispatchHandler< SELECTED_FE_TYPES >::dispatch3D( subRegionFE,
433  [&maxResidualContribution,
434  &nodeManager,
435  &edgeManager,
436  &faceManager,
437  targetRegionIndex,
438  &kernelFactory,
439  &elementSubRegion,
440  numElems,
441  &castedConstitutiveRelation] ( auto const finiteElement )
442  {
443  auto kernel = kernelFactory.createKernel( nodeManager,
444  edgeManager,
445  faceManager,
446  targetRegionIndex,
447  elementSubRegion,
449  castedConstitutiveRelation );
450 
451  using KERNEL_TYPE = decltype( kernel );
452 
453  // Call the kernelLaunch function, and store the maximum contribution to the residual.
454  maxResidualContribution =
455  std::max( maxResidualContribution,
456  KERNEL_TYPE::template kernelLaunch< POLICY, KERNEL_TYPE >( numElems, kernel ) );
457  } );
458  } );
459 
460  // Remove the null constitutive model (not required, but cleaner)
461  if( nullConstitutiveModel )
462  {
463  elementSubRegion.deregisterGroup( "nullModelGroup" );
464  }
465 
466  } );
467 
468  return maxResidualContribution;
469 }
470 
489 template< typename POLICY,
490  typename DISPATCH_TYPE_LIST,
491  typename KERNEL_FACTORY >
492 static
494  string_array const & targetRegions,
495  string const & finiteElementName,
496  string const & constitutiveStringName,
497  KERNEL_FACTORY & kernelFactory )
498 {
500  // save the maximum residual contribution for scaling residuals for convergence criteria.
501  real64 maxResidualContribution = 0;
502 
503  NodeManager & nodeManager = mesh.getNodeManager();
504  EdgeManager & edgeManager = mesh.getEdgeManager();
505  FaceManager & faceManager = mesh.getFaceManager();
506  ElementRegionManager & elementRegionManager = mesh.getElemManager();
507 
508  // Currently only CellElementSubRegion is supported.
509  using SUBREGION_TYPES = types::TypeList< CellElementSubRegion >;
510 
511  // Loop over all sub-regions in regions of type SUBREGION_TYPE, that are listed in the targetRegions array.
512  elementRegionManager.forElementSubRegions( SUBREGION_TYPES{}, targetRegions,
513  [&constitutiveStringName,
514  &maxResidualContribution,
515  &nodeManager,
516  &edgeManager,
517  &faceManager,
518  &kernelFactory,
519  &finiteElementName]
520  ( localIndex const targetRegionIndex, ElementSubRegionBase & elementSubRegion )
521  {
522  localIndex const numElems = elementSubRegion.size();
523 
524  // Get the constitutive model...and allocate a null constitutive model if required.
525  constitutive::ConstitutiveBase * constitutiveRelation = nullptr;
526  constitutive::NullModel * nullConstitutiveModel = nullptr;
527  if( elementSubRegion.template hasWrapper< string >( constitutiveStringName ) )
528  {
529  string const & constitutiveName = elementSubRegion.template getReference< string >( constitutiveStringName );
530  constitutiveRelation = &elementSubRegion.template getConstitutiveModel< >( constitutiveName );
531  }
532  else
533  {
534  nullConstitutiveModel = &elementSubRegion.template registerGroup< constitutive::NullModel >( "nullModelGroup" );
535  constitutiveRelation = nullConstitutiveModel;
536  }
537 
538  FiniteElementBase & subRegionFE = elementSubRegion.template getReference< FiniteElementBase >( finiteElementName );
539 
540  auto kernelLaunch = [&]( auto typeCombination )
541  {
542  using SUBREGION_TYPE = camp::at_v< decltype( typeCombination ), 0 >;
543  using CONSTITUTIVE_TYPE = camp::at_v< decltype( typeCombination ), 1 >;
544  using FE_TYPE = camp::at_v< decltype( typeCombination ), 2 >;
545 
546  SUBREGION_TYPE & castedSubRegion = dynamicCast< SUBREGION_TYPE & >( elementSubRegion );
547  CONSTITUTIVE_TYPE & castedConstitutiveRelation = dynamicCast< CONSTITUTIVE_TYPE & >( *constitutiveRelation );
548  FE_TYPE & castedFiniteElement = dynamicCast< FE_TYPE & >( subRegionFE );
549 
550  auto kernel = kernelFactory.createKernel( nodeManager,
551  edgeManager,
552  faceManager,
553  targetRegionIndex,
554  castedSubRegion,
555  castedFiniteElement,
556  castedConstitutiveRelation );
557 
558  using KERNEL_TYPE = decltype( kernel );
559 
560  // Call the kernelLaunch function, and store the maximum contribution to the residual.
561  maxResidualContribution =
562  std::max( maxResidualContribution,
563  KERNEL_TYPE::template kernelLaunch< POLICY, KERNEL_TYPE >( numElems, kernel ) );
564  };
565 
566  types::dispatch( DISPATCH_TYPE_LIST{}, kernelLaunch, elementSubRegion, *constitutiveRelation, subRegionFE );
567 
568  // Remove the null constitutive model (not required, but cleaner)
569  if( nullConstitutiveModel )
570  {
571  elementSubRegion.deregisterGroup( "nullModelGroup" );
572  }
573 
574  } );
575 
576  return maxResidualContribution;
577 }
578 //END_regionBasedKernelApplication
579 
580 } // namespace finiteElement
581 } // namespace geos
582 
583 
584 
585 #endif /* GEOS_FINITEELEMENT_KERNELBASE_HPP_ */
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:84
#define GEOS_FORCE_INLINE
Marks a function or lambda for inlining.
Definition: GeosxMacros.hpp:51
static real64 regionBasedKernelApplication(MeshLevel &mesh, string_array const &targetRegions, string const &finiteElementName, string const &constitutiveStringName, KERNEL_FACTORY &kernelFactory)
Performs a loop over specific regions (by type and name) and calls a kernel launch on the subregions ...
Definition: KernelBase.hpp:373
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
This class provides an interface to ObjectManagerBase in order to manage edge data.
Definition: EdgeManager.hpp:43
The ElementRegionManager class provides an interface to ObjectManagerBase in order to manage ElementR...
void forElementSubRegions(LAMBDA &&lambda)
This function is used to launch kernel function over the element subregions of all the subregion type...
The FaceManager class provides an interface to ObjectManagerBase in order to manage face data.
Definition: FaceManager.hpp:44
Class facilitating the representation of a multi-level discretization of a MeshBody.
Definition: MeshLevel.hpp:42
NodeManager const & getNodeManager() const
Get the node manager.
Definition: MeshLevel.hpp:155
FaceManager const & getFaceManager() const
Get the face manager.
Definition: MeshLevel.hpp:194
ElementRegionManager const & getElemManager() const
Get the element region manager.
Definition: MeshLevel.hpp:207
EdgeManager const & getEdgeManager() const
Get the edge manager.
Definition: MeshLevel.hpp:181
The NodeManager class provides an interface to ObjectManagerBase in order to manage node data.
Definition: NodeManager.hpp:46
Base class for FEM element implementations.
Define the base interface for finite element kernels.
Definition: KernelBase.hpp:88
traits::ViewTypeConst< typename SUBREGION_TYPE::NodeMapType::base_type > const m_elemsToNodes
The element to nodes map.
Definition: KernelBase.hpp:258
GEOS_HOST_DEVICE void setup(localIndex const k, StackVariables &stack) const
Performs the setup phase for the kernel.
Definition: KernelBase.hpp:155
static constexpr int numQuadraturePointsPerElem
Compile time value for the number of quadrature points per element.
Definition: KernelBase.hpp:107
static constexpr int numDofPerTestSupportPoint
Definition: KernelBase.hpp:100
static constexpr int numDofPerTrialSupportPoint
Definition: KernelBase.hpp:104
GEOS_HOST_DEVICE GEOS_FORCE_INLINE void quadraturePointKernel(localIndex const k, localIndex const q, StackVariables &stack) const
Performs a state update at a quadrature point.
Definition: KernelBase.hpp:180
static real64 kernelLaunch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Kernel Launcher.
Definition: KernelBase.hpp:231
GEOS_HOST_DEVICE real64 complete(localIndex const k, StackVariables &stack) const
Performs the complete phase for the kernel.
Definition: KernelBase.hpp:205
static constexpr int maxNumTrialSupportPointsPerElem
Definition: KernelBase.hpp:96
arrayView1d< integer const > const m_elemGhostRank
The element ghost rank array.
Definition: KernelBase.hpp:261
CONSTITUTIVE_TYPE::KernelWrapper const m_constitutiveUpdate
Definition: KernelBase.hpp:265
KernelBase(SUBREGION_TYPE const &elementSubRegion, FE_TYPE const &finiteElementSpace, CONSTITUTIVE_TYPE &inputConstitutiveType)
Constructor.
Definition: KernelBase.hpp:117
static constexpr int maxNumTestSupportPointsPerElem
Definition: KernelBase.hpp:92
Used to forward arguments to a class that implements the KernelBase interface.
Definition: KernelBase.hpp:283
KERNEL_TYPE< SUBREGION_TYPE, CONSTITUTIVE_TYPE, FE_TYPE > createKernel(NodeManager &nodeManager, EdgeManager const &edgeManager, FaceManager const &faceManager, localIndex const targetRegionIndex, SUBREGION_TYPE const &elementSubRegion, FE_TYPE const &finiteElementSpace, CONSTITUTIVE_TYPE &inputConstitutiveType)
Create a new kernel with the given standard arguments.
Definition: KernelBase.hpp:309
KernelFactory(ARGS ... args)
Initialize the factory.
Definition: KernelBase.hpp:290
camp::list< Ts... > TypeList
Construct a list of types.
bool dispatch(LIST const combinations, LAMBDA &&lambda, Ts &&... objects)
Dispatch a generic worker function lambda based on runtime type.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:188
stdVector< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:401
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
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:81
Kernel variables allocated on the stack.
Definition: KernelBase.hpp:138