idaholab/moose: framework coverage diff

Base 4e5abd Head #31653 1b25b3
Total Total +/- New
Rate 85.99% 85.93% -0.05% 100.00%
Hits 124384 124624 +240 510
Misses 20272 20400 +128 0
Filename Stmts Miss Cover
framework/include/base/MooseObject.h -1 0 +100.00%
framework/include/functions/FunctionInterface.h +7 0 +100.00%
framework/include/functions/PiecewiseTabularBase.h -1 0 -100.00%
framework/include/functions/PiecewiseTabularInterface.h +1 0 +100.00%
framework/include/kokkos/auxkernels/KokkosFunctionAux.h +2 0 +100.00%
framework/include/kokkos/base/KokkosDatum.h 0 -1 +1.37%
framework/include/kokkos/base/KokkosFunctorRegistry.h +18 +5 +72.22%
framework/include/kokkos/base/KokkosFunctorWrapper.h +26 +26 +100.00%
framework/include/kokkos/base/KokkosUtils.h +2 0 +0.17%
framework/include/kokkos/functions/KokkosConstantFunction.h +5 +4 +20.00%
framework/include/kokkos/functions/KokkosFunction.h +13 +12 +7.69%
framework/include/kokkos/functions/KokkosFunctionWrapper.h +40 +12 +70.00%
framework/include/kokkos/functions/KokkosPiecewiseBase.h +3 0 +100.00%
framework/include/kokkos/functions/KokkosPiecewiseConstant.h +44 +25 +43.18%
framework/include/problems/FEProblemBase.h +15 +2 -0.13%
framework/src/base/Moose.C +3 0 +0.02%
framework/src/functions/Function.C -2 0 -0.52%
framework/src/functions/FunctionBase.C +13 +1 +92.31%
framework/src/functions/FunctionInterface.C -5 0 -5.95%
framework/src/functions/PiecewiseTabularBase.C -108 -4 -0.53%
framework/src/functions/PiecewiseTabularInterface.C +124 +6 +95.16%
framework/src/kokkos/actions/AddKokkosFunctionAction.K +15 +2 +86.67%
framework/src/kokkos/auxkernels/KokkosFunctionAux.K +10 +1 +90.00%
framework/src/kokkos/base/KokkosFunctor.K +17 +17 +100.00%
framework/src/kokkos/base/KokkosFunctorRegistry.K +4 0 +100.00%
framework/src/kokkos/functions/KokkosConstantFunction.K +10 +1 +90.00%
framework/src/kokkos/functions/KokkosFunction.K +19 +1 +94.74%
framework/src/kokkos/functions/KokkosFunctionInterface.K +24 +9 +62.50%
framework/src/kokkos/functions/KokkosPiecewiseBase.K +11 +6 +45.45%
framework/src/kokkos/functions/KokkosPiecewiseConstant.K +11 0 +100.00%
framework/src/kokkos/functions/KokkosPiecewiseTabularBase.K +25 +2 +92.00%
framework/src/kokkos/problems/KokkosFEProblemBase.K +16 +1 +0.36%
framework/src/problems/FEProblemBase.C +7 0 +0.02%
TOTAL +368 +128 -0.05%
code
coverage unchanged
code
coverage increased
code
coverage decreased
+
line added or modified

framework/include/base/MooseObject.h

62  
63  
64  
65 +
66  
67  
68  
   * - Moose::Kokkos::ResidualObject in KokkosResidualObject.K
   * - Moose::Kokkos::MaterialBase in KokkosMaterialBase.K
   */
  bool isKokkosObject() const { return parameters().isParamValid(MooseBase::kokkos_object_param); }
#endif

  // To get warnings tracked in the SolutionInvalidityOutput

framework/include/functions/FunctionInterface.h

160  
161  
162  
163 +
164  
165 +
166  
167  
168  
169  
170 +
171  
172 +
173  
174 +
175 +
176  
177  
178 +
179  
180  
181  
#ifdef MOOSE_KOKKOS_ENABLED
template <typename T>
const T &
FunctionInterface::getKokkosFunction(const std::string & name) const
{
  return getKokkosFunctionByName<T>(_fni_params.get<FunctionName>(name));
}

template <typename T>
const T &
FunctionInterface::getKokkosFunctionByName(const FunctionName & name) const
{
  auto function = dynamic_cast<const T *>(getKokkosFunctionByNameHelper(name));

  if (!function)
    _fni_object.mooseError(
        "Kokkos function '", name, "' is not of type '", MooseUtils::prettyCppType<T>(), "'");

  return *function;
}
#endif

framework/include/functions/PiecewiseTabularInterface.h

25  
26  
27  
28 +
29  
30  
31  

protected:
  /// Returns whether the raw data has been loaded already
  bool isRawDataLoaded() const { return _raw_data_loaded; }

  /// Reads data from supplied CSV file.
  void buildFromFile(const libMesh::Parallel::Communicator & comm);

framework/include/kokkos/auxkernels/KokkosFunctionAux.h

19  
20  
21  
22 +
23  
24 +
25  
26  
27  

  KokkosFunctionAux(const InputParameters & parameters);

  KOKKOS_FUNCTION Real computeValue(const unsigned int qp, AssemblyDatum & datum) const
  {
    return _func.value(_t, datum.q_point(qp));
  }

protected:

framework/include/kokkos/base/KokkosDatum.h

155  
156  
157  
158  
159  
160  
161  
    if (!isNodal())
      reinitTransform(qp);
    else
      _xyz = _assembly.kokkosMesh().getNodePoint(_node);

    return _xyz;
  }

framework/include/kokkos/base/KokkosFunctorRegistry.h

20  
21  
22  
23 +
24  
25  
26  
class FunctorRegistryEntryBase
{
public:
  virtual ~FunctorRegistryEntryBase() {}
  /**
   * Build a host wrapper for this functor
   * @param object The pointer to the functor
32  
33  
34  
35 +
36  
37 +
38  
39  
40  
41  
42  
43  
44 +
45  
46  
47  
class FunctorRegistryEntry : public FunctorRegistryEntryBase
{
public:
  std::unique_ptr<FunctorWrapperHostBase> build(const void * object) const override final
  {
    return std::make_unique<FunctorWrapperHost<Object>>(object);
  }
};

class FunctionRegistryEntryBase
{
public:
  virtual ~FunctionRegistryEntryBase() {}
  /**
   * Build a host wrapper for this function
   * @param object The pointer to the function
53  
54  
55  
56 +
57  
58 +
59  
60  
61  
62  
63  
64 +
65  
66  
67  
class FunctionRegistryEntry : public FunctionRegistryEntryBase
{
public:
  std::unique_ptr<FunctionWrapperHostBase> build(const void * object) const override final
  {
    return std::make_unique<FunctionWrapperHost<Object>>(object);
  }
};
class FunctorRegistry
{
public:
  FunctorRegistry() = default;

  FunctorRegistry(FunctorRegistry const &) = delete;
  FunctorRegistry & operator=(FunctorRegistry const &) = delete;
75  
76  
77  
78 +
79  
80 +
81  
82 +
83  
84  
85  
   * @param name The registered functor type name
   */
  template <typename Object>
  static char addFunctor(const std::string & name)
  {
    getRegistry()._functors[name] = std::make_unique<FunctorRegistryEntry<Object>>();

    return 0;
  }

  /**
88  
89  
90  
91 +
92  
93 +
94  
95 +
96  
97  
98  
   * @param name The registered function type name
   */
  template <typename Object>
  static char addFunction(const std::string & name)
  {
    getRegistry()._functions[name] = std::make_unique<FunctionRegistryEntry<Object>>();

    return 0;
  }

