NeoN
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 NeoN authors
3#pragma once
4
5#include <memory>
6#include <concepts>
7
11#include "NeoN/core/input.hpp"
12#include "NeoN/dsl/coeff.hpp"
13#include "NeoN/dsl/operator.hpp"
14
15namespace la = NeoN::la;
16
17namespace NeoN::dsl
18{
19
20template<typename T>
21concept HasExplicitOperator = requires(T t) {
22 // using ValueType = typename T::VectorValueType;
23 {
24 t.explicitOperation(std::declval<Vector<typename T::VectorValueType>&>())
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::VectorValueType;
31 {
32 t.implicitOperation(std::declval<la::LinearSystem<typename T::VectorValueType, localIdx>&>()
33 )
34 } -> std::same_as<void>; // Adjust return type and arguments as needed
35};
36
37template<typename T>
39
40/* @class SpatialOperator
41 * @brief A class to represent an operator in NeoNs dsl
42 *
43 * The design here is based on the type erasure design pattern
44 * see https://www.youtube.com/watch?v=4eeESJQk-mw
45 *
46 * Motivation for using type erasure is that concrete implementation
47 * of Operators e.g Divergence, Laplacian, etc can be stored in a vector of
48 * Operators
49 *
50 * @ingroup dsl
51 */
52template<typename ValueType>
54{
55public:
56
57 using VectorValueType = ValueType;
58
59 // FIXME add again
60 // template<IsSpatialOperator T>
61 template<typename T>
62 SpatialOperator(T cls) : model_(std::make_unique<OperatorModel<T>>(std::move(cls)))
63 {}
64
65 SpatialOperator(const SpatialOperator& eqnOperator) : model_(eqnOperator.model_->clone()) {}
66
67 SpatialOperator(SpatialOperator&& eqnOperator) : model_(std::move(eqnOperator.model_)) {}
68
70 {
71 model_ = eqnOperator.model_->clone();
72 return *this;
73 }
74
75 void explicitOperation(Vector<ValueType>& source) const { model_->explicitOperation(source); }
76
78 {
79 model_->implicitOperation(ls);
80 }
81
82 /* returns the fundamental type of an operator, ie explicit, implicit */
83 Operator::Type getType() const { return model_->getType(); }
84
85 std::string getName() const { return model_->getName(); }
86
87
88 Coeff& getCoefficient() { return model_->getCoefficient(); }
89
90 Coeff getCoefficient() const { return model_->getCoefficient(); }
91
92 /* @brief Given an input this function reads required coeffs */
93 void build(const Input& input) { model_->build(input); }
94
95 /* @brief Get the executor */
96 const Executor& exec() const { return model_->exec(); }
97
98
99private:
100
101 /* @brief Base class defining the concept of a term. This effectively
102 * defines what functions need to be implemented by a concrete Operator implementation
103 * */
104 struct OperatorConcept
105 {
106 virtual ~OperatorConcept() = default;
107
108 virtual void explicitOperation(Vector<ValueType>& source) = 0;
109
110 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) = 0;
111
112 /* @brief Given an input this function reads required coeffs */
113 virtual void build(const Input& input) = 0;
114
115 /* returns the name of the operator */
116 virtual std::string getName() const = 0;
117
118 /* returns the fundamental type of an operator, ie explicit, implicit */
119 virtual Operator::Type getType() const = 0;
120
121 /* @brief get the associated coefficient for this term */
122 virtual Coeff& getCoefficient() = 0;
123
124 /* @brief get the associated coefficient for this term */
125 virtual Coeff getCoefficient() const = 0;
126
127 /* @brief Get the executor */
128 virtual const Executor& exec() const = 0;
129
130 // The Prototype Design Pattern
131 virtual std::unique_ptr<OperatorConcept> clone() const = 0;
132 };
133
134 // Templated derived class to implement the type-specific behavior
135 template<typename ConcreteOperatorType>
136 struct OperatorModel : OperatorConcept
137 {
138 /* @brief build with concrete operator */
139 OperatorModel(ConcreteOperatorType concreteOp) : concreteOp_(std::move(concreteOp)) {}
140
141 /* returns the name of the operator */
142 std::string getName() const override { return concreteOp_.getName(); }
143
144 virtual void explicitOperation(Vector<ValueType>& source) override
145 {
146 if constexpr (HasExplicitOperator<ConcreteOperatorType>)
147 {
148 concreteOp_.explicitOperation(source);
149 }
150 }
151
152 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) override
153 {
154 if constexpr (HasImplicitOperator<ConcreteOperatorType>)
155 {
156 concreteOp_.implicitOperation(ls);
157 }
158 }
159
160 /* @brief Given an input this function reads required coeffs */
161 virtual void build(const Input& input) override { concreteOp_.build(input); }
162
163 /* returns the fundamental type of an operator, ie explicit, implicit, temporal */
164 Operator::Type getType() const override { return concreteOp_.getType(); }
165
166 /* @brief Get the executor */
167 const Executor& exec() const override { return concreteOp_.exec(); }
168
169 /* @brief get the associated coefficient for this term */
170 virtual Coeff& getCoefficient() override { return concreteOp_.getCoefficient(); }
171
172 /* @brief get the associated coefficient for this term */
173 virtual Coeff getCoefficient() const override { return concreteOp_.getCoefficient(); }
174
175 // The Prototype Design Pattern
176 std::unique_ptr<OperatorConcept> clone() const override
177 {
178 return std::make_unique<OperatorModel>(*this);
179 }
180
181 ConcreteOperatorType concreteOp_;
182 };
183
184 std::unique_ptr<OperatorConcept> model_;
185};
186
187
188template<typename ValueType>
190{
191 SpatialOperator<ValueType> result = rhs;
192 result.getCoefficient() *= scalarCoeff;
193 return result;
194}
195
196template<typename ValueType>
197SpatialOperator<ValueType>
199{
200 SpatialOperator<ValueType> result = rhs;
201 result.getCoefficient() *= Coeff {coeffVector};
202 return result;
203}
204
205template<typename ValueType>
207{
208 SpatialOperator<ValueType> result = rhs;
209 result.getCoefficient() *= coeff;
210 return result;
211}
212
213// template<typename CoeffFunction>
214// requires std::invocable<CoeffFunction&, size_t>
215// SpatialOperator operator*([[maybe_unused]] CoeffFunction coeffFunc, const SpatialOperator& lhs)
216// {
217// // TODO implement
218// NF_ERROR_EXIT("Not implemented");
219// SpatialOperator result = lhs;
220// // if (!result.getCoefficient().useSpan)
221// // {
222// // result.setVector(std::make_shared<Vector<scalar>>(result.exec(),
223// result.nCells(), 1.0));
224// // }
225// // map(result.exec(), result.getCoefficient().values, scaleFunc);
226// return result;
227// }
228
229} // namespace dsl
A class to contain the data and executors for a field and define some basic operations.
Definition vector.hpp:53
A class that represents a coefficient for the NeoN dsl.
Definition coeff.hpp:22
SpatialOperator & operator=(const SpatialOperator &eqnOperator)
void implicitOperation(la::LinearSystem< ValueType, localIdx > &ls)
SpatialOperator(SpatialOperator &&eqnOperator)
void explicitOperation(Vector< ValueType > &source) const
const Executor & exec() const
Operator::Type getType() const
void build(const Input &input)
SpatialOperator(const SpatialOperator &eqnOperator)
std::string getName() const
A class representing a linear system of equations.
Coeff operator*(const Coeff &lhs, const Coeff &rhs)
Definition coeff.hpp:57
std::variant< Dictionary, TokenList > Input
Definition input.hpp:13
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
Definition executor.hpp:16
float scalar
Definition scalar.hpp:14