NeoN
A framework for CFD software
Loading...
Searching...
No Matches
divOperator.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2023 - 2026 NeoN authors
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
10#include "NeoN/core/input.hpp"
14
16{
17
18/* @class Factory class to create divergence operators by a given name using
19 * using NeoNs runTimeFactory mechanism
20 */
21template<typename FieldValueType, typename AssemblyType = FieldValueType>
24 DivOperatorFactory<FieldValueType, AssemblyType>,
25 Parameters<const Executor&, const UnstructuredMesh&, const Input&>>
26{
27
28public:
29
30 static std::unique_ptr<DivOperatorFactory<FieldValueType, AssemblyType>>
31 create(const Executor& exec, const UnstructuredMesh& uMesh, const Input& inputs)
32 {
33 std::string key = (std::holds_alternative<Dictionary>(inputs))
34 ? std::get<Dictionary>(inputs).get<std::string>("DivOperator")
35 : std::get<TokenList>(inputs).next<std::string>();
38 exec, uMesh, inputs
39 );
40 }
41
42 static std::string name() { return "DivOperatorFactory"; }
43
45 : exec_(exec), mesh_(mesh) {};
46
47 virtual ~DivOperatorFactory() {} // Virtual destructor
48
49 virtual void
51 const SurfaceField<scalar>& faceFlux,
53 const dsl::Coeff operatorScaling) const = 0;
54
55 virtual void
57 const SurfaceField<scalar>& faceFlux,
59 const dsl::Coeff operatorScaling) const = 0;
60
61 virtual void
63 const SurfaceField<scalar>& faceFlux,
65 const dsl::Coeff operatorScaling) const = 0;
66
68 div(const SurfaceField<scalar>& faceFlux,
70 const dsl::Coeff operatorScaling) const = 0;
71
72 // Pure virtual function for cloning
73 virtual std::unique_ptr<DivOperatorFactory<FieldValueType, AssemblyType>> clone() const = 0;
74
75protected:
76
78
80};
81
82template<typename FieldValueType>
83class DivOperator : public dsl::OperatorMixin<VolumeField<FieldValueType>>
84{
85
86public:
87
88 using VectorValueType = FieldValueType;
89
90 // copy constructor
92 : dsl::OperatorMixin<VolumeField<FieldValueType>>(
93 divOp.exec_, divOp.coeffs_, divOp.field_, divOp.type_
94 ),
95 faceFlux_(divOp.faceFlux_),
96 sameTypeStrategy_(divOp.sameTypeStrategy_ ? divOp.sameTypeStrategy_->clone() : nullptr),
97 scalarMtxStrategy_(
98 divOp.scalarMtxStrategy_ ? divOp.scalarMtxStrategy_->clone() : nullptr
99 ) {};
100
102 dsl::Operator::Type termType,
103 const SurfaceField<scalar>& faceFlux,
105 Input input
106 )
107 : dsl::OperatorMixin<VolumeField<FieldValueType>>(
108 phi.exec(), dsl::Coeff(1.0), phi, termType
109 ),
110 faceFlux_(faceFlux),
111 sameTypeStrategy_(DivOperatorFactory<FieldValueType, FieldValueType>::create(
112 phi.exec(), phi.mesh(), input
113 )),
114 scalarMtxStrategy_(nullptr)
115 {
116 if constexpr (!std::is_same_v<FieldValueType, scalar>)
117 {
118 // The first create() consumed tokens; rewind the cursor so the second
119 // strategy can read the same scheme tokens from the start.
120 if (std::holds_alternative<NeoN::TokenList>(input))
121 {
122 std::get<NeoN::TokenList>(input).reset();
123 }
124 scalarMtxStrategy_ =
126 }
127 };
128
130 dsl::Operator::Type termType,
131 const SurfaceField<scalar>& faceFlux,
133 )
134 : dsl::OperatorMixin<VolumeField<FieldValueType>>(
135 phi.exec(), dsl::Coeff(1.0), phi, termType
136 ),
137 faceFlux_(faceFlux), sameTypeStrategy_(nullptr), scalarMtxStrategy_(nullptr) {};
138
139
141 {
142 NF_ASSERT(sameTypeStrategy_, "DivOperatorStrategy not initialized");
143 auto tmpsource =
144 Vector<FieldValueType>(source.exec(), source.size(), zero<FieldValueType>());
145 const auto operatorScaling = this->getCoefficient();
146 sameTypeStrategy_->div(tmpsource, faceFlux_, this->getVector(), operatorScaling);
147 source += tmpsource;
148 }
149
151 {
152 NF_ASSERT(sameTypeStrategy_, "DivOperatorStrategy not initialized");
153 const auto operatorScaling = this->getCoefficient();
154 sameTypeStrategy_->div(ls, faceFlux_, this->getVector(), operatorScaling);
155 }
156
157 /* @brief Implicit assembly into a scalar-matrix / FieldValueType-rhs linear system
158 * (segregated vector-solve form). Only present when FieldValueType != scalar;
159 * for scalar fields the same-type overload above already covers this signature.
160 */
161 template<typename F = FieldValueType>
162 requires(!std::is_same_v<F, scalar>)
164 {
165 NF_ASSERT(scalarMtxStrategy_, "Scalar-matrix DivOperatorStrategy not initialized");
166 const auto operatorScaling = this->getCoefficient();
167 scalarMtxStrategy_->div(ls, faceFlux_, this->getVector(), operatorScaling);
168 }
169
170 void read(const Input& input)
171 {
172 const UnstructuredMesh& mesh = this->getVector().mesh();
173 NeoN::TokenList tokens;
174 if (std::holds_alternative<NeoN::Dictionary>(input))
175 {
176 auto dict = std::get<NeoN::Dictionary>(input);
177 std::string schemeName = "div(" + faceFlux_.name + "," + this->getVector().name + ")";
178 tokens = dict.subDict("divSchemes").get<NeoN::TokenList>(schemeName);
179 }
180 else
181 {
182 tokens = std::get<NeoN::TokenList>(input);
183 }
184 sameTypeStrategy_ =
186 if constexpr (!std::is_same_v<FieldValueType, scalar>)
187 {
188 tokens.reset();
189 scalarMtxStrategy_ =
191 }
192 }
193
194 std::string getName() const { return "DivOperator"; }
195
196 // TODO make this private and let only friends use it
198 {
199 const auto& ret = this->getVector();
200 const auto& coeff = this->getCoefficient();
201 return {
203 {"coeff", detail::RefHolder<dsl::Coeff> {coeff}},
205 };
206 }
207
208private:
209
210 const SurfaceField<NeoN::scalar>& faceFlux_;
211
212 std::unique_ptr<DivOperatorFactory<FieldValueType, FieldValueType>> sameTypeStrategy_;
213 // Only initialized when FieldValueType != scalar; used to assemble into a
214 // LinearSystem<scalar, FieldValueType> for segregated vector solves.
215 std::unique_ptr<DivOperatorFactory<FieldValueType, scalar>> scalarMtxStrategy_;
216};
217
218
219} // namespace NeoN
A class representing a dictionary that stores key-value pairs.
A factory class for runtime selection of derived classes.
A class representing a list of tokens.
Definition tokenList.hpp:31
ReturnType & get(const size_t &idx)
Retrieves the value associated with the given index, casting it to the specified type.
void reset() const
Rewind the read cursor used by next<>() so the list can be iterated again from the beginning.
Definition tokenList.hpp:92
Represents an unstructured mesh in NeoN.
A class to contain the data and executors for a field and define some basic operations.
Definition vector.hpp:27
A class that represents a coefficient for the NeoN dsl.
Definition coeff.hpp:24
const VolumeField< FieldValueType > & field_
Definition operator.hpp:69
const Executor exec_
Executor associated with the field. (CPU, GPU, openMP, etc.)
Definition operator.hpp:65
OperatorMixin(const Executor exec, const Coeff &coeffs, const VolumeField< FieldValueType > &field, Operator::Type type)
Definition operator.hpp:42
const VolumeField< FieldValueType > & getVector() const
Definition operator.hpp:58
virtual const Executor & exec() const final
Definition operator.hpp:52
DivOperatorFactory(const Executor &exec, const UnstructuredMesh &mesh)
virtual void div(la::LinearSystem< AssemblyType, FieldValueType > &ls, const SurfaceField< scalar > &faceFlux, const VolumeField< FieldValueType > &phi, const dsl::Coeff operatorScaling) const =0
static std::unique_ptr< DivOperatorFactory< FieldValueType, AssemblyType > > create(const Executor &exec, const UnstructuredMesh &uMesh, const Input &inputs)
virtual std::unique_ptr< DivOperatorFactory< FieldValueType, AssemblyType > > clone() const =0
virtual VolumeField< FieldValueType > div(const SurfaceField< scalar > &faceFlux, const VolumeField< FieldValueType > &phi, const dsl::Coeff operatorScaling) const =0
virtual void div(Vector< FieldValueType > &divPhi, const SurfaceField< scalar > &faceFlux, const VolumeField< FieldValueType > &phi, const dsl::Coeff operatorScaling) const =0
virtual void div(VolumeField< FieldValueType > &divPhi, const SurfaceField< scalar > &faceFlux, const VolumeField< FieldValueType > &phi, const dsl::Coeff operatorScaling) const =0
DivOperator(dsl::Operator::Type termType, const SurfaceField< scalar > &faceFlux, const VolumeField< FieldValueType > &phi, Input input)
void implicitOperation(la::LinearSystem< FieldValueType, FieldValueType > &ls) const
void implicitOperation(la::LinearSystem< scalar, FieldValueType > &ls) const
void explicitOperation(Vector< FieldValueType > &source) const
DivOperator(dsl::Operator::Type termType, const SurfaceField< scalar > &faceFlux, const VolumeField< FieldValueType > &phi)
const UnstructuredMesh & mesh() const
Returns a const reference to the unstructured mesh object.
Definition domain.hpp:122
const Executor & exec() const
Returns a const reference to the executor object.
Definition domain.hpp:115
Represents a surface field in a finite volume method.
Represents a volume field in a finite volume method.
A class representing a linear system of equations.
#define NF_ASSERT(condition, message)
Macro for asserting a condition and printing an error message if the condition is false.
Definition error.hpp:118
std::variant< Dictionary, TokenList > Input
Definition input.hpp:15
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
Definition executor.hpp:20
A wrapper class to put references in dictionaries to overcome the issue that std::any cannot hold a r...