  /**
119  
120  
121  
122 +
123  
124  
125 +
126 +
127 +
128  
129  
130  
131 +
132  
133  
134  
   * @param name The registered function type name
   * @returns The host wrapper
   */
  static std::unique_ptr<FunctionWrapperHostBase> buildFunction(const void * object,
                                                                const std::string & name)
  {
    auto it = getRegistry()._functions.find(name);
    if (it == getRegistry()._functions.end())
      mooseError("Kokkos function not registered for type '",
                 name,
                 "'. Double check that you used Kokkos-specific registration macro.");

    return it->second->build(object);
  }

private:

framework/include/kokkos/base/KokkosFunctorWrapper.h

22  
23  
24  
25 +
26 +
27  
28  
29  
class FunctorWrapperDeviceBase
{
public:
  KOKKOS_FUNCTION FunctorWrapperDeviceBase() {}
  KOKKOS_FUNCTION virtual ~FunctorWrapperDeviceBase() {}
};

template <typename Object>
32  
33  
34  
35 +
36  
37  
38  
  friend class FunctorWrapperHost<Object>;

public:
  KOKKOS_FUNCTION FunctorWrapperDevice() {}

protected:
  /**
44  
45  
46  
47 +
48  
49  
50  
class FunctorWrapperHostBase
{
public:
  virtual ~FunctorWrapperHostBase() {}

  /**
   * Allocate device functor and wrapper
69  
70  
71  
72 +
73  
74  
75  
   * Constructor
   * @param functor Pointer to the functor
   */
  FunctorWrapperHost(const void * functor) : _functor_host(*static_cast<const Object *>(functor)) {}
  ~FunctorWrapperHost();

  FunctorWrapperDeviceBase * allocate() final;
93  
94  
95  
96 +
97  
98  
99 +
100 +
101  
102  
103 +
104 +
105  
106  
107 +
108 +
109  
110  
111 +
112 +
113  
114 +
115  
116  
117  
118  
119 +
120  
121  
122 +
123  
124  
125 +
126 +
127 +
128  
129  
130  
131 +
132  
133 +
134 +
135  
136  
137 +
138  
139 +
140 +
141  
142  
143  

template <typename Object>
FunctorWrapperDeviceBase *
FunctorWrapperHost<Object>::allocate()
{
  // Allocate storage for device wrapper on device
  auto wrapper_device = static_cast<FunctorWrapperDevice<Object> *>(
      ::Kokkos::kokkos_malloc<ExecSpace::memory_space>(sizeof(FunctorWrapperDevice<Object>)));

  // Allocate device wrapper on device using placement new to populate vtable with device pointers
  ::Kokkos::parallel_for(
      1, KOKKOS_LAMBDA(const int) { new (wrapper_device) FunctorWrapperDevice<Object>(); });

  // Allocate storage for functor on device
  _functor_device =
      static_cast<Object *>(::Kokkos::kokkos_malloc<ExecSpace::memory_space>(sizeof(Object)));

  // Let device wrapper point to the copy
  ::Kokkos::Impl::DeepCopy<MemSpace, ::Kokkos::HostSpace>(
      &(wrapper_device->_functor), &_functor_device, sizeof(Object *));

  return wrapper_device;
}

template <typename Object>
void
FunctorWrapperHost<Object>::copyFunctor()
{
  // Make a copy of functor on host to trigger copy constructor
  _functor_copy = std::make_unique<Object>(_functor_host);

  // Copy functor to device
  ::Kokkos::Impl::DeepCopy<MemSpace, ::Kokkos::HostSpace>(
      _functor_device, _functor_copy.get(), sizeof(Object));
}

template <typename Object>
void
FunctorWrapperHost<Object>::freeFunctor()
{
  _functor_copy.reset();
}

template <typename Object>
FunctorWrapperHost<Object>::~FunctorWrapperHost()
{
  ::Kokkos::kokkos_free<ExecSpace::memory_space>(_functor_device);
}

} // namespace Kokkos
} // namespace Moose

framework/include/kokkos/base/KokkosUtils.h

25  
26  
27  
28 +
29  
30 +
31  
32  
33  
 */
template <typename T>
KOKKOS_INLINE_FUNCTION T
sign(T x)
{
  return x >= 0.0 ? 1.0 : -1.0;
}

/**

framework/include/kokkos/functions/KokkosConstantFunction.h

23  
24  
25  
26 +
27 +
28 +
29 +
30  
31 +
32  
33  
34  

  KokkosConstantFunction(const InputParameters & parameters);

  KOKKOS_FUNCTION Real value(Real /* t */, Real3 /* p */) const { return _value; }
  KOKKOS_FUNCTION Real timeDerivative(Real /* t */, Real3 /* p */) const { return 0; }
  KOKKOS_FUNCTION Real3 gradient(Real /* t */, Real3 /* p */) const { return Real3(0); }
  KOKKOS_FUNCTION Real timeIntegral(Real t1, Real t2, Real3 /* p */) const
  {
    return _value * (t2 - t1);
  }

protected:

framework/include/kokkos/functions/KokkosFunction.h

45  
46  
47  
48 +
49  
50  
51 +
52  
53  
54  
55  
56 +
57  
58  
59 +
60  
61  
62  
63  
64 +
65  
66  
67 +
68  
69  
70  
  /**
   *
   */
  KOKKOS_FUNCTION Real3 gradient(Real /* t */, Real3 /* p */) const
  {
    KOKKOS_ASSERT(false);
    return Real3(0);
  }
  /**
   *
   */
  KOKKOS_FUNCTION Real3 curl(Real /* t */, Real3 /* p */) const
  {
    KOKKOS_ASSERT(false);
    return Real3(0);
  }
  /**
   *
   */
  KOKKOS_FUNCTION Real div(Real /* t */, Real3 /* p */) const
  {
    KOKKOS_ASSERT(false);
    return 0;
  }
  /**
   *
77  
78  
79  
80 +
81  
82  
83 +
84  
85  
86  
87  
88 +
89  
90  
91 +
92  
93  
94  
95  
96 +
97  
98  
99 +
100  
101  
102  
  /**
   *
   */
  KOKKOS_FUNCTION Real timeIntegral(Real /* t1 */, Real /* t2 */, Real3 /* p */) const
  {
    KOKKOS_ASSERT(false);
    return 0;
  }
  /**
   *
   */
  KOKKOS_FUNCTION Real integral() const
  {
    KOKKOS_ASSERT(false);
    return 0;
  }
  /**
   *
   */
  KOKKOS_FUNCTION Real average() const
  {
    KOKKOS_ASSERT(false);
    return 0;
  }
};

107  
108  
109  
110 +
111  
112  
113  
  Function(const Function & function);
  ~Function();

  KOKKOS_FUNCTION Real value(Real t, Real3 p) const { return _wrapper_device->value(t, p); }
  KOKKOS_FUNCTION Real3 gradient(Real t, Real3 p) const { return _wrapper_device->gradient(t, p); }
  KOKKOS_FUNCTION Real3 curl(Real t, Real3 p) const { return _wrapper_device->curl(t, p); }
  KOKKOS_FUNCTION Real div(Real t, Real3 p) const { return _wrapper_device->div(t, p); }

framework/include/kokkos/functions/KokkosFunctionWrapper.h

