NeoFOAM
WIP Prototype of a modern OpenFOAM core
Loading...
Searching...
No Matches
spatialOperator.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2023-2025 NeoFOAM authors
3#pragma once
4
5#include <memory>
6#include <concepts>
7
12#include "NeoFOAM/dsl/coeff.hpp"
14
15namespace la = NeoFOAM::la;
16
17namespace NeoFOAM::dsl
18{
19
20template<typename T>
21concept HasExplicitOperator = requires(T t) {
22 // using ValueType = typename T::FieldValueType;
23 {
24 t.explicitOperation(std::declval<Field<typename T::FieldValueType>&>())
25 } -> std::same_as<void>; // Adjust return type and arguments as needed
26};
27
28template<typename T>
29concept HasImplicitOperator = requires(T t) {
30 // using ValueType = typename T::FieldValueType;
31 {
32 t.implicitOperation(std::declval<la::LinearSystem<typename T::FieldValueType, localIdx>&>())
33 } -> std::same_as<void>; // Adjust return type and arguments as needed
34};
35
36template<typename T>
38
39/* @class Operator
40 * @brief A class to represent an operator in NeoFOAMs dsl
41 *
42 * The design here is based on the type erasure design pattern
43 * see https://www.youtube.com/watch?v=4eeESJQk-mw
44 *
45 * Motivation for using type erasure is that concrete implementation
46 * of Operators e.g Divergence, Laplacian, etc can be stored in a vector of
47 * Operators
48 *
49 * @ingroup dsl
50 */
51template<typename ValueType>
53{
54public:
55
56 using FieldValueType = ValueType;
57
58 template<IsSpatialOperator T>
59 SpatialOperator(T cls) : model_(std::make_unique<OperatorModel<T>>(std::move(cls)))
60 {}
61
62 SpatialOperator(const SpatialOperator& eqnOperator) : model_(eqnOperator.model_->clone()) {}
63
64 SpatialOperator(SpatialOperator&& eqnOperator) : model_(std::move(eqnOperator.model_)) {}
65
67 {
68 model_ = eqnOperator.model_->clone();
69 return *this;
70 }
71
72 void explicitOperation(Field<ValueType>& source) { model_->explicitOperation(source); }
73
75 {
76 model_->implicitOperation(ls);
77 }
78
80 {
81 return model_->createEmptyLinearSystem();
82 }
83
84 /* returns the fundamental type of an operator, ie explicit, implicit */
85 Operator::Type getType() const { return model_->getType(); }
86
87 std::string getName() const { return model_->getName(); }
88
89
90 Coeff& getCoefficient() { return model_->getCoefficient(); }
91
92 Coeff getCoefficient() const { return model_->getCoefficient(); }
93
94 /* @brief Given an input this function reads required coeffs */
95 void build(const Input& input) { model_->build(input); }
96
97 /* @brief Get the executor */
98 const Executor& exec() const { return model_->exec(); }
99
100
101private:
102
103 /* @brief Base class defining the concept of a term. This effectively
104 * defines what functions need to be implemented by a concrete Operator implementation
105 * */
106 struct OperatorConcept
107 {
108 virtual ~OperatorConcept() = default;
109
110 virtual void explicitOperation(Field<ValueType>& source) = 0;
111
112 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) = 0;
113
114 virtual la::LinearSystem<ValueType, localIdx> createEmptyLinearSystem() const = 0;
115
116 /* @brief Given an input this function reads required coeffs */
117 virtual void build(const Input& input) = 0;
118
119 /* returns the name of the operator */
120 virtual std::string getName() const = 0;
121
122 /* returns the fundamental type of an operator, ie explicit, implicit */
123 virtual Operator::Type getType() const = 0;
124
125 /* @brief get the associated coefficient for this term */
126 virtual Coeff& getCoefficient() = 0;
127
128 /* @brief get the associated coefficient for this term */
129 virtual Coeff getCoefficient() const = 0;
130
131 /* @brief Get the executor */
132 virtual const Executor& exec() const = 0;
133
134 // The Prototype Design Pattern
135 virtual std::unique_ptr<OperatorConcept> clone() const = 0;
136 };
137
138 // Templated derived class to implement the type-specific behavior
139 template<typename ConcreteOperatorType>
140 struct OperatorModel : OperatorConcept
141 {
142 /* @brief build with concrete operator */
143 OperatorModel(ConcreteOperatorType concreteOp) : concreteOp_(std::move(concreteOp)) {}
144
145 /* returns the name of the operator */
146 std::string getName() const override { return concreteOp_.getName(); }
147
148 virtual void explicitOperation(Field<ValueType>& source) override
149 {
150 if constexpr (HasExplicitOperator<ConcreteOperatorType>)
151 {
152 concreteOp_.explicitOperation(source);
153 }
154 }
155
156 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) override
157 {
158 if constexpr (HasImplicitOperator<ConcreteOperatorType>)
159 {
160 concreteOp_.implicitOperation(ls);
161 }
162 }
163
164 virtual la::LinearSystem<ValueType, localIdx> createEmptyLinearSystem() const override
165 {
166 if constexpr (HasImplicitOperator<ConcreteOperatorType>)
167 {
168 return concreteOp_.createEmptyLinearSystem();
169 }
170 throw std::runtime_error("Implicit operation not implemented");
171 // only need to avoid compiler warning about missing return statement
172 // this code path should never be reached as we call implicitOperation on an explicit
173 // operator
174 NeoFOAM::Field<ValueType> values(exec(), 1, zero<ValueType>());
175 Field<NeoFOAM::localIdx> colIdx(exec(), 1, 0);
176 NeoFOAM::Field<NeoFOAM::localIdx> rowPtrs(exec(), 2, 0);
177 NeoFOAM::la::CSRMatrix<ValueType, NeoFOAM::localIdx> csrMatrix(values, colIdx, rowPtrs);
178
179 NeoFOAM::Field<ValueType> rhs(exec(), 1, zero<ValueType>());
180 return la::LinearSystem<ValueType, localIdx>(csrMatrix, rhs, "custom");
181 }
182
183 /* @brief Given an input this function reads required coeffs */
184 virtual void build(const Input& input) override { concreteOp_.build(input); }
185
186 /* returns the fundamental type of an operator, ie explicit, implicit, temporal */
187 Operator::Type getType() const override { return concreteOp_.getType(); }
188
189 /* @brief Get the executor */
190 const Executor& exec() const override { return concreteOp_.exec(); }
191
192 /* @brief get the associated coefficient for this term */
193 virtual Coeff& getCoefficient() override { return concreteOp_.getCoefficient(); }
194
195 /* @brief get the associated coefficient for this term */
196 virtual Coeff getCoefficient() const override { return concreteOp_.getCoefficient(); }
197
198 // The Prototype Design Pattern
199 std::unique_ptr<OperatorConcept> clone() const override
200 {
201 return std::make_unique<OperatorModel>(*this);
202 }
203
204 ConcreteOperatorType concreteOp_;
205 };
206
207 std::unique_ptr<OperatorConcept> model_;
208};
209
210
211template<typename ValueType>
213{
214 SpatialOperator<ValueType> result = rhs;
215 result.getCoefficient() *= scalarCoeff;
216 return result;
217}
218
219template<typename ValueType>
220SpatialOperator<ValueType>
222{
223 SpatialOperator<ValueType> result = rhs;
224 result.getCoefficient() *= Coeff(coeffField);
225 return result;
226}
227
228template<typename ValueType>
230{
231 SpatialOperator<ValueType> result = rhs;
232 result.getCoefficient() *= coeff;
233 return result;
234}
235
236// template<typename CoeffFunction>
237// requires std::invocable<CoeffFunction&, size_t>
238// SpatialOperator operator*([[maybe_unused]] CoeffFunction coeffFunc, const SpatialOperator& lhs)
239// {
240// // TODO implement
241// NF_ERROR_EXIT("Not implemented");
242// SpatialOperator result = lhs;
243// // if (!result.getCoefficient().useSpan)
244// // {
245// // result.setField(std::make_shared<Field<scalar>>(result.exec(), result.nCells(), 1.0));
246// // }
247// // map(result.exec(), result.getCoefficient().values, scaleFunc);
248// return result;
249// }
250
251} // namespace NeoFOAM::dsl
A class to contain the data and executors for a field and define some basic operations.
Definition field.hpp:49
A class that represents a coefficient for the NeoFOAM dsl.
Definition coeff.hpp:22
const Executor & exec() const
SpatialOperator(SpatialOperator &&eqnOperator)
void build(const Input &input)
void explicitOperation(Field< ValueType > &source)
Operator::Type getType() const
SpatialOperator & operator=(const SpatialOperator &eqnOperator)
la::LinearSystem< ValueType, localIdx > createEmptyLinearSystem() const
SpatialOperator(const SpatialOperator &eqnOperator)
void implicitOperation(la::LinearSystem< ValueType, localIdx > &ls)
A class representing a linear system of equations.
Coeff operator*(const Coeff &lhs, const Coeff &rhs)
Definition coeff.hpp:57
float scalar
Definition scalar.hpp:14
std::variant< Dictionary, TokenList > Input
Definition input.hpp:13
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
Definition executor.hpp:16