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 
32 #include <utility>
33 
38 #ifndef SELECTED_FE_TYPES
39 #define SELECTED_FE_TYPES BASE_FE_TYPES
40 #endif
41 
42 namespace geos
43 {
44 
48 namespace finiteElement
49 {
50 
84 template< typename SUBREGION_TYPE,
85  typename CONSTITUTIVE_TYPE,
86  typename FE_TYPE,
87  int NUM_DOF_PER_TEST_SP,
88  int NUM_DOF_PER_TRIAL_SP >
90 {
91 public:
94  static constexpr int maxNumTestSupportPointsPerElem = FE_TYPE::maxSupportPoints;
95 
98  static constexpr int maxNumTrialSupportPointsPerElem = FE_TYPE::maxSupportPoints;
99 
102  static constexpr int numDofPerTestSupportPoint = NUM_DOF_PER_TEST_SP;
103 
106  static constexpr int numDofPerTrialSupportPoint = NUM_DOF_PER_TRIAL_SP;
107 
109  static constexpr int numQuadraturePointsPerElem = FE_TYPE::numQuadraturePoints;
110 
119  KernelBase( SUBREGION_TYPE const & elementSubRegion,
120  FE_TYPE const & finiteElementSpace,
121  CONSTITUTIVE_TYPE & inputConstitutiveType ):
122  m_elemsToNodes( elementSubRegion.nodeList().toViewConst() ),
123  m_elemGhostRank( elementSubRegion.ghostRank() ),
124  m_constitutiveUpdate( inputConstitutiveType.createKernelUpdates() ),
125  m_finiteElementSpace( finiteElementSpace )
126  {}
127 
140  {};
141 
156  inline
157  void setup( localIndex const k,
158  StackVariables & stack ) const
159  {
160  GEOS_UNUSED_VAR( k );
161  GEOS_UNUSED_VAR( stack );
162  }
163 
183  localIndex const q,
184  StackVariables & stack ) const
185  {
186  GEOS_UNUSED_VAR( k );
187  GEOS_UNUSED_VAR( q );
188  GEOS_UNUSED_VAR( stack );
189  }
190 
206  inline
208  StackVariables & stack ) const
209  {
210  GEOS_UNUSED_VAR( k );
211  GEOS_UNUSED_VAR( stack );
212  return 0;
213  }
214 
215 
228  //START_kernelLauncher
229  template< typename POLICY,
230  typename KERNEL_TYPE >
231  static
232  real64
233  kernelLaunch( localIndex const numElems,
234  KERNEL_TYPE const & kernelComponent )
235  {
237 
238  // Define a RAJA reduction variable to get the maximum residual contribution.
239  RAJA::ReduceMax< ReducePolicy< POLICY >, real64 > maxResidual( 0 );
240 
241  forAll< POLICY >( numElems,
242  [=] GEOS_HOST_DEVICE ( localIndex const k )
243  {
244  typename KERNEL_TYPE::StackVariables stack;
245 
246  kernelComponent.setup( k, stack );
247  // #pragma unroll
248  for( integer q=0; q<numQuadraturePointsPerElem; ++q )
249  {
250  kernelComponent.quadraturePointKernel( k, q, stack );
251  }
252  maxResidual.max( kernelComponent.complete( k, stack ) );
253  } );
254  return maxResidual.get();
255  }
256  //END_kernelLauncher
257 
258 protected:
263  using KernelWrapper = decltype( std::declval< CONSTITUTIVE_TYPE const & >().createKernelUpdates() );
264 
266  traits::ViewTypeConst< typename SUBREGION_TYPE::NodeMapType::base_type > const m_elemsToNodes;
267 
270 
274 
277  FE_TYPE const m_finiteElementSpace;
278 };
279 
286 template< template< typename SUBREGION_TYPE,
287  typename CONSTITUTIVE_TYPE,
288  typename FE_TYPE > class KERNEL_TYPE,
289  typename ... ARGS >
291 {
292 public:
293 
298  KernelFactory( ARGS ... args ):
299  m_args( args ... )
300  {}
301 
316  template< typename SUBREGION_TYPE, typename CONSTITUTIVE_TYPE, typename FE_TYPE >
317  KERNEL_TYPE< SUBREGION_TYPE, CONSTITUTIVE_TYPE, FE_TYPE > createKernel(
318  NodeManager & nodeManager,
319  EdgeManager const & edgeManager,
320  FaceManager const & faceManager,
321  localIndex const targetRegionIndex,
322  SUBREGION_TYPE const & elementSubRegion,
323  FE_TYPE const & finiteElementSpace,
324  CONSTITUTIVE_TYPE & inputConstitutiveType )
325  {
326  camp::tuple< NodeManager &,
327  EdgeManager const &,
328  FaceManager const &,
329  localIndex const,
330  SUBREGION_TYPE const &,
331  FE_TYPE const &,
332  CONSTITUTIVE_TYPE & > standardArgs { nodeManager,
333  edgeManager,
334  faceManager,
335  targetRegionIndex,
336  elementSubRegion,
337  finiteElementSpace,
338  inputConstitutiveType };
339 
340  auto allArgs = camp::tuple_cat_pair( standardArgs, m_args );
341  return camp::make_from_tuple< KERNEL_TYPE< SUBREGION_TYPE, CONSTITUTIVE_TYPE, FE_TYPE > >( allArgs );
342  }
343 
344 private:
346  camp::tuple< ARGS ... > m_args;
347 };
348 
349 
350 //*****************************************************************************
351 //*****************************************************************************
352 //*****************************************************************************
353 
354 //START_regionBasedKernelApplication
376 template< typename POLICY,
377  typename CONSTITUTIVE_BASE,
378  typename SUBREGION_TYPE,
379  typename KERNEL_FACTORY >
380 static
382  string_array const & targetRegions,
383  string const & finiteElementName,
384  string const & constitutiveStringName,
385  KERNEL_FACTORY & kernelFactory )
386 {
388  // save the maximum residual contribution for scaling residuals for convergence criteria.
389  real64 maxResidualContribution = 0;
390 
391  NodeManager & nodeManager = mesh.getNodeManager();
392  EdgeManager & edgeManager = mesh.getEdgeManager();
393  FaceManager & faceManager = mesh.getFaceManager();
394  ElementRegionManager & elementRegionManager = mesh.getElemManager();
395 
396  // Loop over all sub-regions in regions of type SUBREGION_TYPE, that are listed in the targetRegions array.
397  elementRegionManager.forElementSubRegions< SUBREGION_TYPE >( targetRegions,
398  [&constitutiveStringName,
399  &maxResidualContribution,
400  &nodeManager,
401  &edgeManager,
402  &faceManager,
403  &kernelFactory,
404  &finiteElementName]
405  ( localIndex const targetRegionIndex, auto & elementSubRegion )
406  {
407  localIndex const numElems = elementSubRegion.size();
408 
409  // Get the constitutive model...and allocate a null constitutive model if required.
410 
411  constitutive::ConstitutiveBase * constitutiveRelation = nullptr;
412  constitutive::NullModel * nullConstitutiveModel = nullptr;
413  if( elementSubRegion.template hasWrapper< string >( constitutiveStringName ) )
414  {
415  string const & constitutiveName = elementSubRegion.template getReference< string >( constitutiveStringName );
416  constitutiveRelation = &elementSubRegion.getConstitutiveModel( constitutiveName );
417  }
418  else
419  {
420  nullConstitutiveModel = &elementSubRegion.template registerGroup< constitutive::NullModel >( "nullModelGroup" );
421  constitutiveRelation = nullConstitutiveModel;
422  }
423 
424  // Call the constitutive dispatch which converts the type of constitutive model into a compile time constant.
425  constitutive::ConstitutivePassThru< CONSTITUTIVE_BASE >::execute( *constitutiveRelation,
426  [&maxResidualContribution,
427  &nodeManager,
428  &edgeManager,
429  &faceManager,
430  targetRegionIndex,
431  &kernelFactory,
432  &elementSubRegion,
433  &finiteElementName,
434  numElems]
435  ( auto & castedConstitutiveRelation )
436  {
438  subRegionFE = elementSubRegion.template getReference< FiniteElementBase >( finiteElementName );
439 
440  finiteElement::FiniteElementDispatchHandler< SELECTED_FE_TYPES >::dispatch3D( subRegionFE,
441  [&maxResidualContribution,
442  &nodeManager,
443  &edgeManager,
444  &faceManager,
445  targetRegionIndex,
446  &kernelFactory,
447  &elementSubRegion,
448  numElems,
449  &castedConstitutiveRelation] ( auto const finiteElement )
450  {
451  auto kernel = kernelFactory.createKernel( nodeManager,
452  edgeManager,
453  faceManager,
454  targetRegionIndex,
455  elementSubRegion,
457  castedConstitutiveRelation );
458 
459  using KERNEL_TYPE = decltype( kernel );
460 
461  // Call the kernelLaunch function, and store the maximum contribution to the residual.
462  maxResidualContribution =
463  std::max( maxResidualContribution,
464  KERNEL_TYPE::template kernelLaunch< POLICY, KERNEL_TYPE >( numElems, kernel ) );
465  } );
466  } );
467 
468  // Remove the null constitutive model (not required, but cleaner)
469  if( nullConstitutiveModel )
470  {
471  elementSubRegion.deregisterGroup( "nullModelGroup" );
472  }
473 
474  } );
475 
476  return maxResidualContribution;
477 }
478 
497 template< typename POLICY,
498  typename DISPATCH_TYPE_LIST,
499  typename KERNEL_FACTORY >
500 static
502  string_array const & targetRegions,
503  string const & finiteElementName,
504  string const & constitutiveStringName,
505  KERNEL_FACTORY & kernelFactory )
506 {
508  // save the maximum residual contribution for scaling residuals for convergence criteria.
509  real64 maxResidualContribution = 0;
510 
511  NodeManager & nodeManager = mesh.getNodeManager();
512  EdgeManager & edgeManager = mesh.getEdgeManager();
513  FaceManager & faceManager = mesh.getFaceManager();
514  ElementRegionManager & elementRegionManager = mesh.getElemManager();
515 
516  // Currently only CellElementSubRegion is supported.
517  using SUBREGION_TYPES = types::TypeList< CellElementSubRegion >;
518 
519  // Loop over all sub-regions in regions of type SUBREGION_TYPE, that are listed in the targetRegions array.
520  elementRegionManager.forElementSubRegions( SUBREGION_TYPES{}, targetRegions,
521  [&constitutiveStringName,
522  &maxResidualContribution,
523  &nodeManager,
524  &edgeManager,
525  &faceManager,
526  &kernelFactory,
527  &finiteElementName]
528  ( localIndex const targetRegionIndex, ElementSubRegionBase & elementSubRegion )
529  {
530  localIndex const numElems = elementSubRegion.size();
531 
532  // Get the constitutive model...and allocate a null constitutive model if required.
533  constitutive::ConstitutiveBase * constitutiveRelation = nullptr;
534  constitutive::NullModel * nullConstitutiveModel = nullptr;
535  if( elementSubRegion.template hasWrapper< string >( constitutiveStringName ) )
536  {
537  string const & constitutiveName = elementSubRegion.template getReference< string >( constitutiveStringName );
538  constitutiveRelation = &elementSubRegion.template getConstitutiveModel< >( constitutiveName );
539  }
540  else
541  {
542  nullConstitutiveModel = &elementSubRegion.template registerGroup< constitutive::NullModel >( "nullModelGroup" );
543  constitutiveRelation = nullConstitutiveModel;
544  }
545 
546  FiniteElementBase & subRegionFE = elementSubRegion.template getReference< FiniteElementBase >( finiteElementName );
547 
548  auto kernelLaunch = [&]( auto typeCombination )
549  {
550  using SUBREGION_TYPE = camp::at_v< decltype( typeCombination ), 0 >;
551  using CONSTITUTIVE_TYPE = camp::at_v< decltype( typeCombination ), 1 >;
552  using FE_TYPE = camp::at_v< decltype( typeCombination ), 2 >;
553 
554  SUBREGION_TYPE & castedSubRegion = dynamicCast< SUBREGION_TYPE & >( elementSubRegion );
555  CONSTITUTIVE_TYPE & castedConstitutiveRelation = dynamicCast< CONSTITUTIVE_TYPE & >( *constitutiveRelation );
556  typename FE_TYPE::ImplType & castedFiniteElement = *(dynamicCast< FE_TYPE & >( subRegionFE ).getImpl());
557 
558  auto kernel = kernelFactory.createKernel( nodeManager,
559  edgeManager,
560  faceManager,
561  targetRegionIndex,
562  castedSubRegion,
563  castedFiniteElement,
564  castedConstitutiveRelation );
565 
566  using KERNEL_TYPE = decltype( kernel );
567 
568  // Call the kernelLaunch function, and store the maximum contribution to the residual.
569  maxResidualContribution =
570  std::max( maxResidualContribution,
571  KERNEL_TYPE::template kernelLaunch< POLICY, KERNEL_TYPE >( numElems, kernel ) );
572  };
573 
574  types::dispatch( DISPATCH_TYPE_LIST{}, kernelLaunch, elementSubRegion, *constitutiveRelation, subRegionFE );
575 
576  // Remove the null constitutive model (not required, but cleaner)
577  if( nullConstitutiveModel )
578  {
579  elementSubRegion.deregisterGroup( "nullModelGroup" );
580  }
581 
582  } );
583 
584  return maxResidualContribution;
585 }
586 //END_regionBasedKernelApplication
587 
588 } // namespace finiteElement
589 } // namespace geos
590 
591 
592 
593 #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.
#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:381
#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:90
traits::ViewTypeConst< typename SUBREGION_TYPE::NodeMapType::base_type > const m_elemsToNodes
The element to nodes map.
Definition: KernelBase.hpp:266
GEOS_HOST_DEVICE void setup(localIndex const k, StackVariables &stack) const
Performs the setup phase for the kernel.
Definition: KernelBase.hpp:157
static constexpr int numQuadraturePointsPerElem
Compile time value for the number of quadrature points per element.
Definition: KernelBase.hpp:109
static constexpr int numDofPerTestSupportPoint
Definition: KernelBase.hpp:102
static constexpr int numDofPerTrialSupportPoint
Definition: KernelBase.hpp:106
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:182
static real64 kernelLaunch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Kernel Launcher.
Definition: KernelBase.hpp:233
GEOS_HOST_DEVICE real64 complete(localIndex const k, StackVariables &stack) const
Performs the complete phase for the kernel.
Definition: KernelBase.hpp:207
KernelWrapper const m_constitutiveUpdate
Definition: KernelBase.hpp:273
static constexpr int maxNumTrialSupportPointsPerElem
Definition: KernelBase.hpp:98
arrayView1d< integer const > const m_elemGhostRank
The element ghost rank array.
Definition: KernelBase.hpp:269
KernelBase(SUBREGION_TYPE const &elementSubRegion, FE_TYPE const &finiteElementSpace, CONSTITUTIVE_TYPE &inputConstitutiveType)
Constructor.
Definition: KernelBase.hpp:119
static constexpr int maxNumTestSupportPointsPerElem
Definition: KernelBase.hpp:94
Used to forward arguments to a class that implements the KernelBase interface.
Definition: KernelBase.hpp:291
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:317
KernelFactory(ARGS ... args)
Initialize the factory.
Definition: KernelBase.hpp:298
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:179
stdVector< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:361
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
int integer
Signed integer type.
Definition: DataTypes.hpp:81
Kernel variables allocated on the stack.
Definition: KernelBase.hpp:140