NeoN
A framework for CFD software
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
12#include "NeoN/core/input.hpp"
13#include "NeoN/dsl/coeff.hpp"
14#include "NeoN/dsl/operator.hpp"
15
16namespace la = NeoN::la;
17
18namespace NeoN::dsl
19{
20
21template<typename T>
22concept HasExplicitOperator = requires(T const t) {
23 {
24 t.explicitOperation(std::declval<Vector<typename T::VectorValueType>&>())
25 } -> std::same_as<void>;
26};
27
28template<typename T>
29concept HasImplicitOperator = requires(T const t) {
30 {
31 t.implicitOperation(std::declval<la::LinearSystem<typename T::VectorValueType, localIdx>&>()
32 )
33 } -> std::same_as<void>; // Adjust return type and arguments as needed
34};
35
36template<typename T>
38
39/* @class SpatialOperator
40 * @brief A class to represent an operator in NeoNs 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 VectorValueType = 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(Vector<ValueType>& source) const { model_->explicitOperation(source); }
73
75 {
76 model_->implicitOperation(ls);
77 }
78
79 /* returns the fundamental type of an operator, ie explicit, implicit */
80 Operator::Type getType() const { return model_->getType(); }
81
82 std::string getName() const { return model_->getName(); }
83
84
85 Coeff& getCoefficient() { return model_->getCoefficient(); }
86
87 Coeff getCoefficient() const { return model_->getCoefficient(); }
88
89 /* @brief Given an input this function reads required properties */
90 void read(const Input& input) { model_->read(input); }
91
92 /* @brief Get the executor */
93 const Executor& exec() const { return model_->exec(); }
94
95
96private:
97
98 /* @brief Base class defining the concept of a term. This effectively
99 * defines what functions need to be implemented by a concrete Operator implementation
100 * */
101 struct OperatorConcept
102 {
103 virtual ~OperatorConcept() = default;
104
105 virtual void explicitOperation(Vector<ValueType>& source) = 0;
106
107 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) = 0;
108
109 /* @brief Given an input this function reads required coeffs */
110 virtual void read(const Input& input) = 0;
111
112 /* returns the name of the operator */
113 virtual std::string getName() const = 0;
114
115 /* returns the fundamental type of an operator, ie explicit, implicit */
116 virtual Operator::Type getType() const = 0;
117
118 /* @brief get the associated coefficient for this term */
119 virtual Coeff& getCoefficient() = 0;
120
121 /* @brief get the associated coefficient for this term */
122 virtual Coeff getCoefficient() const = 0;
123
124 /* @brief Get the executor */
125 virtual const Executor& exec() const = 0;
126
127 // The Prototype Design Pattern
128 virtual std::unique_ptr<OperatorConcept> clone() const = 0;
129 };
130
131 // Templated derived class to implement the type-specific behavior
132 template<typename ConcreteOperatorType>
133 struct OperatorModel : OperatorConcept
134 {
135 /* @brief build with concrete operator */
136 OperatorModel(ConcreteOperatorType concreteOp) : concreteOp_(std::move(concreteOp)) {}
137
138 /* returns the name of the operator */
139 std::string getName() const override { return concreteOp_.getName(); }
140
141 virtual void explicitOperation(Vector<ValueType>& source) override
142 {
143 if constexpr (HasExplicitOperator<ConcreteOperatorType>)
144 {
145 concreteOp_.explicitOperation(source);
146 }
147 }
148
149 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) override
150 {
151 if constexpr (HasImplicitOperator<ConcreteOperatorType>)
152 {
153 concreteOp_.implicitOperation(ls);
154 }
155 }
156
157 /* @brief Given an input this function reads required coeffs */
158 virtual void read(const Input& input) override { concreteOp_.read(input); }
159
160 /* returns the fundamental type of an operator, ie explicit, implicit, temporal */
161 Operator::Type getType() const override { return concreteOp_.getType(); }
162
163 /* @brief Get the executor */
164 const Executor& exec() const override { return concreteOp_.exec(); }
165
166 /* @brief get the associated coefficient for this term */
167 virtual Coeff& getCoefficient() override { return concreteOp_.getCoefficient(); }
168
169 /* @brief get the associated coefficient for this term */
170 virtual Coeff getCoefficient() const override { return concreteOp_.getCoefficient(); }
171
172 // The Prototype Design Pattern
173 std::unique_ptr<OperatorConcept> clone() const override
174 {
175 return std::make_unique<OperatorModel>(*this);
176 }
177
178 ConcreteOperatorType concreteOp_;
179 };
180
181 std::unique_ptr<OperatorConcept> model_;
182};
183
184
185template<typename ValueType>
187{
188 SpatialOperator<ValueType> result = rhs;
189 result.getCoefficient() *= scalarCoeff;
190 return result;
191}
192
193template<typename ValueType>
194SpatialOperator<ValueType>
196{
197 SpatialOperator<ValueType> result = rhs;
198 result.getCoefficient() *= Coeff {coeffVector};
199 return result;
200}
201
202template<typename ValueType>
204{
205 SpatialOperator<ValueType> result = rhs;
206 result.getCoefficient() *= coeff;
207 return result;
208}
209
210// template<typename CoeffFunction>
211// requires std::invocable<CoeffFunction&, size_t>
212// SpatialOperator operator*([[maybe_unused]] CoeffFunction coeffFunc, const SpatialOperator& lhs)
213// {
214// // TODO implement
215// NF_ERROR_EXIT("Not implemented");
216// SpatialOperator result = lhs;
217// // if (!result.getCoefficient().useView)
218// // {
219// // result.setVector(std::make_shared<Vector<scalar>>(result.exec(),
220// result.nCells(), 1.0));
221// // }
222// // map(result.exec(), result.getCoefficient().values, scaleFunc);
223// return result;
224// }
225
226} // namespace dsl
A class to contain the data and executors for a field and define some basic operations.
Definition vector.hpp:28
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
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: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
DataClass read(Input input)
Definition input.hpp:16