22  
23  
24  
25 +
26 +
27  
28  
29  
class FunctionWrapperDeviceBase
{
public:
  KOKKOS_FUNCTION FunctionWrapperDeviceBase() {}
  KOKKOS_FUNCTION virtual ~FunctionWrapperDeviceBase() {}

  KOKKOS_FUNCTION virtual Real value(Real t, Real3 p) const = 0;
  KOKKOS_FUNCTION virtual Real3 gradient(Real t, Real3 p) const = 0;
41  
42  
43  
44 +
45  
46 +
47  
48 +
49  
50 +
51  
52 +
53  
54 +
55 +
56 +
57  
58 +
59  
60 +
61  
62 +
63  
64 +
65 +
66  
67  
68  
  friend class FunctionWrapperHost<Object>;

public:
  KOKKOS_FUNCTION FunctionWrapperDevice() {}

  KOKKOS_FUNCTION Real value(Real t, Real3 p) const override final
  {
    return _function->value(t, p);
  }
  KOKKOS_FUNCTION Real3 gradient(Real t, Real3 p) const override final
  {
    return _function->gradient(t, p);
  }
  KOKKOS_FUNCTION Real3 curl(Real t, Real3 p) const override final { return _function->curl(t, p); }
  KOKKOS_FUNCTION Real div(Real t, Real3 p) const override final { return _function->div(t, p); }
  KOKKOS_FUNCTION Real timeDerivative(Real t, Real3 p) const override final
  {
    return _function->timeDerivative(t, p);
  }
  KOKKOS_FUNCTION Real timeIntegral(Real t1, Real t2, Real3 p) const override final
  {
    return _function->timeIntegral(t1, t2, p);
  }
  KOKKOS_FUNCTION Real integral() const override final { return _function->integral(); }
  KOKKOS_FUNCTION Real average() const override final { return _function->average(); }

protected:
  /**
74  
75  
76  
77 +
78  
79  
80  
class FunctionWrapperHostBase
{
public:
  virtual ~FunctionWrapperHostBase() {}

  /**
   * Allocate device function and wrapper
99  
100  
101  
102 +
103 +
104  
105 +
106  
107  
108  
   * Constructor
   * @param function Pointer to the function
   */
  FunctionWrapperHost(const void * function)
    : _function_host(*static_cast<const Object *>(function))
  {
  }
  ~FunctionWrapperHost();

  FunctionWrapperDeviceBase * allocate() final;
126  
127  
128  
129 +
130  
131  
132 +
133 +
134  
135  
136 +
137 +
138  
139  
140 +
141 +
142  
143  
144 +
145 +
146  
147 +
148  
149  
150  
151  
152 +
153  
154  
155 +
156  
157  
158 +
159 +
160 +
161  
162  
163  
164 +
165  
166 +
167 +
168  
169  
170 +
171  
172 +
173 +
174  
175  
176  

template <typename Object>
FunctionWrapperDeviceBase *
FunctionWrapperHost<Object>::allocate()
{
  // Allocate storage for device wrapper on device
  auto wrapper_device = static_cast<FunctionWrapperDevice<Object> *>(
      ::Kokkos::kokkos_malloc<ExecSpace::memory_space>(sizeof(FunctionWrapperDevice<Object>)));

  // Allocate device wrapper on device using placement new to populate vtable with device pointers
  ::Kokkos::parallel_for(
      1, KOKKOS_LAMBDA(const int) { new (wrapper_device) FunctionWrapperDevice<Object>(); });

  // Allocate storage for function on device
  _function_device =
      static_cast<Object *>(::Kokkos::kokkos_malloc<ExecSpace::memory_space>(sizeof(Object)));

  // Let device wrapper point to the copy
  ::Kokkos::Impl::DeepCopy<MemSpace, ::Kokkos::HostSpace>(
      &(wrapper_device->_function), &_function_device, sizeof(Object *));

  return wrapper_device;
}

template <typename Object>
void
FunctionWrapperHost<Object>::copyFunction()
{
  // Make a copy of function on host to trigger copy constructor
  _function_copy = std::make_unique<Object>(_function_host);

  // Copy function to device
  ::Kokkos::Impl::DeepCopy<MemSpace, ::Kokkos::HostSpace>(
      _function_device, _function_copy.get(), sizeof(Object));
}

template <typename Object>
void
FunctionWrapperHost<Object>::freeFunction()
{
  _function_copy.reset();
}

template <typename Object>
FunctionWrapperHost<Object>::~FunctionWrapperHost()
{
  ::Kokkos::kokkos_free<ExecSpace::memory_space>(_function_device);
}

} // namespace Kokkos
} // namespace Moose

framework/include/kokkos/functions/KokkosPiecewiseBase.h

23  
24  
25  
26 +
27 +
28 +
29  
30  
31  

  KokkosPiecewiseBase(const InputParameters & parameters);

  KOKKOS_FUNCTION auto functionSize() const { return _raw_x.size(); }
  KOKKOS_FUNCTION Real domain(const unsigned int i) const { return _raw_x[i]; }
  KOKKOS_FUNCTION Real range(const unsigned int i) const { return _raw_y[i]; }

  /**
   * Provides a means for explicitly setting the x and y data. This must

framework/include/kokkos/functions/KokkosPiecewiseConstant.h

25  
26  
27  
28 +
29  
30  
31  
  KokkosPiecewiseConstant(const InputParameters & parameters);

  KOKKOS_FUNCTION Real value(Real t, Real3 p) const;
  KOKKOS_FUNCTION Real timeDerivative(Real /* t */, Real3 /* p */) const { return 0; }
  KOKKOS_FUNCTION Real integral() const;
  KOKKOS_FUNCTION Real average() const;

35  
36  
37  
38 +
39  
40  
41  
42 +
43  
44 +
45 +
46  
47  
48 +
49 +
50 +
51 +
52 +
53 +
54 +
55 +
56 +
57 +
58 +
59 +
60 +
61 +
62 +
63 +
64  
65 +
66  
67 +
68 +
69 +
70 +
71 +
72 +
73 +
74 +
75 +
76 +
77  
78  
79 +
80  
81  
82  
83 +
84  
85 +
86  
87 +
88  
89 +
90 +
91  
92 +
93  
94 +
95 +
96  
97 +
98  
99  
100  
101 +
102  
103 +
104  
105  
};

KOKKOS_FUNCTION inline Real
KokkosPiecewiseConstant::value(Real t, Real3 p) const
{
  using Moose::Kokkos::Utils::sign;

  const Real x = _has_axis ? p(_axis) : t;

  const auto len = functionSize();
  const Real tolerance = 1.0e-14;

  // endpoint cases
  if ((_direction == Direction::LEFT && x < (1 + tolerance * sign(domain(0))) * domain(0)) ||
      (_direction == Direction::RIGHT && x < (1 - tolerance * sign(domain(0))) * domain(0)) ||
      (_direction == Direction::LEFT_INCLUSIVE &&
       x < (1 - tolerance * sign(domain(0))) * domain(0)) ||
      (_direction == Direction::RIGHT_INCLUSIVE &&
       x < (1 + tolerance * sign(domain(0))) * domain(0)))
    return _scale_factor * range(0);
  else if ((_direction == Direction::LEFT &&
            x > (1 + tolerance * sign(domain(len - 1))) * domain(len - 1)) ||
           (_direction == Direction::RIGHT &&
            x > (1 - tolerance * sign(domain(len - 1))) * domain(len - 1)) ||
           (_direction == Direction::LEFT_INCLUSIVE &&
            x > (1 - tolerance * sign(domain(len - 1))) * domain(len - 1)) ||
           (_direction == Direction::RIGHT_INCLUSIVE &&
            x > (1 + tolerance * sign(domain(len - 1))) * domain(len - 1)))
    return _scale_factor * range(len - 1);

  for (unsigned int i = 1; i < len; ++i)
  {
    if (_direction == Direction::LEFT && x < (1 + tolerance * sign(domain(i))) * domain(i))
      return _scale_factor * range(i - 1);
    else if (_direction == Direction::LEFT_INCLUSIVE &&
             x < (1 - tolerance * sign(domain(i))) * domain(i))
      return _scale_factor * range(i - 1);
    else if ((_direction == Direction::RIGHT && x < (1 - tolerance * sign(domain(i))) * domain(i)))
      return _scale_factor * range(i);
    else if ((_direction == Direction::RIGHT_INCLUSIVE &&
              x < (1 + tolerance * sign(domain(i))) * domain(i)))
      return _scale_factor * range(i);
  }

  return 0.0;
}

