DynamicFieldI.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
30 
31 template<class T, int SizeMin>
32 template<class ListType>
34 (
35  const ListType& list
36 )
37 {
38  const label len = list.size();
39 
40  if (capacity_ < len)
41  {
42  // Needs more space for the copy operation
43  List<T>::setAddressableSize(capacity_); // Use entire space
44  List<T>::resize_nocopy(len);
45  capacity_ = List<T>::size();
46  }
47 
48  // Perform copy into addressable portion
49  List<T>::setAddressableSize(len);
50  List<T>::operator=(list);
51 }
52 
53 
54 template<class T, int SizeMin>
56 (
57  const bool nocopy,
58  const label newCapacity
59 )
60 {
61  if (newCapacity == capacity_)
62  {
63  return;
64  }
65 
66  // Addressable length, possibly truncated by new capacity
67  const label currLen = min(List<T>::size(), newCapacity);
68 
69  // Corner case - see comments in DynamicList doCapacity
70  if (List<T>::size() == newCapacity)
71  {
72  List<T>::setAddressableSize(currLen+1);
73  }
74 
75  if (nocopy)
76  {
77  List<T>::resize_nocopy(newCapacity);
78  }
79  else
80  {
81  List<T>::resize(newCapacity);
82  }
83 
84  capacity_ = List<T>::size();
85  List<T>::setAddressableSize(currLen);
86 }
87 
88 
89 template<class T, int SizeMin>
91 (
92  const bool nocopy,
93  const label len
94 )
95 {
96  if (capacity_ < len)
97  {
98  // Preserve addressed size
99  const label currLen = List<T>::size();
100 
101  // Increase capacity (doubling)
102  capacity_ = max(SizeMin, max(len, label(2*capacity_)));
103 
104  if (nocopy)
105  {
106  List<T>::resize_nocopy(capacity_);
107  }
108  else
109  {
110  List<T>::resize(capacity_);
111  }
112  List<T>::setAddressableSize(currLen);
113  }
114 }
115 
116 
117 template<class T, int SizeMin>
119 (
120  const bool nocopy,
121  const label len
122 )
123 {
124  this->doReserve(nocopy, len);
126 }
127 
128 
129 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
130 
131 template<class T, int SizeMin>
133 :
134  Field<T>(),
135  capacity_(0)
136 {}
137 
138 
139 template<class T, int SizeMin>
140 inline Foam::DynamicField<T, SizeMin>::DynamicField(const label initialCapacity)
141 :
142  Field<T>(),
143  capacity_(0)
144 {
145  reserve_nocopy(initialCapacity);
146 }
147 
148 
149 template<class T, int SizeMin>
151 (
152  const label len,
153  const T& val
154 )
155 :
156  Field<T>(len, val),
157  capacity_(Field<T>::size())
158 {}
159 
160 
161 template<class T, int SizeMin>
163 (
164  const label len,
165  const Foam::zero
166 )
167 :
168  Field<T>(len, Foam::zero{}),
169  capacity_(Field<T>::size())
170 {}
171 
172 
173 template<class T, int SizeMin>
175 (
176  const DynamicField<T, SizeMin>& list
177 )
178 :
179  Field<T>(list),
180  capacity_(Field<T>::size())
181 {}
182 
183 
184 template<class T, int SizeMin>
185 template<int AnySizeMin>
187 (
188  const DynamicField<T, AnySizeMin>& list
189 )
190 :
191  Field<T>(list),
192  capacity_(Field<T>::size())
193 {}
194 
195 
196 template<class T, int SizeMin>
198 (
199  const UList<T>& list
200 )
201 :
202  Field<T>(list),
203  capacity_(Field<T>::size())
204 {}
205 
206 
207 template<class T, int SizeMin>
208 template<class Addr>
210 (
211  const IndirectListBase<T, Addr>& list
212 )
213 :
214  Field<T>(list),
215  capacity_(Field<T>::size())
216 {}
217 
218 
219 template<class T, int SizeMin>
221 (
222  List<T>&& content
223 ) noexcept
224 :
225  Field<T>(std::move(content)),
226  capacity_(Field<T>::size())
227 {}
228 
229 
230 template<class T, int SizeMin>
231 template<int AnySizeMin>
233 (
235 ) noexcept
236 :
237  Field<T>(std::move(static_cast<List<T>&>(content))),
238  capacity_(content.capacity())
239 {
240  content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
241 }
242 
243 
244 template<class T, int SizeMin>
246 (
247  DynamicField<T, SizeMin>&& content
248 ) noexcept
249 :
250  Field<T>(std::move(static_cast<List<T>&>(content))),
251  capacity_(content.capacity())
252 {
253  content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
254 }
255 
256 
257 template<class T, int SizeMin>
258 template<int AnySizeMin>
260 (
262 ) noexcept
263 :
264  Field<T>(std::move(static_cast<List<T>&>(content))),
265  capacity_(content.capacity())
266 {
267  content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
268 }
269 
270 
271 template<class T, int SizeMin>
273 (
274  const UList<T>& mapF,
275  const labelUList& mapAddressing
276 )
277 :
278  Field<T>(mapF, mapAddressing),
279  capacity_(Field<T>::size())
280 {}
281 
282 
283 template<class T, int SizeMin>
285 (
286  const UList<T>& mapF,
287  const labelListList& mapAddressing,
288  const scalarListList& weights
289 )
290 :
291  Field<T>(mapF, mapAddressing, weights),
292  capacity_(Field<T>::size())
293 {}
294 
295 
296 template<class T, int SizeMin>
298 (
299  const UList<T>& mapF,
300  const FieldMapper& map
301 )
302 :
303  Field<T>(mapF, map),
304  capacity_(Field<T>::size())
305 {}
306 
307 
308 template<class T, int SizeMin>
310 :
311  Field<T>(is),
312  capacity_(Field<T>::size())
313 {}
314 
315 
316 template<class T, int SizeMin>
319 {
320  return tmp<DynamicField<T, SizeMin>>::New(*this);
321 }
322 
323 
324 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
325 
326 template<class T, int SizeMin>
327 inline std::streamsize
329 {
330  return std::streamsize(capacity_)*sizeof(T);
331 }
332 
333 
334 template<class T, int SizeMin>
336 (
337  const label len
338 )
339 {
340  this->doCapacity(false, len); // nocopy = false
341 }
342 
343 
344 template<class T, int SizeMin>
346 (
347  const label len
348 )
349 {
350  this->doCapacity(true, len); // nocopy = true
351 }
352 
353 
354 template<class T, int SizeMin>
356 (
357  const label len
358 ) noexcept
359 {
360  capacity_ = len;
361 }
362 
363 
364 template<class T, int SizeMin>
366 (
367  const label len
368 )
369 {
370  this->doReserve(false, len); // nocopy = false
371 }
372 
373 
374 template<class T, int SizeMin>
376 (
377  const label len
378 )
379 {
380  this->doReserve(true, len); // nocopy = true
381 }
382 
383 
384 template<class T, int SizeMin>
386 (
387  const label len
388 )
389 {
390  this->doResize(false, len); // nocopy = false
391 }
392 
393 
394 template<class T, int SizeMin>
396 (
397  const label len
398 )
399 {
400  this->doResize(true, len); // nocopy = true
401 }
402 
403 
404 template<class T, int SizeMin>
406 (
407  const label len,
408  const T& val
409 )
410 {
411  const label oldLen = List<T>::size();
412  resize(len);
413 
414  // Fill newly exposed with constant value
415  if (oldLen < List<T>::size())
416  {
417  std::fill
418  (
419  this->begin(oldLen), this->end(), val
420  );
421  }
422 }
423 
424 
425 template<class T, int SizeMin>
427 {
429 }
430 
431 
432 template<class T, int SizeMin>
434 {
435  List<T>::clear();
436  capacity_ = 0;
437 }
438 
439 
440 template<class T, int SizeMin>
442 {
443  const label currLen = List<T>::size();
444 
445  if (currLen < capacity_)
446  {
447  // Adjust addressable size to trigger proper resizing
448  List<T>::setAddressableSize(currLen+1);
449  List<T>::resize(currLen);
450  capacity_ = List<T>::size();
451  }
452 }
453 
454 
455 template<class T, int SizeMin>
457 {
458  if (List<T>::empty())
459  {
460  // Delete storage if empty
461  List<T>::clear();
462  }
463  capacity_ = List<T>::size();
464 }
465 
466 
467 template<class T, int SizeMin>
470 {
471  this->shrink_to_fit();
472  return *this;
473 }
474 
475 
476 template<class T, int SizeMin>
477 inline void
479 {
480  if
481  (
482  static_cast<const List<T>*>(this)
483  == static_cast<const List<T>*>(&list)
484  )
485  {
486  return; // Self-swap is a no-op
487  }
488 
489  // Remove unused storage
490  this->shrink_to_fit();
491 
492  // Swap storage and addressable size
493  UList<T>::swap(list);
494 
495  // Update capacity
496  capacity_ = List<T>::size();
497 }
498 
499 
500 template<class T, int SizeMin>
501 template<int AnySizeMin>
503 (
505 )
506 {
507  if
508  (
509  static_cast<const List<T>*>(this)
510  == static_cast<const List<T>*>(&other)
511  )
512  {
513  return; // Self-swap is a no-op
514  }
515 
516  // Swap storage and addressable size
517  UList<T>::swap(other);
518 
519  // Swap capacity
520  std::swap(this->capacity_, other.capacity_);
521 }
522 
523 
524 template<class T, int SizeMin>
525 template<int AnySizeMin>
527 (
529 )
530 {
531  if
532  (
533  static_cast<const List<T>*>(this)
534  == static_cast<const List<T>*>(&other)
535  )
536  {
537  return; // Self-swap is a no-op
538  }
539 
540  // Swap storage and addressable size
541  UList<T>::swap(other);
542 
543  // Swap capacity
544  const label oldCap = this->capacity();
545  const label newCap = other.capacity();
547  this->setCapacity_unsafe(newCap);
548  other.setCapacity_unsafe(oldCap);
549 }
550 
551 
552 template<class T, int SizeMin>
554 {
555  Field<T>::transfer(list);
556  capacity_ = Field<T>::size();
557 }
558 
559 
560 template<class T, int SizeMin>
561 template<int AnySizeMin>
563 (
565 )
566 {
567  if
568  (
569  static_cast<const List<T>*>(this)
570  == static_cast<const List<T>*>(&list)
571  )
572  {
573  return; // Self-assignment is a no-op
574  }
575 
576  // Take over storage as-is (without shrink)
577  capacity_ = list.capacity();
578  Field<T>::transfer(static_cast<List<T>&>(list));
579  list.clearStorage(); // capacity=0 etc.
580 }
581 
582 
583 template<class T, int SizeMin>
584 template<int AnySizeMin>
586 (
588 )
589 {
590  if
591  (
592  static_cast<const List<T>*>(this)
593  == static_cast<const List<T>*>(&list)
594  )
595  {
596  return; // Self-assignment is a no-op
597  }
598 
599  // Take over storage as-is (without shrink)
600  capacity_ = list.capacity();
601  Field<T>::transfer(static_cast<List<T>&>(list));
602  list.clearStorage(); // capacity=0 etc.
603 }
604 
605 
606 template<class T, int SizeMin>
607 template<class... Args>
609 {
610  // This could/should be better with inplace construction
611  // (as per std::vector), but currently lacking the methods for that
612  // so resize and move assign
613 
614  const label idx = List<T>::size();
615  resize(idx + 1);
616 
617  // move assign element
618  this->operator[](idx) = T(std::forward<Args>(args)...);
619  return this->operator[](idx);
620 }
621 
622 
623 template<class T, int SizeMin>
625 (
626  const T& val
627 )
628 {
629  const label idx = List<T>::size();
630  resize(idx + 1);
632  this->operator[](idx) = val; // copy element
633 }
634 
635 
636 template<class T, int SizeMin>
638 (
639  T&& val
640 )
641 {
642  const label idx = List<T>::size();
643  resize(idx + 1);
645  this->operator[](idx) = std::move(val); // move assign element
646 }
647 
648 
649 template<class T, int SizeMin>
651 (
652  const UList<T>& list
653 )
654 {
655  if (this == &list)
656  {
658  << "Attempted push_back to self"
659  << abort(FatalError);
660  }
661 
662  const label idx = List<T>::size();
663  resize(idx + list.size());
665  std::copy(list.begin(), list.end(), this->begin(idx));
666 }
667 
668 
669 template<class T, int SizeMin>
671 (
672  List<T>&& list
673 )
674 {
675  if (this == &list)
676  {
678  << "Attempted push_back to self"
679  << abort(FatalError);
680  }
681 
682  const label idx = List<T>::size();
683  resize(idx + list.size());
684 
685  std::move(list.begin(), list.end(), this->begin(idx));
686 
687  list.clear();
688 }
689 
690 
691 template<class T, int SizeMin>
693 {
694  if (n >= this->size())
695  {
696  this->clear();
697  }
698  else if (n > 0)
699  {
700  resize(this->size() - n);
701  }
702 }
703 
704 
705 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
706 
707 template<class T, int SizeMin>
709 (
710  const label i
711 )
712 {
713  if (i >= List<T>::size())
714  {
715  resize(i + 1);
716  }
718  return this->operator[](i);
719 }
720 
721 
722 template<class T, int SizeMin>
724 (
725  const T& val
726 )
727 {
728  UList<T>::operator=(val);
729 }
730 
731 
732 template<class T, int SizeMin>
734 (
735  const Foam::zero
736 )
737 {
739 }
740 
741 
742 template<class T, int SizeMin>
744 (
745  const UList<T>& list
746 )
747 {
748  doAssignDynList(list);
749 }
750 
751 
752 template<class T, int SizeMin>
754 (
755  const DynamicField<T, SizeMin>& list
756 )
757 {
758  if (this == &list)
759  {
760  return; // Self-assignment is a no-op
761  }
762 
763  doAssignDynList(list);
764 }
765 
766 
767 template<class T, int SizeMin>
768 template<class Addr>
770 (
771  const IndirectListBase<T, Addr>& list
772 )
773 {
774  // NOTE: Self-assignment needs special handling
781  doAssignDynList(list);
782 }
783 
784 
785 template<class T, int SizeMin>
787 (
788  List<T>&& list
789 )
790 {
791  transfer(list);
792 }
793 
794 
795 template<class T, int SizeMin>
797 (
799 )
800 {
801  transfer(list);
802 }
803 
804 
805 template<class T, int SizeMin>
806 template<int AnySizeMin>
808 (
810 )
811 {
812  transfer(list);
813 }
814 
815 
816 template<class T, int SizeMin>
817 template<int AnySizeMin>
819 (
821 )
822 {
823  transfer(list);
824 }
825 
826 
827 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
828 
829 template<class T, int SizeMin>
831 (
832  Istream& is
833 )
834 {
835  // Use DynamicList::readList for reading DynamicField.
836  // The logic should be the same and this avoids duplicate code
837 
839  this->swap(list);
840 
841  list.readList(is);
842  this->swap(list);
843 
844  return is;
845 }
846 
847 
848 template<class T, int SizeMin>
849 inline Foam::Istream& Foam::operator>>
850 (
851  Istream& is,
852  DynamicField<T, SizeMin>& rhs
853 )
854 {
855  return rhs.readList(is);
856 }
857 
858 
859 template<class T, int SizeMin>
860 inline Foam::Ostream& Foam::operator<<
861 (
862  Ostream& os,
863  const DynamicField<T, SizeMin>& rhs
864 )
865 {
866  os << static_cast<const Field<T>&>(rhs);
867  return os;
868 }
869 
870 
871 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
void swap(List< T > &list)
Swap with plain List content. Implies shrink_to_fit().
void setCapacity(const label len)
Alter the size of the underlying storage.
patchWriters resize(patchIds.size())
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:326
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
DynamicField< T, SizeMin > & shrink()
Calls shrink_to_fit() and returns a reference to the DynamicField.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
void push_back(const T &val)
Copy append an element at the end of the list.
constexpr DynamicField() noexcept
Default construct, an empty field without allocation.
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
Istream & readList(Istream &is)
Read from Istream, discarding existing contents.
void transfer(List< T > &list)
Transfer the parameter contents into this.
void reserve_nocopy(const label len)
Reserve allocation space for at least this size, allocating new space if required without retaining o...
label capacity() const noexcept
Size of the underlying storage.
Definition: DynamicList.H:225
void resize_nocopy(const label len)
Alter addressable list size, allocating new space if required without necessarily recovering old cont...
tmp< DynamicField< T, SizeMin > > clone() const
Clone.
void setCapacity_unsafe(const label len) noexcept
Change the value for the list capacity directly (ADVANCED, UNSAFE) Does not perform any memory manage...
label capacity() const noexcept
Size of the underlying storage.
Definition: DynamicField.H:236
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Abstract base class to hold the Field mapping addressing and weights.
Definition: FieldMapper.H:43
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
Generic templated field type.
Definition: Field.H:62
void shrink_to_fit()
Shrink the allocated space to the number of elements used.
void pop_back(label n=1)
Reduce size by 1 or more elements. Can be called on an empty list.
Dynamically sized Field.
Definition: DynamicField.H:45
patchWriters clear()
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:391
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
void shrink_unsafe()
Shrink the internal bookkeeping of the allocated space to the number of addressed elements without af...
Istream & readList(Istream &is)
Read from Istream, discarding existing contents.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: Scalar.H:258
void setCapacity_unsafe(const label len) noexcept
Change the value for the list capacity directly (ADVANCED, UNSAFE) Does not perform any memory manage...
Definition: DynamicListI.H:323
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
OBJstream os(runTime.globalPath()/outputName)
const volScalarField & T
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
void clearStorage()
Clear the list and delete storage.
void setCapacity_nocopy(const label len)
Alter the size of the underlying storage, without retaining old content.
std::streamsize capacity_bytes() const noexcept
Number of contiguous bytes of the underlying storage.
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:412
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
label n
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:435
A class for managing temporary objects.
Definition: HashPtrTable.H:50
Foam::argList args(argc, argv)
constexpr auto begin(C &c) -> decltype(c.begin())
Return iterator to the beginning of the container c.
Definition: stdFoam.H:168
A non-counting (dummy) refCount.
Definition: refCount.H:55
Namespace for OpenFOAM.
friend Ostream & operator(Ostream &os, const DynamicField< T, SizeMin > &rhs)
Write to Ostream.