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