KOKKOS_FUNCTION inline Real
KokkosPiecewiseConstant::integral() const
{
  const auto len = functionSize();

  unsigned int offset = 0;

  if (_direction == Direction::RIGHT || _direction == Direction::RIGHT_INCLUSIVE)
    offset = 1;

  Real sum = 0;

  for (unsigned int i = 0; i < len - 1; ++i)
    sum += range(i + offset) * (domain(i + 1) - domain(i));

  return _scale_factor * sum;
}

KOKKOS_FUNCTION inline Real
KokkosPiecewiseConstant::average() const
{
  return integral() / (domain(functionSize() - 1) - domain(0));
}

framework/include/materials/MaterialPropertyInterface.h

917  
918  
919  
920 +
921  
922  
923  
                                                            const unsigned int state)
{
  if (_is_kokkos_object)
    _mi_moose_object.mooseError(
        "Attempted to retrieve a standard MOOSE material property from a Kokkos object.");

  if (_use_interpolated_state)
980  
981  
982  
983 +
984  
985  
986  
MaterialPropertyInterface::getKokkosMaterialPropertyByName(const std::string & prop_name_in)
{
  if (!_is_kokkos_object)
    _mi_moose_object.mooseError(
        "Attempted to retrieve a Kokkos material property from a standard MOOSE object.");

  if constexpr (std::is_same_v<T, Real>)

framework/include/problems/FEProblemBase.h

3588  
3589  
3590  
3591 +
3592  
3593 +
3594  
3595  
3596 +
3597  
3598  
3599  
3600 +
3601  
3602 +
3603 +
3604 +
3605 +
3606  
3607  
3608 +
3609 +
3610 +
3611  
3612 +
3613 +
3614 +
3615  
3616 +
3617  
3618  
3619  
#ifdef MOOSE_KOKKOS_ENABLED
template <typename T>
T &
FEProblemBase::getKokkosFunction(const std::string & name)
{
  if (!hasKokkosFunction(name))
  {
    // If we didn't find a function, it might be a default function, attempt to construct one now
    std::istringstream ss(name);
    Real real_value;

    // First see if it's just a constant. If it is, build a ConstantFunction
    if (ss >> real_value && ss.eof())
    {
      InputParameters params = _factory.getValidParams("KokkosConstantFunction");
      params.set<Real>("value") = real_value;
      addKokkosFunction("KokkosConstantFunction", ss.str(), params);
    }

    // Try once more
    if (!hasKokkosFunction(name))
      mooseError("Unable to find Kokkos function '" + name, "'");
  }

  auto * const ret = dynamic_cast<T *>(_kokkos_functions.getActiveObject(name).get());
  if (!ret)
    mooseError("No Kokkos function named '", name, "' of appropriate type");

  return *ret;
}
#endif

framework/src/base/Moose.C

153  
154  
155  
156 +
157  
158  
159  

  registerMooseObjectTask("add_function",                 Function,                  false);
#ifdef MOOSE_KOKKOS_ENABLED
  appendMooseObjectTask  ("add_function",                 KokkosFunction);
#endif

  registerMooseObjectTask("add_distribution",             Distribution,              false);
588  
589  
590  
591 +
592 +
593  
594  
595  
  syntax.registerSyntaxType("Functions/*", "FunctionName");

#ifdef MOOSE_KOKKOS_ENABLED
  registerSyntax("AddKokkosFunctionAction", "KokkosFunctions/*");
  syntax.registerSyntaxType("KokkosFunctions/*", "FunctionName");
#endif

  registerSyntax("AddMeshDivisionAction", "MeshDivisions/*");

framework/src/functions/Function.C

15  
16  
17  
18 +
19  
20  
21  
22  
23  
24  
25 +
26  
27  
28  
InputParameters
Function::validParams()
{
  InputParameters params = FunctionBase::validParams();
  params.registerBase("Function");

  return params;
}

Function::Function(const InputParameters & parameters)
  : FunctionBase(parameters), Moose::FunctorBase<Real>(name())
{
}

framework/src/functions/FunctionBase.C

13  
14  
15  
16 +
17  
18 +
19 +
20  
21  
22 +
23  
24 +
25 +
26  
27 +
28  
29  
30  
{

InputParameters
FunctionBase::validParams()
{
  InputParameters params = MooseObject::validParams();
  params += SetupInterface::validParams();

  // Functions should be executed on the fly
  params.suppressParameter<ExecFlagEnum>("execute_on");

  return params;
}

FunctionBase::FunctionBase(const InputParameters & parameters)
  : MooseObject(parameters),
    SetupInterface(this),
    TransientInterface(this),
32  
33  
34  
35 +
36  
37 +
38  
39  
40 +
41  
42  
43  
    UserObjectInterface(this),
    Restartable(this, "Functions"),
    MeshChangedInterface(parameters),
    ScalarCoupleable(this)
{
}

#ifdef MOOSE_KOKKOS_ENABLED
FunctionBase::FunctionBase(const FunctionBase & object, const Moose::Kokkos::FunctorCopy & key)
  : MooseObject(object, key),
    SetupInterface(object, key),
    TransientInterface(object, key),
45  
46  
47  
48 +
49  
50 +
51  
52  
53 +
54  
55  
56  
    UserObjectInterface(object, key),
    Restartable(object, key),
    MeshChangedInterface(object, key),
    ScalarCoupleable(object, key)
{
}
#endif

FunctionBase::~FunctionBase() {}

} // namespace Moose

framework/src/functions/FunctionInterface.C

20  
21  
22  
23 +
24 +
25  
26  
27  
}

FunctionInterface::FunctionInterface(const MooseObject * moose_object)
  : _fni_object(*moose_object),
    _fni_params(moose_object->parameters()),
    _fni_feproblem(*_fni_params.getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
    _fni_tid(_fni_params.have_parameter<THREAD_ID>("_tid") ? _fni_params.get<THREAD_ID>("_tid") : 0)
{
30  
31  
32  
33 +
34  
35  
36  
const Function &
FunctionInterface::getFunction(const std::string & name) const
{
  return getFunctionByName(_fni_params.get<FunctionName>(name));
}

const Function &

framework/src/functions/PiecewiseConstant.C

19  
20  
21  
22 +
23  
24  
25  
  MooseEnum direction("LEFT RIGHT LEFT_INCLUSIVE RIGHT_INCLUSIVE", "LEFT");
  params.addParam<MooseEnum>(
      "direction", direction, "Direction to look to find value: " + direction.getRawNames());
  params.addClassDescription("Defines piece-wise constant data using a set of x-y data pairs");
  return params;
}

framework/src/functions/PiecewiseTabularBase.C

14  
15  
16  
17 +
18  
19  
20  
21  
22  
23  
24  
25  
26  
27 +
28 +
29  
30  
31  
32 +
33  
34  
35  
PiecewiseTabularBase::validParams()
{
  InputParameters params = PiecewiseBase::validParams();
  params += PiecewiseTabularInterface::validParams();

  params.addParam<Real>("scale_factor", 1.0, "Scale factor to be applied to the output values");
  params.declareControllable("scale_factor");

  return params;
}

PiecewiseTabularBase::PiecewiseTabularBase(const InputParameters & parameters)
  : PiecewiseBase(parameters),
    PiecewiseTabularInterface(*this, _raw_x, _raw_y),
    _scale_factor(getParam<Real>("scale_factor"))
{
  // load the data
  if (isParamValid("data_file"))
    buildFromFile(_communicator);
  else if (isParamValid("x") && isParamValid("y"))
    buildFromXandY();
  else if (isParamValid("xy_data"))
46  
47  
48  
49 +
50  
51  
  if (!isParamValid("json_uo"))
    return;
  else
    buildFromJSON(getUserObject<JSONFileReader>("json_uo"));
}

framework/src/functions/PiecewiseTabularInterface.C

14  
15  
16  
17 +
18  
19 +
20  
21  
22 +
23 +
24  
25  
26  
27 +
28  
29 +
30 +
31  
32  
33 +
34 +
35 +
36 +
37  
38 +
39  
40 +
41 +
42 +
43 +
44  
45  
46  
47 +
48 +
49  
50 +
51  
52  
53 +
54 +
55  
56  
57 +
58  
59 +
60 +
61  
62 +
63  
64 +
65 +
66 +
67 +
68 +
69 +
70  
71  
72 +
73 +
74  
75  
76 +
77 +
78 +
79  
80 +
81  
82  
83 +
84 +
85  
86 +
87 +
88 +
89 +
90 +
91 +
92  
93  
94  
95 +
96 +
97 +
98  
99  
100  
101 +
102  
103  
104 +
105  
106  
107 +
108 +
109  
110  
111  
112  
113 +
114 +
115  
116 +
117 +
118  
119  
120  
121 +
122  
123  
124  
125 +
126 +
127 +
128 +
129  
130 +
131 +
132  
133 +
134 +
135 +
136  
137  
138  
139  
140  
141 +
142  
143  
144 +
145 +
146 +
147  
148 +
149  
150 +
151 +
152 +
153 +
154  
155 +
156 +
157  
158  
159  
160  
161  
162 +
163  
164 +
165  
166 +
167 +
168  
169  
170  
#include "libmesh/int_range.h"

InputParameters
PiecewiseTabularInterface::validParams()
{
  InputParameters params = emptyInputParameters();

  // Parameters shared across all data input methods
  MooseEnum axis("x=0 y=1 z=2");
  params.addParam<MooseEnum>(
      "axis", axis, "The axis used (x, y, or z) if this is to be a function of position");

  // Data from input file parameters
  params.addParam<std::vector<Real>>("xy_data",
                                     "All function data, supplied in abscissa, ordinate pairs");
  params.addParam<std::vector<Real>>("x", "The abscissa values");
  params.addParam<std::vector<Real>>("y", "The ordinate values");

  // Data from CSV file parameters
  params.addParam<FileName>("data_file", "File holding CSV data");
  params.addParam<unsigned int>("x_index_in_file", 0, "The abscissa index in the data file");
  params.addParam<unsigned int>("y_index_in_file", 1, "The ordinate index in the data file");
  params.addParam<std::string>(
      "x_title", "The title of the column/row containing the x data in the data file");
  params.addParam<std::string>(
      "y_title", "The title of the column/row containing the y data in the data file");
  params.addParam<bool>(
      "xy_in_file_only", true, "If the data file only contains abscissa and ordinate data");
  MooseEnum format("columns=0 rows=1", "rows");
  params.addParam<MooseEnum>(
      "format", format, "Format of csv data file that is in either in columns or rows");

  // Data from JSON parameters
  params.addParam<UserObjectName>("json_uo", "JSONFileReader holding the data");
  params.addParam<std::vector<std::string>>(
      "x_keys", "Ordered vector of keys in the JSON tree to obtain the abscissa");
  params.addParam<std::vector<std::string>>(
      "y_keys", "Ordered vector of keys in the JSON tree to obtain the ordinate");

  params.addParamNamesToGroup("xy_data x y", "Data from input file");
  params.addParamNamesToGroup(
      "data_file x_index_in_file y_index_in_file x_title y_title xy_in_file_only format",
      "Data from CSV file");
  params.addParamNamesToGroup("json_uo x_keys y_keys", "Data from JSON");

  return params;
}

PiecewiseTabularInterface::PiecewiseTabularInterface(const MooseObject & object,
                                                     std::vector<Real> & data_x,
                                                     std::vector<Real> & data_y)
  : _has_axis(object.isParamValid("axis")),
    _object(object),
    _parameters(object.parameters()),
    _data_x(data_x),
    _data_y(data_y)
{
  // determine function argument
  if (_has_axis)
    _axis = _parameters.get<MooseEnum>("axis");

  // Check all parameters for inconsistencies
  if (_parameters.isParamValid("data_file") + _parameters.isParamValid("json_uo") +
          (_parameters.isParamValid("x") || _parameters.isParamValid("y")) +
          _parameters.isParamValid("xy_data") >
      1)
    _object.mooseError(
        "Either 'data_file' or 'json_uo' or 'x' and 'y' or 'xy_data' must be specified "
        "exclusively.");
  if ((_parameters.isParamValid("x") + _parameters.isParamValid("y")) % 2 != 0)
    _object.mooseError(
        "Both 'x' and 'y' parameters or neither (for another input method) must be specified");
  if (!_parameters.isParamValid("data_file") &&
      (_parameters.isParamSetByUser("x_index_in_file") ||
       _parameters.isParamSetByUser("y_index_in_file") || _parameters.isParamValid("x_title") ||
       _parameters.isParamValid("y_title") || _parameters.isParamSetByUser("xy_in_file_only") ||
       _parameters.isParamSetByUser("format")))
    _object.mooseError(
        "A parameter was passed for an option using data from a CSV file but the "
        "'data_file' parameter has not been set. This is not allowed. Please check the parameter "
        "groups in the documentation for the list of parameters for each data input method.");
  if (!_parameters.isParamValid("json_uo") &&
      (_parameters.isParamValid("x_keys") || _parameters.isParamValid("y_keys")))
    _object.mooseError(
        "A parameter was passed for a JSON input option but the 'json_uo' parameter has not "
        "been set. This is not allowed. Please check the parameter groups in the "
        "documentation for the list of parameters for each data input method.");
}

void
PiecewiseTabularInterface::buildFromFile(const libMesh::Parallel::Communicator & comm)
{
  // Input parameters
  const auto & data_file_name = _parameters.get<FileName>("data_file");
  const MooseEnum format = _parameters.get<MooseEnum>("format");

  // xy_in_file_only does not make sense here as it restricts the file to exactly
  // two cows/columns, which is not a likely scenario when looking up data by name.
  // A wrong 'format' parameter would be caught by the failing name resolution anyways.
  bool xy_only = _parameters.get<bool>("xy_in_file_only");
  if (_parameters.isParamValid("x_title") || _parameters.isParamValid("y_title"))
  {
    if (_parameters.isParamSetByUser("xy_in_file_only") && xy_only)
      _parameters.paramError(
          "xy_in_file_only",
          "When accessing data through 'x_title' or 'y_title' this parameter should not be used");
    else
      xy_only = false;
  }

  // Read the data from CSV file
  MooseUtils::DelimitedFileReader reader(data_file_name, &comm);
  reader.setFormatFlag(format.getEnum<MooseUtils::DelimitedFileReader::FormatFlag>());
  reader.setComment("#");
  reader.read();

  const auto & columns = reader.getNames();
  const auto & data = reader.getData();

  if (data.size() > 2 && xy_only)
    _object.mooseError("In ",
                       _object.name(),
                       ": Read more than two ",
                       format,
                       " of data from file '",
                       data_file_name,
                       "'.  Did you mean to use \"format = ",
                       format == "columns" ? "rows" : "columns",
                       "\" or set \"xy_in_file_only\" to false?");

  unsigned int x_index = libMesh::invalid_uint;
  unsigned int y_index = libMesh::invalid_uint;
  const auto setIndex = [&](unsigned int & index, const std::string & prefix)
  {
    if (_parameters.isParamValid(prefix + "_title"))
    {
      const auto name = _parameters.get<std::string>(prefix + "_title");
      for (const auto i : index_range(columns))
        if (columns[i] == name)
          index = i;

      if (index == libMesh::invalid_uint)
        _parameters.paramError(prefix + "_title",
                               "None of the ",
                               format,
                               " in the data file has the title '",
                               name,
                               "'.");
    }
    else
      index = _parameters.get<unsigned int>(prefix + "_index_in_file");

    if (index >= data.size())
      _parameters.paramError(prefix + "_index_in_file",
                             "Index out-of-range of the available data in '",
                             data_file_name,
                             "', which contains ",
172  
173  
174  
175 +
176  
177 +
178 +
179  
180 +
181 +
182 +
183  
184  
185  
186 +
187 +
188  
189  
190 +
191 +
192  
193 +
194 +
195  
196  
197 +
198  
199 +
200 +
201 +
202 +
203 +
204 +
205 +
206  
207  
208 +
209 +
210 +
211 +
212  
213  
214 +
215  
216 +
217 +
218 +
219 +
220  
221  
222 +
223  
224 +
225 +
226 +
227 +
228 +
229  
230 +
231 +
232 +
233 +
234  
235 +
236 +
237  
238 +
239 +
240  
                             " ",
                             format,
                             " of data.");
  };

  setIndex(x_index, "x");
  setIndex(y_index, "y");

  if (x_index == y_index)
    _object.mooseError("In ",
                       _object.name(),
                       ": 'x_index_in_file' and 'y_index_in_file' are set to the same value.");

  // Update the input vectors to contained the desired data
  _data_x = reader.getData(x_index);
  _data_y = reader.getData(y_index);

  // Size mismatch error
  if (_data_x.size() != _data_y.size())
    _object.mooseError("In ", _object.name(), ": Lengths of x and y data do not match.");

  _raw_data_loaded = true;
}

void
PiecewiseTabularInterface::buildFromJSON(const JSONFileReader & json_uo)
{
  if (!_parameters.isParamValid("x_keys"))
    _object.mooseError("Missing 'x_keys' parameters for loading data from JSON");
  if (!_parameters.isParamValid("y_keys"))
    _object.mooseError("Missing 'y_keys' parameters for loading data from JSON");
  json_uo.getVector<Real>(_parameters.get<std::vector<std::string>>("x_keys"), _data_x);
  json_uo.getVector<Real>(_parameters.get<std::vector<std::string>>("y_keys"), _data_y);
  _raw_data_loaded = true;

  // Size mismatch error
  if (_data_x.size() != _data_y.size())
    _object.mooseError(
        "Lengths of x (", _data_x.size(), ") and y (", _data_y.size(), ") data do not match.");
}

void
PiecewiseTabularInterface::buildFromXandY()
{
  _data_x = _parameters.get<std::vector<Real>>("x");
  _data_y = _parameters.get<std::vector<Real>>("y");
  _raw_data_loaded = true;
}

void
PiecewiseTabularInterface::buildFromXY()
{
  const auto & xy = _parameters.get<std::vector<Real>>("xy_data");
  const auto xy_size = xy.size();
  if (xy_size % 2 != 0)
    _object.mooseError(
        "In ", _object.name(), ": Length of data provided in 'xy_data' must be a multiple of 2.");

  const auto data_size = xy_size / 2;
  _data_x.resize(data_size);
  _data_y.resize(data_size);
  for (const auto i : make_range(data_size))
  {
    _data_x[i] = xy[2 * i];
    _data_y[i] = xy[2 * i + 1];
  }
  _raw_data_loaded = true;
}

framework/src/interfaces/BlockRestrictable.C

88  
89  
90  
91 +
92  
93  
94  
  if (_blk_feproblem != NULL)
  {
#ifdef MOOSE_KOKKOS_ENABLED
    if (_moose_object->isKokkosObject())
      _blk_material_data = &_blk_feproblem->getKokkosMaterialData(Moose::BLOCK_MATERIAL_DATA);
    else
#endif
187  
188  
189  
190 +
191  
192  
193  
    _blk_dim = _blk_mesh->dimension();

#ifdef MOOSE_KOKKOS_ENABLED
  if (moose_object->isKokkosObject())
    initializeKokkosBlockRestrictable(_blk_mesh->getKokkosMesh());
#endif
}

framework/src/interfaces/BoundaryRestrictable.C

44  
45  
46  
47 +
48  
49  
50  
    _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
    _bnd_material_data(
#ifdef MOOSE_KOKKOS_ENABLED
        moose_object->isKokkosObject()
            ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
            :
#endif
69  
70  
71  
72 +
73  
74  
75  
    _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
    _bnd_material_data(
#ifdef MOOSE_KOKKOS_ENABLED
        moose_object->isKokkosObject()
            ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
            :
#endif
186  
187  
188  
189 +
190  
191  
192  
  }

#ifdef MOOSE_KOKKOS_ENABLED
  if (_moose_object.isKokkosObject())
    initializeKokkosBoundaryRestrictable(_bnd_mesh);
#endif
}

framework/src/kokkos/actions/AddKokkosFunctionAction.K

13  
14  
15  
16 +
17  
18 +
19 +
20 +
21 +
22  
23 +
24 +
25  
26 +
27  
28  
29 +
30  
31 +
32 +
33 +
34 +
35 +
36 +
37  
registerMooseAction("MooseApp", AddKokkosFunctionAction, "add_function");

InputParameters
AddKokkosFunctionAction::validParams()
{
  InputParameters params = KokkosObjectAction::validParams();
  params.addClassDescription("Add a Kokkos Function object to the simulation.");
  return params;
}

AddKokkosFunctionAction::AddKokkosFunctionAction(const InputParameters & params)
  : KokkosObjectAction(params, "Function")
{
}

void
AddKokkosFunctionAction::act()
{
  FunctionParserBase<Real> fp;
  std::string vars = "x,y,z,t,NaN,pi,e";
  if (fp.Parse(_name, vars) == -1) // -1 for success
    mooseWarning("Function name '" + _name + "' could evaluate as a ParsedFunction");
  _problem->addKokkosFunction(_type, _name, _moose_object_pars);
}

framework/src/kokkos/auxkernels/KokkosFunctionAux.K

9  
10  
11  
12 +
13  
14  
15 +
16  
17 +
18 +
19  
20 +
21 +
22 +
23  
24 +
25 +
26  
27 +
28  

#include "KokkosFunctionAux.h"

registerKokkosAuxKernel("MooseApp", KokkosFunctionAux);

InputParameters
KokkosFunctionAux::validParams()
{
  InputParameters params = AuxKernel::validParams();
  params.addClassDescription("Auxiliary Kernel that creates and updates a field variable by "
                             "sampling a function through space and time.");
  params.addRequiredParam<FunctionName>("function", "The function to use as the value");
  return params;
}

KokkosFunctionAux::KokkosFunctionAux(const InputParameters & parameters)
  : AuxKernel(parameters), _func(getKokkosFunction("function"))
{
}

framework/src/kokkos/base/KokkosFunctor.K

16  
17  
18  
19 +
20 +
21  
22  
23 +
24 +
25  
26 +
27 +
28 +
29 +
30 +
31 +
32  
33  
34 +
35 +
36  
37 +
38  
39  
40 +
41 +
42  
43  
44 +
45 +
46  
47  
48  
namespace Kokkos
{

Functor::Functor(FEProblemBase & problem, std::shared_ptr<FunctorWrapperHostBase> wrapper)
  : _wrapper_host(wrapper), _problem(problem), _t(problem.time()), _t_old(problem.timeOld())
{
  // Allocate device wrapper
  _wrapper_device = _wrapper_host->allocate();
}

Functor::Functor(const Functor & functor)
  : _wrapper_host(functor._wrapper_host),
    _wrapper_device(functor._wrapper_device),
    _problem(functor._problem),
    _t(functor._t),
    _t_old(functor._t_old)
{
  // Copy functor to device
  _wrapper_host->copyFunctor();
}

Functor::~Functor()
{
  // Free device wrapper
  if (_wrapper_host.use_count() == 1)
    ::Kokkos::kokkos_free<ExecSpace::memory_space>(_wrapper_device);

  // Free host copy of functor
  _wrapper_host->freeFunctor();
}

} // namespace Kokkos
} // namespace Moose

framework/src/kokkos/base/KokkosFunctorRegistry.K

15  
16  
17  
18 +
19  
20  
21 +
22 +
23 +
24  
25  
26  
{

FunctorRegistry &
FunctorRegistry::getRegistry()
{
  static FunctorRegistry * registry = nullptr;
  if (!registry)
    registry = new FunctorRegistry();
  return *registry;
}

} // namespace Kokkos

framework/src/kokkos/functions/KokkosConstantFunction.K

12  
13  
14  
15 +
16  
17 +
18 +
19  
20 +
21 +
22 +
23 +
24  
25 +
26 +
27  
28 +
29  
registerKokkosFunction("MooseApp", KokkosConstantFunction);

InputParameters
KokkosConstantFunction::validParams()
{
  InputParameters params = FunctionBase::validParams();
  params.addClassDescription(
      "A function that returns a constant value as defined by an input parameter.");
  params.addParam<Real>("value", 0.0, "The constant value");
  params.declareControllable("value");
  return params;
}

KokkosConstantFunction::KokkosConstantFunction(const InputParameters & parameters)
  : FunctionBase(parameters), _value(getParam<Real>("value"))
{
}

framework/src/kokkos/functions/KokkosFunction.K

15  
16  
17  
18 +
19  
20 +
21 +
22  
23 +
24 +
25  
26 +
27  
28 +
29  
30 +
31  
32  
33 +
34 +
35  
36 +
37 +
38  
39  
40 +
41 +
42  
43 +
44  
45  
46 +
47 +
48  
49  
50 +
51 +
52  
53  
54  
{

InputParameters
FunctionBase::validParams()
{
  InputParameters params = Moose::FunctionBase::validParams();
  params.registerBase("KokkosFunction");

  return params;
}

FunctionBase::FunctionBase(const InputParameters & parameters) : Moose::FunctionBase(parameters) {}

FunctionBase::FunctionBase(const FunctionBase & object) : Moose::FunctionBase(object, {}) {}

Function::Function(std::shared_ptr<FunctionWrapperHostBase> wrapper) : _wrapper_host(wrapper)
{
  // Allocate device wrapper
  _wrapper_device = _wrapper_host->allocate();
}

Function::Function(const Function & function)
  : _wrapper_host(function._wrapper_host), _wrapper_device(function._wrapper_device)
{
  // Copy function to device
  _wrapper_host->copyFunction();
}

Function::~Function()
{
  // Free device wrapper
  if (_wrapper_host.use_count() == 1)
    ::Kokkos::kokkos_free<ExecSpace::memory_space>(_wrapper_device);

  // Free host copy of function
  _wrapper_host->freeFunction();
}

} // namespace Kokkos
} // namespace Moose

