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-2021 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 (std::is_same<Type, InputType>::value)
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<Type, InputType>::value && 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;
99
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)
120 {
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);
148 }
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));
154 }
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
162 (
163 const Container<InputType>& input,
164 Container<Type>& other
165 )
166 {
167 if (std::is_same<Type, InputType>::value)
168 {
169 return reinterpret_cast<const Container<Type>&>(input);
170 }
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(Container<InputType>& src, const bool doCopy)
201 {
202 orig_.ref(src);
203 if (std::is_same<Type, InputType>::value)
204 {
205 // Use reference directly
206 this->ref(reinterpret_cast<Container<Type>&>(src));
207 }
208 else
209 {
210 // Need intermediate buffer
211 this->reset(new Container<Type>(src.size()));
212 if (doCopy)
213 {
214 std::copy(src.cbegin(), src.cend(), this->ref().begin());
215 }
216 }
217 }
218
219public:
220
221 //- The adapted field type. Same as element_type
222 typedef Container<Type> FieldType;
223
224
225 // Constructors
226
227 //- Default construct, setting content later
228 PrecisionAdaptor() = default;
229
230 //- Construct from Container<InputType>,
231 //- copying input if required (and requested)
232 explicit PrecisionAdaptor
233 (
234 Container<InputType>& input,
235 const bool doCopy = true
236 )
237 {
238 this->setInput(input, doCopy);
239 }
240
241
242 //- Destructor, copies back content changes (as required)
244 {
245 this->commit(); // Commit changes
246 this->clear();
247 }
248
249
250 // Member Functions
251
252 //- Is precision adaption being used (non-passive adaptor)?
253 bool active() const noexcept
254 {
255 // Same as refPtr::movable()
256 return (this->is_pointer() && this->good());
257 }
258
259 //- Commit adapted content changes back to original input (as required)
260 void commit()
261 {
262 if (this->active() && orig_.good())
263 {
264 const auto& stored = this->cref();
265 auto& input = orig_.ref();
266 input.resize(stored.size()); // Extra safety
267 std::copy(stored.cbegin(), stored.cend(), input.begin());
268 }
269 }
270
271 //- Set adaptor for different input, copying input as required
272 void set(Container<InputType>& input, const bool doCopy = true)
273 {
274 if (orig_.get() != &input)
275 {
276 // Commit changes to old input first
277 this->commit();
278 }
279 this->setInput(input, doCopy);
280 }
281};
282
283
284// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
285
286} // End namespace Foam
287
288// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
289
290#endif
291
292// ************************************************************************* //
A const Field/List wrapper with possible data conversion.
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)
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.
Definition: Field.H:82
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)
A class for managing references or pointers (no reference counting)
Definition: refPtr.H:58
bool is_pointer() const noexcept
True if this is a managed pointer (not a reference)
Definition: refPtr.H:160
const T & cref() const
Definition: refPtrI.H:189
T * get() noexcept
Return pointer without nullptr checking.
Definition: refPtr.H:169
bool good() const noexcept
True if pointer/reference is non-null.
Definition: refPtr.H:154
void clear() const noexcept
Definition: refPtrI.H:283
void reset(refPtr< T > &&other) noexcept
Clear existing and transfer ownership.
Definition: refPtrI.H:303
T & ref() const
Definition: refPtrI.H:203
A class for managing temporary objects.
Definition: tmp.H:65
Namespace for OpenFOAM.
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:55
const direction noexcept
Definition: Scalar.H:223