https://mooseframework.inl.gov
Loading...
Searching...
No Matches
KokkosResidualObject.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
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
20namespace Moose::Kokkos
21{
22
27 public MeshHolder,
28 public AssemblyHolder,
29 public FESystemHolder
30{
31public:
33
35 static constexpr bool uses_precompute_hooks = false;
36
38 static constexpr bool supports_scalar_jacobian = false;
39
46 Moose::VarFieldType field_type,
47 bool nodal = false);
52
58 {
59 };
61 {
62 };
64 {
65 };
67 {
68 };
70
71 virtual const MooseVariableBase & variable() const override
72 {
73 if (_vars.size() > 1)
74 mooseError("variable() was called for a multi-variable Kokkos residual object. Use "
75 "variables() instead.");
76
77 return *_vars[0];
78 }
79
80 virtual std::vector<const MooseVariableBase *> variables() const override
81 {
82 return {_vars.begin(), _vars.end()};
83 }
84
85 virtual void computeOffDiagJacobian(unsigned int) override final
86 {
87 mooseError("computeOffDiagJacobian() is not used for Kokkos residual objects.");
88 }
89 virtual void computeResidualAndJacobian() override
90 {
93 }
94
95protected:
99 const std::vector<MooseVariableFieldBase *> _vars;
112 std::unique_ptr<DispatcherBase> _residual_dispatcher;
113 std::unique_ptr<DispatcherBase> _jacobian_dispatcher;
114 std::unique_ptr<DispatcherBase> _offdiag_jacobian_dispatcher;
115 std::unique_ptr<DispatcherBase> _offdiag_jacobian_scalar_dispatcher;
117
121 const unsigned int _dimension;
122
127
148
156 KOKKOS_FUNCTION void accumulateTaggedElementalResidual(const Real local_re,
157 const ContiguousElementID elem,
158 const unsigned int i,
159 const unsigned int comp) const;
167 KOKKOS_FUNCTION void accumulateTaggedNodalResidual(const bool add,
168 const Real local_re,
169 const ContiguousNodeID node,
170 const unsigned int comp) const;
178 KOKKOS_FUNCTION void accumulateTaggedVectorNodalResidual(const bool add,
179 const Real local_re,
180 const ContiguousNodeID node,
181 const unsigned int i) const;
191 KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const Real local_ke,
192 const ContiguousElementID elem,
193 const unsigned int i,
194 const unsigned int j,
195 const unsigned int jvar,
196 const unsigned int comp) const;
205 KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const DNDerivativeType & local_ke,
206 const AssemblyDatum & datum,
207 const unsigned int i,
208 const unsigned int comp) const;
217 KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add,
218 const Real local_ke,
219 const ContiguousNodeID node,
220 const unsigned int jvar,
221 const unsigned int comp) const;
231 KOKKOS_FUNCTION void accumulateTaggedVectorNodalMatrix(const bool add,
232 const Real local_ke,
233 const ContiguousNodeID node,
234 const unsigned int i,
235 const unsigned int j,
236 const unsigned int jvar) const;
245 KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add,
246 const DNDerivativeType & local_ke,
247 const ContiguousNodeID node,
248 const unsigned int comp) const;
249
255 template <typename function>
256 KOKKOS_FUNCTION void computeResidualInternal(AssemblyDatum & datum, function body) const;
262 template <typename function>
263 KOKKOS_FUNCTION void computeJacobianInternal(AssemblyDatum & datum, function body) const;
264
265private:
271 std::vector<MooseVariableFieldBase *> getMooseVariables(Moose::VarFieldType field_type);
272
280};
281
282KOKKOS_FUNCTION inline void
284 const ContiguousElementID elem,
285 const unsigned int i,
286 const unsigned int comp) const
287{
288 if (!local_re)
289 return;
290
291 auto & sys = kokkosSystem(_kokkos_var.sys(comp));
292 auto dof = sys.getElemLocalDofIndex(elem, i, _kokkos_var.var(comp));
293 auto constraints = sys.getLocalConstraints(dof);
294
295 for (unsigned int t = 0; t < _vector_tags.size(); ++t)
296 {
297 auto tag = _vector_tags[t];
298
299 if (sys.isResidualTagActive(tag))
300 {
301 if (constraints.size())
302 for (unsigned int c = 0; c < constraints.size(); ++c)
303 {
304 auto [constraint_dof, weight] = constraints[c];
305
306 ::Kokkos::atomic_add(&sys.getVectorDofValue(constraint_dof, tag), weight * local_re);
307 }
308 else
309 ::Kokkos::atomic_add(&sys.getVectorDofValue(dof, tag), local_re);
310 }
311 }
312}
313
314KOKKOS_FUNCTION inline void
316 const Real local_re,
317 const ContiguousNodeID node,
318 const unsigned int comp) const
319{
320 if (!local_re && add)
321 return;
322
323 auto & sys = kokkosSystem(_kokkos_var.sys(comp));
324 auto dof = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
325
326 for (unsigned int t = 0; t < _vector_tags.size(); ++t)
327 {
328 auto tag = _vector_tags[t];
329
330 if (sys.isResidualTagActive(tag))
331 {
332 if (add)
333 sys.getVectorDofValue(dof, tag) += local_re;
334 else
335 sys.getVectorDofValue(dof, tag) = local_re;
336 }
337 }
338}
339
340KOKKOS_FUNCTION inline void
342 const Real local_re,
343 const ContiguousNodeID node,
344 const unsigned int i) const
345{
346 if (!local_re && add)
347 return;
348
349 auto & sys = kokkosSystem(_kokkos_var.sys());
350 auto dof = sys.getNodeLocalDofIndex(node, i, _kokkos_var.var());
351
352 for (unsigned int t = 0; t < _vector_tags.size(); ++t)
353 {
354 auto tag = _vector_tags[t];
355
356 if (sys.isResidualTagActive(tag))
357 {
358 if (add)
359 sys.getVectorDofValue(dof, tag) += local_re;
360 else
361 sys.getVectorDofValue(dof, tag) = local_re;
362 }
363 }
364}
365
366KOKKOS_FUNCTION inline void
368 const ContiguousElementID elem,
369 const unsigned int i,
370 const unsigned int j,
371 const unsigned int jvar,
372 const unsigned int comp) const
373{
374 if (!local_ke)
375 return;
376
377 auto & sys = kokkosSystem(_kokkos_var.sys(comp));
378 const auto ivar = _kokkos_var.var(comp);
379 auto row = sys.getElemLocalDofIndex(elem, i, ivar);
380 auto col = sys.isScalarVariable(jvar) ? sys.getScalarLocalDofIndex(j, jvar)
381 : sys.getElemLocalDofIndex(elem, j, jvar);
382 auto col_global = sys.localToGlobalDofIndex(col);
383 auto row_constraints = sys.getLocalConstraints(row);
384 auto col_constraints = sys.getLocalConstraints(col);
385
386 for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
387 {
388 auto tag = _matrix_tags[t];
389
390 if (sys.isMatrixTagActive(tag))
391 {
392 for (unsigned int rc = 0; rc < ::Kokkos::max(1u, row_constraints.size()); ++rc)
393 {
394 auto constraint_row = row_constraints.size() ? row_constraints[rc].first : row;
395 auto weight_row = row_constraints.size() ? row_constraints[rc].second : 1.0;
396
397 if (sys.hasNodalBCMatrixTag(constraint_row, tag))
398 continue;
399
400 for (unsigned int cc = 0; cc < ::Kokkos::max(1u, col_constraints.size()); ++cc)
401 {
402 auto constraint_col = col_constraints.size()
403 ? sys.localToGlobalDofIndex(col_constraints[cc].first)
404 : col_global;
405 auto weight_col = col_constraints.size() ? col_constraints[cc].second : 1.0;
406
407 ::Kokkos::atomic_add(&sys.getMatrixValue(constraint_row, constraint_col, tag),
408 weight_row * weight_col * local_ke);
409 }
410 }
411 }
412 }
413}
414
415KOKKOS_FUNCTION inline void
417 const AssemblyDatum & datum,
418 const unsigned int i,
419 const unsigned int comp) const
420{
421 auto & sys = kokkosSystem(_kokkos_var.sys(comp));
422 const auto ivar = _kokkos_var.var(comp);
423 auto row = sys.getElemLocalDofIndex(datum.elem().id, i, ivar);
424 auto row_constraints = sys.getLocalConstraints(row);
425
426 for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
427 {
428 auto tag = _matrix_tags[t];
429
430 if (sys.isMatrixTagActive(tag))
431 {
432 for (unsigned int rc = 0; rc < ::Kokkos::max(1u, row_constraints.size()); ++rc)
433 {
434 auto constraint_row = row_constraints.size() ? row_constraints[rc].first : row;
435 auto weight_row = row_constraints.size() ? row_constraints[rc].second : 1.0;
436
437 if (sys.hasNodalBCMatrixTag(constraint_row, tag))
438 continue;
439
440 for (unsigned int j = 0; j < local_ke.size(); ++j)
441 {
442 auto col = local_ke.raw_index(j);
443 auto col_constraints = sys.getLocalConstraints(col);
444
445 for (unsigned int cc = 0; cc < ::Kokkos::max(1u, col_constraints.size()); ++cc)
446 {
447 auto constraint_col =
448 sys.localToGlobalDofIndex(col_constraints.size() ? col_constraints[cc].first : col);
449 auto weight_col = col_constraints.size() ? col_constraints[cc].second : 1.0;
450
451 ::Kokkos::atomic_add(&sys.getMatrixValue(constraint_row, constraint_col, tag),
452 weight_row * weight_col * local_ke.raw_at(j));
453 }
454 }
455 }
456 }
457 }
458}
459
460KOKKOS_FUNCTION inline void
462 const Real local_ke,
463 const ContiguousNodeID node,
464 const unsigned int jvar,
465 const unsigned int comp) const
466{
467 if (!local_ke && add)
468 return;
469
470 auto & sys = kokkosSystem(_kokkos_var.sys(comp));
471 auto row = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
472 auto col = sys.getNodeGlobalDofIndex(node, 0, jvar);
473
474 for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
475 {
476 auto tag = _matrix_tags[t];
477
478 if (sys.isMatrixTagActive(tag))
479 {
480 auto & matrix = sys.getMatrix(tag);
481
482 if (add)
483 matrix(row, col) += local_ke;
484 else
485 {
486 matrix.zero(row);
487 matrix(row, col) = local_ke;
488 }
489 }
490 }
491}
492
493KOKKOS_FUNCTION inline void
495 const Real local_ke,
496 const ContiguousNodeID node,
497 const unsigned int i,
498 const unsigned int j,
499 const unsigned int jvar) const
500{
501 if (!local_ke && add)
502 return;
503
504 auto & sys = kokkosSystem(_kokkos_var.sys());
505 auto row = sys.getNodeLocalDofIndex(node, i, _kokkos_var.var());
506 auto col = sys.getNodeGlobalDofIndex(node, j, jvar);
507
508 for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
509 {
510 auto tag = _matrix_tags[t];
511
512 if (sys.isMatrixTagActive(tag))
513 {
514 auto & matrix = sys.getMatrix(tag);
515
516 if (add)
517 matrix(row, col) += local_ke;
518 else
519 {
520 matrix.zero(row);
521 matrix(row, col) = local_ke;
522 }
523 }
524 }
525}
526
527KOKKOS_FUNCTION inline void
529 const DNDerivativeType & local_ke,
530 const ContiguousNodeID node,
531 const unsigned int comp) const
532{
533 auto & sys = kokkosSystem(_kokkos_var.sys(comp));
534 auto row = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
535
536 for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
537 {
538 auto tag = _matrix_tags[t];
539 auto & matrix = sys.getMatrix(tag);
540
541 if (sys.isMatrixTagActive(tag))
542 {
543 if (!add)
544 matrix.zero(row);
545
546 for (unsigned int j = 0; j < local_ke.size(); ++j)
547 {
548 auto col = sys.localToGlobalDofIndex(local_ke.raw_index(j));
549
550 if (add)
551 matrix(row, col) += local_ke.raw_at(j);
552 else
553 matrix(row, col) = local_ke.raw_at(j);
554 }
555 }
556 }
557}
558
559template <typename function>
560KOKKOS_FUNCTION void
562{
563 Real local_re[MAX_CACHED_DOF];
564
565 const auto scaling_factor =
566 kokkosSystem(_kokkos_var.sys()).getVariableScalingFactor(_kokkos_var.var());
567
568 unsigned int stride = MAX_CACHED_DOF * datum.num_local_threads();
569 unsigned int num_batches = datum.n_dofs() / stride;
570
571 if (datum.n_dofs() % stride)
572 ++num_batches;
573
574 for (unsigned int batch = 0; batch < num_batches; ++batch)
575 {
576 unsigned int ib = batch * stride;
577 unsigned int ie = ::Kokkos::min(ib + stride, datum.n_dofs());
578
579 const unsigned int n = ie - ib;
580 const unsigned int d = n / datum.num_local_threads();
581 const unsigned int m = n % datum.num_local_threads();
582 const unsigned int t = datum.local_thread_id();
583
584 ib += t * d + (t < m ? t : m);
585 ie = ib + d + (t < m ? 1 : 0);
586
587 for (unsigned int i = ib; i < ie; ++i)
588 local_re[i - ib] = 0;
589
590 body(local_re - ib, ib, ie);
591
592 for (unsigned int i = ib; i < ie; ++i)
594 local_re[i - ib] * scaling_factor, datum.elem().id, i, datum.comp());
595 }
596}
597
598template <typename function>
599KOKKOS_FUNCTION void
601{
602 Real local_ke[MAX_CACHED_DOF];
603
604 const auto scaling_factor =
605 kokkosSystem(_kokkos_var.sys()).getVariableScalingFactor(_kokkos_var.var());
606
607 for (unsigned int j = datum.local_thread_id(); j < datum.n_jdofs();
608 j += datum.num_local_threads())
609 {
610 unsigned int num_batches = datum.n_idofs() / MAX_CACHED_DOF;
611
612 if (datum.n_idofs() % MAX_CACHED_DOF)
613 ++num_batches;
614
615 for (unsigned int batch = 0; batch < num_batches; ++batch)
616 {
617 unsigned int ib = batch * MAX_CACHED_DOF;
618 unsigned int ie = ::Kokkos::min(ib + MAX_CACHED_DOF, datum.n_idofs());
619
620 for (unsigned int i = ib; i < ie; ++i)
621 local_ke[i - ib] = 0;
622
623 body(local_ke - ib, ib, ie, j);
624
625 for (unsigned int i = ib; i < ie; ++i)
627 local_ke[i - ib] * scaling_factor, datum.elem().id, i, j, datum.jvar(), datum.comp());
628 }
629 }
630}
631
632} // namespace Moose::Kokkos
dof_id_type ContiguousElementID
Definition KokkosMesh.h:20
dof_id_type ContiguousNodeID
Definition KokkosMesh.h:21
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
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
Base variable class.
KOKKOS_FUNCTION index_type size() const
Get the total array size.
The Kokkos array class.
The Kokkos object that holds thread-private data in the parallel operations of Kokkos kernels.
KOKKOS_FUNCTION unsigned int n_dofs() const
Get the number of local DOFs.
KOKKOS_FUNCTION unsigned int jvar() const
Get the coupled variable number.
KOKKOS_FUNCTION unsigned int n_idofs() const
Get the number of local DOFs.
KOKKOS_FUNCTION unsigned int n_jdofs() const
Get the number of local DOFs for the coupled variable.
KOKKOS_FUNCTION unsigned int comp() const
Get the variable component.
The Kokkos interface that holds the host reference of the Kokkos assembly and copies it to device dur...
KOKKOS_FUNCTION unsigned int num_local_threads() const
Get the number of local threads.
KOKKOS_FUNCTION unsigned int local_thread_id() const
Get the current local thread ID.
KOKKOS_FUNCTION const ElementInfo & elem() const
Get the element information object.
Definition KokkosDatum.h:46
The Kokkos interface that holds the host reference of the Kokkos mesh and copies it to device during ...
Definition KokkosMesh.h:669
The base class for Kokkos residual objects.
virtual std::vector< const MooseVariableBase * > variables() const override
Returns all the variables that this object operates on.
virtual void computeResidualAndJacobian() override
Compute this object's contribution to the residual and Jacobian simultaneously.
std::vector< MooseVariableFieldBase * > getMooseVariables(Moose::VarFieldType field_type)
Get the MOOSE variables from the 'variable' or 'variables' parameter.
Scalar< const Real > _t_old
Old time.
ResidualObject(const InputParameters &parameters, Moose::VarFieldType field_type, bool nodal=false)
Constructor.
std::unique_ptr< DispatcherBase > _residual_dispatcher
Kokkos functor dispatchers.
Scalar< Real > _t
TODO: Move to TransientInterface.
Scalar< Real > _dt_old
Size of the old 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.
ResidualObject(const ResidualObject &object)
Copy constructor for parallel dispatch.
Variable _kokkos_var
Kokkos variable.
Thread _thread
Kokkos thread object.
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) const
Accumulate local elemental Jacobian contribution to tagged matrices.
KOKKOS_FUNCTION void accumulateTaggedElementalResidual(const Real local_re, const ContiguousElementID elem, const unsigned int i, const unsigned int comp) const
Accumulate local elemental residual contribution to tagged vectors.
const unsigned int _dimension
Mesh dimension.
static InputParameters validParams()
KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add, const Real local_ke, const ContiguousNodeID node, const unsigned int jvar, const unsigned int comp) const
Accumulate or set local nodal Jacobian contribution to tagged matrices.
std::unique_ptr< DispatcherBase > _offdiag_jacobian_scalar_dispatcher
static constexpr bool uses_precompute_hooks
Whether this object's hooks factor out the test function.
Array< TagID > _vector_tags
Tags this object operates on.
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.
virtual void computeOffDiagJacobian(unsigned int) override final
Computes this object's contribution to off-diagonal blocks of the system Jacobian matrix.
static constexpr bool supports_scalar_jacobian
Whether this object has computeQpOffDiagJacobianScalar() hook.
KOKKOS_FUNCTION void computeJacobianInternal(AssemblyDatum &datum, function body) const
The common loop structure template for computing elemental Jacobian.
Scalar< Real > _dt
Time step size.
std::unique_ptr< DispatcherBase > _offdiag_jacobian_dispatcher
virtual const MooseVariableBase & variable() const override
Returns the variable that this object operates on.
std::unique_ptr< DispatcherBase > _jacobian_dispatcher
KOKKOS_FUNCTION void accumulateTaggedNodalResidual(const bool add, const Real local_re, const ContiguousNodeID node, const unsigned int comp) const
Accumulate or set local nodal residual contribution to tagged vectors.
Scalar< int > _t_step
The number of the time step.
KOKKOS_FUNCTION void computeResidualInternal(AssemblyDatum &datum, function body) const
The common loop structure template for computing elemental residual.
const std::vector< MooseVariableFieldBase * > _vars
MOOSE variables.
The Kokkos wrapper class that can hold the reference of an arithmetic scalar variable.
The Kokkos thread object that aids in converting the one-dimensional thread index into multi-dimensio...
The Kokkos variable object that carries the coupled variable and tag information.
KOKKOS_FUNCTION unsigned int var(unsigned int comp=0) const
Get the variable number of a component.
KOKKOS_FUNCTION unsigned int sys(unsigned int comp=0) const
Get the system number of a component.
This is the common base class for objects that give residual contributions.
virtual void computeResidual()=0
Compute this object's contribution to the residual.
virtual void computeJacobian()=0
Compute this object's contribution to the diagonal Jacobian entries.
KokkosSemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< MOOSE_AD_MAX_DOFS_PER_ELEM > > DNDerivativeType
constexpr unsigned int MAX_CACHED_DOF
Maximum number of DOFs to cache during residual and Jacobian computation.
ContiguousElementID id
Contiguous element ID.
Definition KokkosMesh.h:42