framework/src/kokkos/functions/KokkosFunctionInterface.K

12  
13  
14  
15 +
16 +
17 +
18 +
19 +
20 +
21  
22 +
23  
24  
25 +
26  
27 +
28  
29  
30  
31 +
32  
33  
34 +
35  
36  
37  
38 +
39 +
40  
41 +
42  
43  
44  
45 +
46  
47 +
48  
49  
50  
51 +
52  
53 +
54 +
55  
56 +
57  
58  
59  
60 +
61  
62 +
63 +
64  
65 +
66  
67  
#include "FunctionInterface.h"
#include "FEProblemBase.h"

FunctionInterface::FunctionInterface(const FunctionInterface & object,
                                     const Moose::Kokkos::FunctorCopy &)
  : _fni_object(object._fni_object),
    _fni_params(object._fni_params),
    _fni_feproblem(object._fni_feproblem),
    _fni_tid(object._fni_tid)
{
}

Moose::Kokkos::Function
FunctionInterface::getKokkosFunction(const std::string & name) const
{
  return getKokkosFunctionByName(_fni_params.get<FunctionName>(name));
}

Moose::Kokkos::Function
FunctionInterface::getKokkosFunctionByName(const FunctionName & name) const
{
#ifdef MOOSE_ENABLE_KOKKOS_GPU
  _fni_object.mooseError(
      "Retrieving a Kokkos function as abstract type is currently not supported for GPU.");
#endif

  if (!_fni_object.isKokkosObject())
    _fni_object.mooseError("Attempted to retrieve a Kokkos function from a non-Kokkos object.");

  return _fni_feproblem.getKokkosFunction(name);
}

