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 Coeff& getCoefficient() { return model_->getCoefficient(); }
87
88 Coeff getCoefficient() const { return model_->getCoefficient(); }
89
90 /* @brief Given an input this function reads required properties */
91 void read(const Input& input) { model_->read(input); }
92
93 /* @brief Get the executor */
94 const Executor& exec() const { return model_->exec(); }
95
96
97private:
98
99 /* @brief Base class defining the concept of a term. This effectively
100 * defines what functions need to be implemented by a concrete Operator implementation
101 * */
102 struct OperatorConcept
103 {
104 virtual ~OperatorConcept() = default;
105
106 virtual void explicitOperation(Vector<ValueType>& source) const = 0;
107
108 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) const = 0;
109
110 /* @brief Given an input this function reads required coeffs */
111 virtual void read(const Input& input) = 0;
112
113 /* returns the name of the operator */
114 virtual std::string getName() const = 0;
115
116 /* returns the fundamental type of an operator, ie explicit, implicit */
117 virtual Operator::Type getType() const = 0;
118
119 /* @brief get the associated coefficient for this term */
120 virtual Coeff& getCoefficient() = 0;
121
122 /* @brief get the associated coefficient for this term */
123 virtual Coeff getCoefficient() const = 0;
124
125 /* @brief Get the executor */
126 virtual const Executor& exec() const = 0;
127
128 // The Prototype Design Pattern
129 virtual std::unique_ptr<OperatorConcept> clone() const = 0;
130 };
131
132 // Templated derived class to implement the type-specific behavior
133 template<typename ConcreteOperatorType>
134 struct OperatorModel : OperatorConcept
135 {
136 /* @brief build with concrete operator */
137 OperatorModel(ConcreteOperatorType concreteOp) : concreteOp_(std::move(concreteOp)) {}
138
139 /* returns the name of the operator */
140 std::string getName() const override { return concreteOp_.getName(); }
141
142 virtual void explicitOperation(Vector<ValueType>& source) const override
143 {
144 if constexpr (HasExplicitOperator<ConcreteOperatorType>)
145 {
146 concreteOp_.explicitOperation(source);
147 }
148 }
149
150 virtual void implicitOperation(la::LinearSystem<ValueType, localIdx>& ls) const override
151 {
152 if constexpr (HasImplicitOperator<ConcreteOperatorType>)
153 {
154 concreteOp_.implicitOperation(ls);
155 }
156 }
157
158 /* @brief Given an input this function reads required coeffs */
159 virtual void read(const Input& input) override { concreteOp_.read(input); }
160
161 /* returns the fundamental type of an operator, ie explicit, implicit, temporal */
162 Operator::Type getType() const override { return concreteOp_.getType(); }
163
164 /* @brief Get the executor */
165 const Executor& exec() const override { return concreteOp_.exec(); }
166
167 /* @brief get the associated coefficient for this term */
168 virtual Coeff& getCoefficient() override { return concreteOp_.getCoefficient(); }
169
170 /* @brief get the associated coefficient for this term */
171 virtual Coeff getCoefficient() const override { return concreteOp_.getCoefficient(); }
172
173 // The Prototype Design Pattern
174 std::unique_ptr<OperatorConcept> clone() const override
175 {
176 return std::make_unique<OperatorModel>(*this);
177 }
178
179 ConcreteOperatorType concreteOp_;
180 };
181
182 std::unique_ptr<OperatorConcept> model_;
183};
184
185
186template<typename ValueType>
188{
189 SpatialOperator<ValueType> result = rhs;
190 result.getCoefficient() *= scalarCoeff;
191 return result;
192}
193
194template<typename ValueType>
195SpatialOperator<ValueType>
197{
198 SpatialOperator<ValueType> result = rhs;
199 result.getCoefficient() *= Coeff {coeffVector};
200 return result;
201}
202
203template<typename ValueType>
205{
206 SpatialOperator<ValueType> result = rhs;
207 result.getCoefficient() *= coeff;
208 return result;
209}
210
211// template<typename CoeffFunction>
212// requires std::invocable<CoeffFunction&, size_t>
213// SpatialOperator operator*([[maybe_unused]] CoeffFunction coeffFunc, const SpatialOperator& lhs)
214// {
215// // TODO implement
216// NF_ERROR_EXIT("Not implemented");
217// SpatialOperator result = lhs;
218// // if (!result.getCoefficient().useView)
219// // {
220// // result.setVector(std::make_shared<Vector<scalar>>(result.exec(),
221// result.nCells(), 1.0));
222// // }
223// // map(result.exec(), result.getCoefficient().values, scaleFunc);
224// return result;
225// }
226
227} // 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) const
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