https://mooseframework.inl.gov
KokkosResidualObject.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #pragma once
11 
12 #include "KokkosDispatcher.h"
13 #include "KokkosFESystem.h"
14 #include "KokkosVariableValue.h"
16 
17 #include "MooseVariableBase.h"
18 #include "ResidualObject.h"
19 
20 namespace Moose::Kokkos
21 {
22 
27  public MeshHolder,
28  public AssemblyHolder,
29  public FESystemHolder
30 {
31 public:
33 
35  static constexpr bool use_precompute_hooks = false;
36 
43  Moose::VarFieldType field_type,
44  bool nodal = false);
48  ResidualObject(const ResidualObject & object);
49 
53  struct ResidualLoop
55  {
56  };
57  struct JacobianLoop
58  {
59  };
61  {
62  };
64 
65  virtual const MooseVariableBase & variable() const override { return _var; }
66 
67  virtual void computeOffDiagJacobian(unsigned int) override final
68  {
69  mooseError("computeOffDiagJacobian() is not used for Kokkos residual objects.");
70  }
71  virtual void computeResidualAndJacobian() override
72  {
75  }
76 
77 protected:
93  std::unique_ptr<DispatcherBase> _residual_dispatcher;
95  std::unique_ptr<DispatcherBase> _jacobian_dispatcher;
96  std::unique_ptr<DispatcherBase> _offdiag_jacobian_dispatcher;
98 
102  const unsigned int _dimension;
103 
107 
129 
137  KOKKOS_FUNCTION void accumulateTaggedElementalResidual(const Real local_re,
138  const ContiguousElementID elem,
139  const unsigned int i,
140  const unsigned int comp = 0) const;
148  KOKKOS_FUNCTION void accumulateTaggedNodalResidual(const bool add,
149  const Real local_re,
150  const ContiguousNodeID node,
151  const unsigned int comp = 0) const;
159  KOKKOS_FUNCTION void accumulateTaggedVectorNodalResidual(const bool add,
160  const Real local_re,
161  const ContiguousNodeID node,
162  const unsigned int i) const;
172  KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const Real local_ke,
173  const ContiguousElementID elem,
174  const unsigned int i,
175  const unsigned int j,
176  const unsigned int jvar,
177  const unsigned int comp = 0) const;
186  KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const DNDerivativeType & local_ke,
187  const AssemblyDatum & datum,
188  const unsigned int i,
189  const unsigned int comp = 0) const;
198  KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add,
199  const Real local_ke,
200  const ContiguousNodeID node,
201  const unsigned int jvar,
202  const unsigned int comp = 0) const;
212  KOKKOS_FUNCTION void accumulateTaggedVectorNodalMatrix(const bool add,
213  const Real local_ke,
214  const ContiguousNodeID node,
215  const unsigned int i,
216  const unsigned int j,
217  const unsigned int jvar) const;
226  KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add,
227  const DNDerivativeType & local_ke,
228  const ContiguousNodeID node,
229  const unsigned int comp = 0) const;
230 
236  template <typename function>
237  KOKKOS_FUNCTION void computeResidualInternal(AssemblyDatum & datum, function body) const;
243  template <typename function>
244  KOKKOS_FUNCTION void computeJacobianInternal(AssemblyDatum & datum, function body) const;
245 
246 private:
254 };
255 
256 KOKKOS_FUNCTION inline void
258  const ContiguousElementID elem,
259  const unsigned int i,
260  const unsigned int comp) const
261 {
262  if (!local_re)
263  return;
264 
265  auto & sys = kokkosSystem(_kokkos_var.sys(comp));
266  auto dof = sys.getElemLocalDofIndex(elem, i, _kokkos_var.var(comp));
267 
268  for (unsigned int t = 0; t < _vector_tags.size(); ++t)
269  {
270  auto tag = _vector_tags[t];
271 
272  if (sys.isResidualTagActive(tag))
273  ::Kokkos::atomic_add(&sys.getVectorDofValue(dof, tag), local_re);
274  }
275 }
276 
277 KOKKOS_FUNCTION inline void
279  const Real local_re,
280  const ContiguousNodeID node,
281  const unsigned int comp) const
282 {
283  if (!local_re && add)
284  return;
285 
286  auto & sys = kokkosSystem(_kokkos_var.sys(comp));
287  auto dof = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
288 
289  for (unsigned int t = 0; t < _vector_tags.size(); ++t)
290  {
291  auto tag = _vector_tags[t];
292 
293  if (sys.isResidualTagActive(tag))
294  {
295  if (add)
296  sys.getVectorDofValue(dof, tag) += local_re;
297  else
298  sys.getVectorDofValue(dof, tag) = local_re;
299  }
300  }
301 }
302 
303 KOKKOS_FUNCTION inline void
305  const Real local_re,
306  const ContiguousNodeID node,
307  const unsigned int i) const
308 {
309  if (!local_re && add)
310  return;
311 
312  auto & sys = kokkosSystem(_kokkos_var.sys());
313  auto dof = sys.getNodeLocalDofIndex(node, i, _kokkos_var.var());
314 
315  for (unsigned int t = 0; t < _vector_tags.size(); ++t)
316  {
317  auto tag = _vector_tags[t];
318 
319  if (sys.isResidualTagActive(tag))
320  {
321  if (add)
322  sys.getVectorDofValue(dof, tag) += local_re;
323  else
324  sys.getVectorDofValue(dof, tag) = local_re;
325  }
326  }
327 }
328 
329 KOKKOS_FUNCTION inline void
331  const ContiguousElementID elem,
332  const unsigned int i,
333  const unsigned int j,
334  const unsigned int jvar,
335  const unsigned int comp) const
336 {
337  if (!local_ke)
338  return;
339 
340  auto & sys = kokkosSystem(_kokkos_var.sys(comp));
341  auto row = sys.getElemLocalDofIndex(elem, i, _kokkos_var.var(comp));
342  auto col = sys.getElemGlobalDofIndex(elem, j, jvar);
343 
344  for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
345  {
346  auto tag = _matrix_tags[t];
347 
348  if (sys.isMatrixTagActive(tag) && !sys.hasNodalBCMatrixTag(row, tag))
349  ::Kokkos::atomic_add(&sys.getMatrixValue(row, col, tag), local_ke);
350  }
351 }
352 
353 KOKKOS_FUNCTION inline void
355  const AssemblyDatum & datum,
356  const unsigned int i,
357  const unsigned int comp) const
358 {
359  auto & sys = kokkosSystem(_kokkos_var.sys(comp));
360  auto row = sys.getElemLocalDofIndex(datum.elem().id, i, _kokkos_var.var(comp));
361 
362  for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
363  {
364  auto tag = _matrix_tags[t];
365 
366  if (sys.isMatrixTagActive(tag) && !sys.hasNodalBCMatrixTag(row, tag))
367  for (unsigned int j = 0; j < local_ke.size(); ++j)
368  {
369  auto col = local_ke.raw_index(j);
370 
371  ::Kokkos::atomic_add(&sys.getMatrixValue(row, col, tag), local_ke.raw_at(j));
372  }
373  }
374 }
375 
376 KOKKOS_FUNCTION inline void
378  const Real local_ke,
379  const ContiguousNodeID node,
380  const unsigned int jvar,
381  const unsigned int comp) const
382 {
383  if (!local_ke && add)
384  return;
385 
386  auto & sys = kokkosSystem(_kokkos_var.sys(comp));
387  auto row = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
388  auto col = sys.getNodeGlobalDofIndex(node, 0, jvar);
389 
390  for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
391  {
392  auto tag = _matrix_tags[t];
393 
394  if (sys.isMatrixTagActive(tag))
395  {
396  auto & matrix = sys.getMatrix(tag);
397 
398  if (add)
399  matrix(row, col) += local_ke;
400  else
401  {
402  matrix.zero(row);
403  matrix(row, col) = local_ke;
404  }
405  }
406  }
407 }
408 
409 KOKKOS_FUNCTION inline void
411  const Real local_ke,
412  const ContiguousNodeID node,
413  const unsigned int i,
414  const unsigned int j,
415  const unsigned int jvar) const
416 {
417  if (!local_ke && add)
418  return;
419 
420  auto & sys = kokkosSystem(_kokkos_var.sys());
421  auto row = sys.getNodeLocalDofIndex(node, i, _kokkos_var.var());
422  auto col = sys.getNodeGlobalDofIndex(node, j, jvar);
423 
424  for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
425  {
426  auto tag = _matrix_tags[t];
427 
428  if (sys.isMatrixTagActive(tag))
429  {
430  auto & matrix = sys.getMatrix(tag);
431 
432  if (add)
433  matrix(row, col) += local_ke;
434  else
435  {
436  matrix.zero(row);
437  matrix(row, col) = local_ke;
438  }
439  }
440  }
441 }
442 
443 KOKKOS_FUNCTION inline void
445  const DNDerivativeType & local_ke,
446  const ContiguousNodeID node,
447  const unsigned int comp) const
448 {
449  auto & sys = kokkosSystem(_kokkos_var.sys(comp));
450  auto row = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
451 
452  for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
453  {
454  auto tag = _matrix_tags[t];
455  auto & matrix = sys.getMatrix(tag);
456 
457  if (sys.isMatrixTagActive(tag))
458  {
459  if (!add)
460  matrix.zero(row);
461 
462  for (unsigned int j = 0; j < local_ke.size(); ++j)
463  {
464  auto col = local_ke.raw_index(j);
465 
466  if (add)
467  matrix(row, col) += local_ke.raw_at(j);
468  else
469  matrix(row, col) = local_ke.raw_at(j);
470  }
471  }
472  }
473 }
474 
475 template <typename function>
476 KOKKOS_FUNCTION void
478 {
479  Real local_re[MAX_CACHED_DOF];
480 
481  unsigned int stride = MAX_CACHED_DOF * datum.num_local_threads();
482  unsigned int num_batches = datum.n_dofs() / stride;
483 
484  if (datum.n_dofs() % stride)
485  ++num_batches;
486 
487  for (unsigned int batch = 0; batch < num_batches; ++batch)
488  {
489  unsigned int ib = batch * stride;
490  unsigned int ie = ::Kokkos::min(ib + stride, datum.n_dofs());
491 
492  const unsigned int n = ie - ib;
493  const unsigned int d = n / datum.num_local_threads();
494  const unsigned int m = n % datum.num_local_threads();
495  const unsigned int t = datum.local_thread_id();
496 
497  ib += t * d + (t < m ? t : m);
498  ie = ib + d + (t < m ? 1 : 0);
499 
500  for (unsigned int i = ib; i < ie; ++i)
501  local_re[i - ib] = 0;
502 
503  body(local_re - ib, ib, ie);
504 
505  for (unsigned int i = ib; i < ie; ++i)
506  accumulateTaggedElementalResidual(local_re[i - ib], datum.elem().id, i);
507  }
508 }
509 
510 template <typename function>
511 KOKKOS_FUNCTION void
513 {
514  Real local_ke[MAX_CACHED_DOF];
515 
516  for (unsigned int j = datum.local_thread_id(); j < datum.n_jdofs();
517  j += datum.num_local_threads())
518  {
519  unsigned int num_batches = datum.n_idofs() / MAX_CACHED_DOF;
520 
521  if (datum.n_idofs() % MAX_CACHED_DOF)
522  ++num_batches;
523 
524  for (unsigned int batch = 0; batch < num_batches; ++batch)
525  {
526  unsigned int ib = batch * MAX_CACHED_DOF;
527  unsigned int ie = ::Kokkos::min(ib + MAX_CACHED_DOF, datum.n_idofs());
528 
529  for (unsigned int i = ib; i < ie; ++i)
530  local_ke[i - ib] = 0;
531 
532  body(local_ke - ib, ib, ie, j);
533 
534  for (unsigned int i = ib; i < ie; ++i)
535  accumulateTaggedElementalMatrix(local_ke[i - ib], datum.elem().id, i, j, datum.jvar());
536  }
537  }
538 }
539 
540 } // namespace Moose::Kokkos
VarFieldType
Definition: MooseTypes.h:770
Scalar< Real > _dt_old
Size of the old time step.
static constexpr bool use_precompute_hooks
Whether this object&#39;s hooks factor out the test function.
std::unique_ptr< DispatcherBase > _jacobian_dispatcher
KOKKOS_FUNCTION unsigned int sys(unsigned int comp=0) const
Get the system number of a component.
KOKKOS_FUNCTION void computeJacobianInternal(AssemblyDatum &datum, function body) const
The common loop structure template for computing elemental Jacobian.
Scalar< Real > _t
TODO: Move to TransientInterface.
dof_id_type ContiguousElementID
Definition: KokkosMesh.h:20
KOKKOS_FUNCTION unsigned int num_local_threads() const
Get the number of local threads.
Definition: KokkosDatum.h:384
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
ResidualObject(const InputParameters &parameters, Moose::VarFieldType field_type, bool nodal=false)
Constructor.
KOKKOS_FUNCTION void accumulateTaggedNodalResidual(const bool add, const Real local_re, const ContiguousNodeID node, const unsigned int comp=0) const
Accumulate or set local nodal residual contribution to tagged vectors.
virtual void computeOffDiagJacobian(unsigned int) override final
Computes this object&#39;s contribution to off-diagonal blocks of the system Jacobian matrix...
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
The base class for Kokkos residual objects.
Thread _thread
Kokkos thread object.
KOKKOS_FUNCTION unsigned int jvar() const
Get the coupled variable number.
Definition: KokkosDatum.h:651
MooseVariableFieldBase & _var
Reference of the MOOSE variable.
This class provides an interface for common operations on field variables of both FE and FV types wit...
KOKKOS_FUNCTION unsigned int n_jdofs() const
Get the number of local DOFs for the coupled variable.
Definition: KokkosDatum.h:631
The Kokkos interface that holds the host reference of the Kokkos mesh and copies it to device during ...
Definition: KokkosMesh.h:629
KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const Real local_ke, const ContiguousElementID elem, const unsigned int i, const unsigned int j, const unsigned int jvar, const unsigned int comp=0) const
Accumulate local elemental Jacobian contribution to tagged matrices.
dof_id_type ContiguousNodeID
Definition: KokkosMesh.h:21
KOKKOS_FUNCTION void accumulateTaggedVectorNodalResidual(const bool add, const Real local_re, const ContiguousNodeID node, const unsigned int i) const
Accumulate or set local nodal residual contribution to tagged vectors for vector FE variables...
KOKKOS_FUNCTION unsigned int n_idofs() const
Get the number of local DOFs.
Definition: KokkosDatum.h:626
virtual void computeResidual()=0
Compute this object&#39;s contribution to the residual.
The Kokkos interface that holds the host reference of the Kokkos assembly and copies it to device dur...
KOKKOS_FUNCTION unsigned int local_thread_id() const
Get the current local thread ID.
Definition: KokkosDatum.h:379
virtual void computeJacobian()=0
Compute this object&#39;s contribution to the diagonal Jacobian entries.
KOKKOS_FUNCTION index_type size() const
Get the total array size.
Definition: KokkosArray.h:294
Scalar< const Real > _t_old
Old time.
KokkosSemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< MOOSE_AD_MAX_DOFS_PER_ELEM > > DNDerivativeType
Definition: KokkosADReal.h:22
Scalar< int > _t_step
The number of the time step.
KOKKOS_FUNCTION void accumulateTaggedVectorNodalMatrix(const bool add, const Real local_ke, const ContiguousNodeID node, const unsigned int i, const unsigned int j, const unsigned int jvar) const
Accumulate or set local nodal Jacobian contribution to tagged matrices for vector FE variables...
std::unique_ptr< DispatcherBase > _offdiag_jacobian_dispatcher
constexpr unsigned int MAX_CACHED_DOF
Maximum number of DOFs to cache during residual and Jacobian computation.
Definition: KokkosHeader.h:83
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
The Kokkos variable object that carries the coupled variable and tag information. ...
KOKKOS_FUNCTION void accumulateTaggedElementalResidual(const Real local_re, const ContiguousElementID elem, const unsigned int i, const unsigned int comp=0) const
Accumulate local elemental residual contribution to tagged vectors.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:271
The Kokkos object that holds thread-private data in the parallel operations of Kokkos kernels...
Definition: KokkosDatum.h:559
Scalar< Real > _dt
Time step size.
Variable _kokkos_var
Kokkos variable.
KOKKOS_FUNCTION const ElementInfo & elem() const
Get the element information object.
Definition: KokkosDatum.h:46
KOKKOS_FUNCTION unsigned int var(unsigned int comp=0) const
Get the variable number of a component.
std::unique_ptr< DispatcherBase > _residual_dispatcher
Kokkos functor dispatchers.
KOKKOS_FUNCTION unsigned int n_dofs() const
Get the number of local DOFs.
Definition: KokkosDatum.h:621
auto min(const L &left, const R &right)
static InputParameters validParams()
Array< TagID > _vector_tags
Tags this object operates on.
KOKKOS_FUNCTION void computeResidualInternal(AssemblyDatum &datum, function body) const
The common loop structure template for computing elemental residual.
KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add, const Real local_ke, const ContiguousNodeID node, const unsigned int jvar, const unsigned int comp=0) const
Accumulate or set local nodal Jacobian contribution to tagged matrices.
The Kokkos thread object that aids in converting the one-dimensional thread index into multi-dimensio...
Definition: KokkosThread.h:29
virtual void computeResidualAndJacobian() override
Compute this object&#39;s contribution to the residual and Jacobian simultaneously.
virtual const MooseVariableBase & variable() const override
Returns the variable that this object operates on.
ContiguousElementID id
Contiguous element ID.
Definition: KokkosMesh.h:42
Base variable class.
const unsigned int _dimension
Mesh dimension.