bool
FunctionInterface::hasKokkosFunction(const std::string & param_name) const
{
  return hasKokkosFunctionByName(_fni_params.get<FunctionName>(param_name));
}

bool
FunctionInterface::hasKokkosFunctionByName(const FunctionName & name) const
{
  if (!_fni_object.isKokkosObject())
    _fni_object.mooseError("Attempted to retrieve a Kokkos function from a non-Kokkos object.");

  return _fni_feproblem.hasKokkosFunction(name);
}

const Moose::FunctionBase *
FunctionInterface::getKokkosFunctionByNameHelper(const FunctionName & name) const
{
  if (!_fni_object.isKokkosObject())
    _fni_object.mooseError("Attempted to retrieve a Kokkos function from a non-Kokkos object.");

  return &_fni_feproblem.getKokkosFunction<Moose::FunctionBase>(name);
}

framework/src/kokkos/functions/KokkosPiecewiseBase.K

10  
11  
12  
13 +
14  
15 +
16  
17  
18 +
19 +
20  
21 +
22  
23  
24 +
25  
26 +
27 +
28  
29 +
30 +
31 +
32  
#include "KokkosPiecewiseBase.h"

InputParameters
KokkosPiecewiseBase::validParams()
{
  return FunctionBase::validParams();
}

KokkosPiecewiseBase::KokkosPiecewiseBase(const InputParameters & parameters)
  : FunctionBase(parameters)
{
}

