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 -------------------------------------------------------------------------------
10 License
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 
26 Class
27  Foam::PrecisionAdaptor
28 
29 Description
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 PrecisionAdaptor_H
40 #define 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 
49 namespace Foam
50 {
51 
52 /*---------------------------------------------------------------------------*\
53  Class ConstPrecisionAdaptor Declaration
54 \*---------------------------------------------------------------------------*/
55 
56 //- A const Field/List wrapper with possible data conversion
57 template<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 
95 public:
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
186 template<class Type, class InputType, template<class> class Container = Field>
187 class PrecisionAdaptor
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 
219 public:
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)
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 // ************************************************************************* //
Foam::PrecisionAdaptor::set
void set(Container< InputType > &input, const bool doCopy=true)
Set adaptor for different input, copying input as required.
Definition: PrecisionAdaptor.H:271
Foam::refPtr< Container< Type > >::is_pointer
bool is_pointer() const noexcept
True if this is a managed pointer (not a reference)
Definition: refPtr.H:160
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
refPtr.H
Foam::ConstPrecisionAdaptor::set
void set(const Container< InputType > &input)
Set adaptor for different input, copying input if required.
Definition: PrecisionAdaptor.H:138
Foam::PrecisionAdaptor::commit
void commit()
Commit adapted content changes back to original input (as required)
Definition: PrecisionAdaptor.H:259
Foam::refPtr::get
T * get() noexcept
Return pointer without nullptr checking.
Definition: refPtr.H:169
Foam::ConstPrecisionAdaptor::set
void set(tmp< Container< InputType >> &&input)
Set adaptor for tmp Container of InputType, copy/move as required.
Definition: PrecisionAdaptor.H:144
Foam::refPtr< Container< Type > >::clear
void clear() const noexcept
Definition: refPtrI.H:283
Foam::ConstPrecisionAdaptor::ConstPrecisionAdaptor
ConstPrecisionAdaptor(tmp< Container< InputType >> &&input)
Construct from tmp Container of InputType, copy/move as required.
Definition: PrecisionAdaptor.H:112
Foam::ConstPrecisionAdaptor::ConstPrecisionAdaptor
ConstPrecisionAdaptor()=default
Default construct, setting content later.
Foam::ConstPrecisionAdaptor::select
static const Container< Type > & select(const Container< InputType > &input, Container< Type > &other)
Definition: PrecisionAdaptor.H:161
Foam::refPtr< Container< Type > >::reset
void reset(refPtr< Container< Type > > &&other) noexcept
Clear existing and transfer ownership.
Definition: refPtrI.H:303
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::refPtr< Container< Type > >::cref
const Container< Type > & cref() const
Definition: refPtrI.H:189
Foam::PrecisionAdaptor::PrecisionAdaptor
PrecisionAdaptor()=default
Default construct, setting content later.
Field.H
Foam::PrecisionAdaptor::~PrecisionAdaptor
~PrecisionAdaptor()
Destructor, copies back content changes (as required)
Definition: PrecisionAdaptor.H:242
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::ConstPrecisionAdaptor::set
void set(const tmp< Container< InputType >> &input)
Set adaptor for tmp Container of InputType, copy/move as required.
Definition: PrecisionAdaptor.H:150
Foam::PrecisionAdaptor
A non-const Field/List wrapper with possible data conversion.
Definition: PrecisionAdaptor.H:186
Foam::PrecisionAdaptor::active
bool active() const noexcept
Is precision adaption being used (non-passive adaptor)?
Definition: PrecisionAdaptor.H:252
Foam::PrecisionAdaptor::FieldType
Container< Type > FieldType
The adapted field type. Same as element_type.
Definition: PrecisionAdaptor.H:221
Foam::ConstPrecisionAdaptor::ConstPrecisionAdaptor
ConstPrecisionAdaptor(const Container< InputType > &input)
Construct from Container of InputType, copying if required.
Definition: PrecisionAdaptor.H:106
Foam::ConstPrecisionAdaptor
A const Field/List wrapper with possible data conversion.
Definition: PrecisionAdaptor.H:57
Foam::input
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:55
Foam::ConstPrecisionAdaptor::active
bool active() const noexcept
Is precision adaption being used (non-passive adaptor)?
Definition: PrecisionAdaptor.H:127
Foam::ConstPrecisionAdaptor::commit
void commit()
Commit adapted content changes (no-op for const adaptor)
Definition: PrecisionAdaptor.H:134
Foam::ConstPrecisionAdaptor::FieldType
Container< Type > FieldType
The adapted field type. Same as element_type.
Definition: PrecisionAdaptor.H:97
Foam::refPtr< Container< Type > >::good
bool good() const noexcept
True if pointer/reference is non-null.
Definition: refPtr.H:154
Foam::refPtr< Container< Type > >::ref
Container< Type > & ref() const
Definition: refPtrI.H:203
Foam::ConstPrecisionAdaptor::ConstPrecisionAdaptor
ConstPrecisionAdaptor(const tmp< Container< InputType >> &input)
Construct from tmp Container of InputType, copy/move as required.
Definition: PrecisionAdaptor.H:118
Foam::refPtr
A class for managing references or pointers (no reference counting)
Definition: PtrList.H:60