Loading...
Searching...
No Matches
PrecisionAdaptor.H
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2019-2025 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26Class
27 Foam::PrecisionAdaptor
28
29Description
30 Conversion adaptor for Field/List that either wrap the input as a
31 reference, or creates a temporary pointer and copies the values
32 on construction/destruction.
33
34 This provides, for example, automatic conversion between types
35 for linear solvers able to run mixed precision.
36
37\*---------------------------------------------------------------------------*/
38
39#ifndef Foam_PrecisionAdaptor_H
40#define Foam_PrecisionAdaptor_H
41
42#include <algorithm> // For std::copy
43#include <type_traits> // For std::is_same
44#include "refPtr.H"
45#include "Field.H"
46
47// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48
49namespace Foam
50{
51
52/*---------------------------------------------------------------------------*\
53 Class ConstPrecisionAdaptor Declaration
54\*---------------------------------------------------------------------------*/
55
56//- A const Field/List wrapper with possible data conversion
57template<class Type, class InputType, template<class> class Container = Field>
59:
60 public refPtr<Container<Type>>
61{
62 // Private Member Functions
63
64 //- Set adaptor for different input, copying as required
65 void setInput(const Container<InputType>& src)
66 {
67 if constexpr (std::is_same_v<Type, InputType>)
68 {
69 // Use reference directly
70 this->cref(reinterpret_cast<const Container<Type>&>(src));
71 }
72 else
73 {
74 // Need intermediate buffer
75 this->reset(new Container<Type>(src.size()));
76 std::copy(src.cbegin(), src.cend(), this->ref().begin());
77 }
78 }
79
80 //- Set from tmp, steal pointer if possible
81 void tmpInput(tmp<Container<InputType>>& tsrc)
82 {
83 if (std::is_same_v<Type, InputType> && tsrc.is_pointer())
84 {
85 // Acquire control of the managed pointer
86 this->reset(reinterpret_cast<Container<Type>*>(tsrc.ptr()));
87 }
88 else
89 {
90 this->setInput(tsrc.cref());
91 }
92 tsrc.clear();
93 }
94
95public:
96
97 //- The adapted field type. Same as element_type
98 typedef Container<Type> FieldType;
100
101 // Constructors
102
103 //- Default construct, setting content later
104 ConstPrecisionAdaptor() = default;
105
106 //- Construct from Container of InputType, copying if required
107 explicit ConstPrecisionAdaptor(const Container<InputType>& input)
108 {
109 this->setInput(input);
110 }
111
112 //- Construct from tmp Container of InputType, copy/move as required
113 explicit ConstPrecisionAdaptor(tmp<Container<InputType>>&& input)
114 {
115 this->tmpInput(input);
116 }
117
118 //- Construct from tmp Container of InputType, copy/move as required
119 explicit ConstPrecisionAdaptor(const tmp<Container<InputType>>& input)
121 this->tmpInput(const_cast<tmp<Container<InputType>>&>(input));
122 }
123
124
125 // Member Functions
126
127 //- Is precision adaption being used (non-passive adaptor)?
128 bool active() const noexcept
129 {
130 // Same as refPtr::movable()
131 return (this->is_pointer() && this->good());
132 }
133
134 //- Commit adapted content changes (no-op for const adaptor)
135 void commit()
136 {}
137
138 //- Set adaptor for different input, copying input if required
139 void set(const Container<InputType>& input)
140 {
141 this->setInput(input);
142 }
143
144 //- Set adaptor for tmp Container of InputType, copy/move as required
145 void set(tmp<Container<InputType>>&& input)
146 {
147 this->tmpInput(input);
149
150 //- Set adaptor for tmp Container of InputType, copy/move as required
151 void set(const tmp<Container<InputType>>& input)
152 {
153 this->tmpInput(const_cast<tmp<Container<InputType>>&>(input));
155
156
157 // Static Member Functions
158
159 //- Select a reference to the input (if types are identical),
160 //- or copy into other and return a reference to that
161 static const Container<Type>& select
163 const Container<InputType>& input,
164 [[maybe_unused]] Container<Type>& other
165 )
166 {
167 if constexpr (std::is_same_v<Type, InputType>)
168 {
169 return reinterpret_cast<const Container<Type>&>(input);
171 else
172 {
173 other.resize(input.size());
174 std::copy(input.cbegin(), input.cend(), other.begin());
175 return other;
176 }
177 }
178};
179
180
181/*---------------------------------------------------------------------------*\
182 Class PrecisionAdaptor Declaration
183\*---------------------------------------------------------------------------*/
184
185//- A non-const Field/List wrapper with possible data conversion
186template<class Type, class InputType, template<class> class Container = Field>
188:
189 public refPtr<Container<Type>>
190{
191 // Private Data
192
193 //- Reference to underlying external input data
195
196
197 // Private Member Functions
198
199 //- Set adaptor for different input, copying as required
200 void setInput
201 (
202 Container<InputType>& src,
203 [[maybe_unused]] const bool doCopy
204 )
205 {
206 orig_.ref(src);
207 if constexpr (std::is_same_v<Type, InputType>)
208 {
209 // Use reference directly
210 this->ref(reinterpret_cast<Container<Type>&>(src));
211 }
212 else
213 {
214 // Need intermediate buffer
215 this->reset(new Container<Type>(src.size()));
216 if (doCopy)
217 {
218 std::copy(src.cbegin(), src.cend(), this->ref().begin());
219 }
220 }
221 }
222
223public:
224
225 //- The adapted field type. Same as element_type
226 typedef Container<Type> FieldType;
227
228
229 // Constructors
230
231 //- Default construct, setting content later
232 PrecisionAdaptor() = default;
233
234 //- Construct from Container<InputType>,
235 //- copying input if required (and requested)
236 explicit PrecisionAdaptor
237 (
238 Container<InputType>& input,
239 const bool doCopy = true
240 )
241 {
242 this->setInput(input, doCopy);
243 }
244
245
246 //- Destructor, copies back content changes (as required)
248 {
249 this->commit(); // Commit changes
250 this->clear();
251 }
252
253
254 // Member Functions
256 //- Is precision adaption being used (non-passive adaptor)?
257 bool active() const noexcept
258 {
259 // Same as refPtr::movable()
260 return (this->is_pointer() && this->good());
261 }
262
263 //- Commit adapted content changes back to original input (as required)
264 void commit()
265 {
266 if (this->active() && orig_.good())
267 {
268 const auto& stored = this->cref();
269 auto& input = orig_.ref();
270 input.resize(stored.size()); // Extra safety
271 std::copy(stored.cbegin(), stored.cend(), input.begin());
272 }
273 }
274
275 //- Set adaptor for different input, copying input as required
276 void set(Container<InputType>& input, const bool doCopy = true)
277 {
278 if (orig_.get() != &input)
279 {
280 // Commit changes to old input first
281 this->commit();
283 this->setInput(input, doCopy);
284 }
285};
286
287
288// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
289
290} // End namespace Foam
291
292// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
293
294#endif
295
296// ************************************************************************* //
ConstPrecisionAdaptor(const tmp< Container< InputType > > &input)
Construct from tmp Container of InputType, copy/move as required.
void set(const Container< InputType > &input)
Set adaptor for different input, copying input if required.
bool active() const noexcept
Is precision adaption being used (non-passive adaptor)?
ConstPrecisionAdaptor(const Container< InputType > &input)
Construct from Container of InputType, copying if required.
Container< Type > FieldType
The adapted field type. Same as element_type.
ConstPrecisionAdaptor()=default
Default construct, setting content later.
void set(const tmp< Container< InputType > > &input)
Set adaptor for tmp Container of InputType, copy/move as required.
static const Container< Type > & select(const Container< InputType > &input, Container< Type > &other)
Select a reference to the input (if types are identical), or copy into other and return a reference t...
void commit()
Commit adapted content changes (no-op for const adaptor).
void set(tmp< Container< InputType > > &&input)
Set adaptor for tmp Container of InputType, copy/move as required.
ConstPrecisionAdaptor(tmp< Container< InputType > > &&input)
Construct from tmp Container of InputType, copy/move as required.
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
A non-const Field/List wrapper with possible data conversion.
PrecisionAdaptor()=default
Default construct, setting content later.
bool active() const noexcept
Is precision adaption being used (non-passive adaptor)?
~PrecisionAdaptor()
Destructor, copies back content changes (as required).
Container< Type > FieldType
The adapted field type. Same as element_type.
void set(Container< InputType > &input, const bool doCopy=true)
Set adaptor for different input, copying input as required.
void commit()
Commit adapted content changes back to original input (as required).
PrecisionAdaptor(Container< InputType > &input, const bool doCopy=true)
Construct from Container<InputType>, copying input if required (and requested).
constexpr refPtr() noexcept
Definition refPtrI.H:37
bool is_pointer() const noexcept
Definition refPtrI.H:193
const Field< Type > & cref() const
Definition refPtrI.H:216
bool good() const noexcept
Definition refPtr.H:221
void clear() const noexcept
Definition refPtrI.H:303
void reset(Field< Type > *p=nullptr) noexcept
Definition refPtrI.H:314
Field< Type > & ref() const
Definition refPtrI.H:230
A class for managing temporary objects.
Definition tmp.H:75
Namespace for OpenFOAM.
const direction noexcept
Definition scalarImpl.H:265