void
KokkosPiecewiseBase::setData(const std::vector<Real> & x, const std::vector<Real> & y)
{
  _raw_x = x;
  _raw_y = y;

  if (_raw_x.size() != _raw_y.size())
    mooseError("In KokkosPiecewiseBase ", _name, ": Lengths of x and y data do not match.");
}

framework/src/kokkos/functions/KokkosPiecewiseConstant.K

12  
13  
14  
15 +
16  
17 +
18 +
19 +
20 +
21 +
22 +
23 +
24  
25 +
26  
27 +
28  
29 +
30  
registerKokkosFunction("MooseApp", KokkosPiecewiseConstant);

InputParameters
KokkosPiecewiseConstant::validParams()
{
  InputParameters params = KokkosPiecewiseTabularBase::validParams();
  MooseEnum direction("LEFT RIGHT LEFT_INCLUSIVE RIGHT_INCLUSIVE", "LEFT");
  params.addParam<MooseEnum>(
      "direction", direction, "Direction to look to find value: " + direction.getRawNames());
  params.addClassDescription("Defines piece-wise constant data using a set of x-y data pairs");
  return params;
}

KokkosPiecewiseConstant::KokkosPiecewiseConstant(const InputParameters & parameters)
  : KokkosPiecewiseTabularBase(parameters),
    _direction(getParam<MooseEnum>("direction").getEnum<Direction>())
{
}

