NeoN
A framework for CFD software
Loading...
Searching...
No Matches
gradOperator.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/error.hpp"
12#include "NeoN/core/input.hpp"
16
18{
19
20/* @class Factory class to create gradient operators by a given name using
21 * using NeoNs runTimeFactory mechanism
22 */
23template<typename ValueType>
26 GradOperatorFactory<ValueType>,
27 Parameters<const Executor&, const UnstructuredMesh&, const Input&>>
28{
29
30public:
31
32 static std::unique_ptr<GradOperatorFactory<ValueType>>
33 create(const Executor& exec, const UnstructuredMesh& uMesh, const Input& inputs)
34 {
35 std::string key = (std::holds_alternative<Dictionary>(inputs))
36 ? std::get<Dictionary>(inputs).get<std::string>("GradOperator")
37 : std::get<TokenList>(inputs).next<std::string>();
39 return GradOperatorFactory<ValueType>::table().at(key)(exec, uMesh, inputs);
40 }
41
42 static std::string name() { return "GradOperatorFactory"; }
43
45 : exec_(exec), mesh_(mesh) {};
46
47 virtual ~GradOperatorFactory() = default; // Virtual destructor
48
49 /* @brief compute implicit gradient operator contribution
50 *
51 * @param [in] phi
52 * @param [in] operatorScaling
53 * @param [in,out] ls the linear system to assemble into
54 */
55 virtual void grad(
56 const VolumeField<scalar>& phi,
57 const dsl::Coeff operatorScaling,
59 ) const = 0;
60
61 /* @brief compute explicit gradient operator
62 *
63 * @param phi [in] - field for which the gradient is computed
64 * @param operatorScaling [in] - scales operator by a coefficient
65 * @param gradPhi [in,out] - resulting gradient field
66 */
67 virtual void grad(
68 const VolumeField<scalar>& phi, const dsl::Coeff operatorScaling, Vector<Vec3>& gradPhi
69 ) const = 0;
70
71 /* @brief compute explicit gradient operator and return result
72 *
73 * @param phi [in] - field for which the gradient is computed
74 * @param operatorScaling [in] - scales operator by a coefficient
75 * @return gradPhi - resulting gradient field
76 */
78 grad(const VolumeField<scalar>& phi, const dsl::Coeff operatorScaling) const = 0;
79
80 /* @brief compute the tensor gradient of a vector field into @p gradU
81 *
82 * Result convention: gradU(i, j) = d U_i / d x_j (row i is the gradient of
83 * the i-th velocity component). Schemes that do not support a tensor gradient
84 * leave this as the aborting default.
85 *
86 * @param u [in] - vector field to differentiate
87 * @param gradU [in,out] - resulting tensor field
88 * @param operatorScaling [in] - scales the operator by a coefficient
89 */
90 virtual void gradTensor(
91 const VolumeField<Vec3>& u, VolumeField<Tensor>& gradU, const dsl::Coeff operatorScaling
92 ) const
93 {
94 NF_ERROR_EXIT("gradTensor is not implemented for this gradient scheme");
95 }
96
97 // Pure virtual function for cloning
98 virtual std::unique_ptr<GradOperatorFactory<ValueType>> clone() const = 0;
99
100protected:
101
103
105};
106
107template<typename ValueType>
108class GradOperator : public dsl::OperatorMixin<VolumeField<ValueType>, VolumeField<scalar>>
109{
110
111public:
112
113 using VectorValueType = ValueType;
114
115 // copy constructor
117 : dsl::OperatorMixin<VolumeField<ValueType>, VolumeField<scalar>>(
118 gradOp.exec_, gradOp.coeffs_, gradOp.field_, gradOp.type_
119 ),
120 gradOperatorStrategy_(
121 gradOp.gradOperatorStrategy_ ? gradOp.gradOperatorStrategy_->clone() : nullptr
122 ) {};
123
124 GradOperator(dsl::Operator::Type termType, const VolumeField<scalar>& phi, const Input& input)
125 : dsl::OperatorMixin<VolumeField<ValueType>, VolumeField<scalar>>(
126 phi.exec(), dsl::Coeff(1.0), phi, termType
127 ),
128 gradOperatorStrategy_(
129 GradOperatorFactory<ValueType>::create(phi.exec(), phi.mesh(), input)
130 ) {};
131
133 dsl::Operator::Type termType,
134 const VolumeField<scalar>& phi,
135 std::unique_ptr<GradOperatorFactory<ValueType>> gradOperatorStrategy
136 )
137 : dsl::OperatorMixin<VolumeField<ValueType>, VolumeField<scalar>>(
138 phi.exec(), dsl::Coeff(1.0), phi, termType
139 ),
140 gradOperatorStrategy_(std::move(gradOperatorStrategy)) {};
141
143 : dsl::OperatorMixin<VolumeField<ValueType>, VolumeField<scalar>>(
144 phi.exec(), dsl::Coeff(1.0), phi, termType
145 ),
146 gradOperatorStrategy_(nullptr) {};
147
148
149 void explicitOperation(Vector<Vec3>& source) const
150 {
151 NF_ASSERT(gradOperatorStrategy_, "GradOperatorStrategy not initialized");
152 auto tmpsource = Vector<Vec3>(source.exec(), source.size(), zero<Vec3>());
153 const auto operatorScaling = this->getCoefficient();
154 gradOperatorStrategy_->grad(this->getVector(), operatorScaling, tmpsource);
155 source += tmpsource;
156 }
157
158 /* @brief forwards to implicit gradOperatorStrategy_->grad() with arguments */
160 {
161 NF_ASSERT(gradOperatorStrategy_, "GradOperatorStrategy not initialized");
162 const auto operatorScaling = this->getCoefficient();
163 gradOperatorStrategy_->grad(this->getVector(), operatorScaling, ls);
164 }
165
166 /* @brief forwards to gradOperatorStrategy_->grad() with arguments */
167 [[deprecated("use explicit or implicit operation")]] void grad(auto&&... args) const
168 {
169 const auto operatorScaling = this->getCoefficient();
170 gradOperatorStrategy_->grad(
171 std::forward<decltype(args)>(args)..., this->getVector(), operatorScaling
172 );
173 }
174
175 void read(const Input& input)
176 {
177 const UnstructuredMesh& mesh = this->getVector().mesh();
178 if (std::holds_alternative<NeoN::Dictionary>(input))
179 {
180 auto dict = std::get<NeoN::Dictionary>(input);
181 std::string schemeName = "grad(" + this->getVector().name + ")";
182 auto tokens = dict.subDict("gradSchemes").get<NeoN::TokenList>(schemeName);
183 gradOperatorStrategy_ =
184 GradOperatorFactory<ValueType>::create(this->exec(), mesh, tokens);
185 }
186 else
187 {
188 auto tokens = std::get<NeoN::TokenList>(input);
189 gradOperatorStrategy_ =
190 GradOperatorFactory<ValueType>::create(this->exec(), mesh, tokens);
191 }
192 }
193
194 std::string getName() const { return "GradOperator"; }
195
197 {
198 // Expose the operand like DivOperator does, so scheme-default expansion
199 // (which needs "grad(<field>)" keys) can learn the field's name.
200 const auto& ret = this->getVector();
201 return {{"field", NeoN::detail::RefHolder<VolumeField<scalar>> {ret}}};
202 }
203
204private:
205
206 std::unique_ptr<GradOperatorFactory<ValueType>> gradOperatorStrategy_;
207};
208
209
210} // 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
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 Executor exec_
Executor associated with the field. (CPU, GPU, openMP, etc.)
Definition operator.hpp:65
OperatorMixin(const Executor exec, const Coeff &coeffs, const VolumeField< scalar > &field, Operator::Type type)
Definition operator.hpp:42
const UnstructuredMesh & mesh() const
Returns a const reference to the unstructured mesh object.
Definition domain.hpp:122
virtual std::unique_ptr< GradOperatorFactory< ValueType > > clone() const =0
static std::unique_ptr< GradOperatorFactory< ValueType > > create(const Executor &exec, const UnstructuredMesh &uMesh, const Input &inputs)
virtual void grad(const VolumeField< scalar > &phi, const dsl::Coeff operatorScaling, Vector< Vec3 > &gradPhi) const =0
virtual void gradTensor(const VolumeField< Vec3 > &u, VolumeField< Tensor > &gradU, const dsl::Coeff operatorScaling) const
virtual VolumeField< ValueType > grad(const VolumeField< scalar > &phi, const dsl::Coeff operatorScaling) const =0
virtual void grad(const VolumeField< scalar > &phi, const dsl::Coeff operatorScaling, la::LinearSystem< ValueType > &ls) const =0
GradOperatorFactory(const Executor &exec, const UnstructuredMesh &mesh)
void explicitOperation(Vector< Vec3 > &source) const
void implicitOperation(la::LinearSystem< ValueType > &ls) const
GradOperator(dsl::Operator::Type termType, const VolumeField< scalar > &phi, std::unique_ptr< GradOperatorFactory< ValueType > > gradOperatorStrategy)
GradOperator(dsl::Operator::Type termType, const VolumeField< scalar > &phi)
GradOperator(dsl::Operator::Type termType, const VolumeField< scalar > &phi, const Input &input)
Represents a volume field in a finite volume method.
A class representing a linear system of equations.
#define NF_ERROR_EXIT(message)
Macro for printing an error message and aborting the program.
Definition error.hpp:90
#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
KOKKOS_INLINE_FUNCTION Vec3 zero< Vec3 >()
Definition vec3.hpp:205
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
Definition executor.hpp:20
float scalar
Definition scalar.hpp:17
A wrapper class to put references in dictionaries to overcome the issue that std::any cannot hold a r...