framework/src/kokkos/functions/KokkosPiecewiseTabularBase.K

12  
13  
14  
15 +
16  
17 +
18 +
19  
20 +
21 +
22  
23 +
24 +
25  
26 +
27  
28 +
29 +
30  
31  
32 +
33 +
34 +
35 +
36 +
37 +
38 +
39 +
40  
41 +
42  
43  
44 +
45  
46  
47 +
48 +
49  
50  
51 +
52 +
53 +
54  
#include "JSONFileReader.h"

InputParameters
KokkosPiecewiseTabularBase::validParams()
{
  InputParameters params = KokkosPiecewiseBase::validParams();
  params += PiecewiseTabularInterface::validParams();

  params.addParam<Real>("scale_factor", 1.0, "Scale factor to be applied to the output values");
  params.declareControllable("scale_factor");

  return params;
}

KokkosPiecewiseTabularBase::KokkosPiecewiseTabularBase(const InputParameters & parameters)
  : KokkosPiecewiseBase(parameters),
    PiecewiseTabularInterface(*this, _data_x, _data_y),
    _scale_factor(getParam<Real>("scale_factor"))
{
  // load the data
  if (isParamValid("data_file"))
    buildFromFile(_communicator);
  else if (isParamValid("x") && isParamValid("y"))
    buildFromXandY();
  else if (isParamValid("xy_data"))
    buildFromXY();
  else if (!isParamValid("json_uo"))
    mooseError("Unknown X-Y data source. Are you missing a parameter? Did you misspell one?");
  // JSON data is not available at construction as we rely on a user object
}

void
KokkosPiecewiseTabularBase::initialSetup()
{
  // For JSON UO input, we need to wait for initialSetup to load the data
  if (isParamValid("json_uo"))
    buildFromJSON(getUserObject<JSONFileReader>("json_uo"));

  // Copy data to GPU
  _raw_x = _data_x;
  _raw_y = _data_y;
}

framework/src/kokkos/problems/KokkosFEProblemBase.K

87  
88  
89  
90 +
91  
92  
93 +
94  
95  
96  
97  
98  
99 +
100  
101 +
102  
103 +
104 +
105  
106  
107 +
108  
109  
110  
111  
112  
113 +
114  
115 +
116 +
117 +
118 +
119  
120 +
121 +
122  
123  
124 +
125  
126 +
127  
128  
129  
130 +
131  
132 +
133  
134 +
135 +
136  
137 +
138  
139  
140  

  _has_kokkos_objects = true;
  _has_kokkos_residual_objects = true;
}

void
FEProblemBase::addKokkosAuxKernel(const std::string & kernel_name,
                                  const std::string & name,
                                  InputParameters & parameters)
{
  parallel_object_only();

  setAuxKernelParamsAndLog(kernel_name, name, parameters, "KokkosAuxKernel");

  _aux->addKokkosKernel(kernel_name, name, parameters);

  _has_kokkos_objects = true;
}

void
FEProblemBase::addKokkosFunction(const std::string & type,
                                 const std::string & name,
                                 InputParameters & parameters)
{
  parallel_object_only();

  parameters.set<SubProblem *>("_subproblem") = this;

  std::shared_ptr<Moose::FunctionBase> func =
      _factory.create<Moose::FunctionBase>(type, name, parameters);
  logAdd("Function", name, type, parameters);
  _kokkos_functions.addObject(func);

  _has_kokkos_objects = true;
}

bool
FEProblemBase::hasKokkosFunction(const std::string & name)
{
  return _kokkos_functions.hasActiveObject(name);
}

Moose::Kokkos::Function
FEProblemBase::getKokkosFunction(const std::string & name)
{
  const auto & function = getKokkosFunction<Moose::FunctionBase>(name);

  std::shared_ptr<Moose::Kokkos::FunctionWrapperHostBase> wrapper =
      Moose::Kokkos::FunctorRegistry::buildFunction(&function, function.type());

  return Moose::Kokkos::Function(wrapper);
}

void

framework/src/materials/MaterialPropertyInterface.C

61  
62  
63  
64 +
65  
66  
67  
    _mi_subproblem(*_mi_params.getCheckedPointerParam<SubProblem *>("_subproblem")),
    _mi_tid(_mi_params.get<THREAD_ID>("_tid")),
#ifdef MOOSE_KOKKOS_ENABLED
    _is_kokkos_object(_mi_moose_object.isKokkosObject()),
#else
    _is_kokkos_object(false),
#endif

framework/src/problems/FEProblemBase.C

1112  
1113  
1114  
1115 +
1116  
1117  
1118  
    }

#ifdef MOOSE_KOKKOS_ENABLED
    _kokkos_functions.initialSetup();
#endif
  }

1612  
1613  
1614  
1615 +
1616  
1617  
1618  
  }

#ifdef MOOSE_KOKKOS_ENABLED
  _kokkos_functions.timestepSetup();
#endif

  _aux->timestepSetup();
4815  
4816  
4817  
4818 +
4819  
4820  
4821  
  }

#ifdef MOOSE_KOKKOS_ENABLED
  _kokkos_functions.customSetup(exec_type);
#endif

  _aux->customSetup(exec_type);
7245  
7246  
7247  
7248 +
7249  
7250  
7251  
      }

#ifdef MOOSE_KOKKOS_ENABLED
      _kokkos_functions.residualSetup();
#endif

      computeSystems(EXEC_LINEAR);
7481  
7482  
7483  
7484 +
7485  
7486  
7487  
      }

#ifdef MOOSE_KOKKOS_ENABLED
      _kokkos_functions.residualSetup();
#endif

      computeSystems(EXEC_LINEAR);
7631  
7632  
7633  
7634 +
7635  
7636  
7637  
        }

#ifdef MOOSE_KOKKOS_ENABLED
        _kokkos_functions.jacobianSetup();
#endif

        computeSystems(EXEC_NONLINEAR);
7823  
7824  
7825  
7826 +
7827  
7828  
7829  
  }

#ifdef MOOSE_KOKKOS_ENABLED
  _kokkos_functions.jacobianSetup();
#endif

  try