BELFEM 0.9.3
Berkeley Lab Finite Element Framework
Loading...
Searching...
No Matches
cl_Cell.hpp
Go to the documentation of this file.
1/*
2 * BELFEM -- The Berkeley Lab Finite Element Framework
3 * Copyright (c) 2026, The Regents of the University of California,
4 * through Lawrence Berkeley National Laboratory (subject to receipt of any required
5 * approvals from the U.S. Dept. of Energy). All rights reserved.
6 *
7 * Developers: Christian Messe, Gregory Giard
8 *
9 * See the top-level LICENSE file for the complete license and disclaimer.
10 */
11
12#ifndef BELFEM_CL_CELL_HPP
13#define BELFEM_CL_CELL_HPP
14
15#include <vector>
16#include <initializer_list>
17#include <algorithm> // for unique and reverse
18#include <iterator> // for std::make_move_iterator
19#include <sstream> // for std::ostringstream (generic print)
20
21#include "typedefs.hpp"
22#include "assert.hpp"
23
24namespace belfem
25{
26 namespace cell
27 {
28 void
29 error_out_of_bounds( const index_t aI, const index_t aN );
30 }
31//------------------------------------------------------------------------------
32
43 template< typename T >
44 class Cell
45 {
46//------------------------------------------------------------------------------
47 private:
48//------------------------------------------------------------------------------
49
50 std::vector< T > mCell;
51
52//------------------------------------------------------------------------------
53 public:
54//------------------------------------------------------------------------------
55
56 Cell() = default ;
57
58//------------------------------------------------------------------------------
59
63 Cell( const std::size_t aReserve )
64 {
65 mCell.reserve( aReserve );
66 }
67
68 Cell( const std::size_t aSize, const T aInitializationValue )
69 {
70 mCell.resize( aSize, aInitializationValue );
71 }
72
73//------------------------------------------------------------------------------
74
75 Cell( const std::initializer_list< T > & aInitList ) :
76 mCell( aInitList )
77 {
78 }
79
80//------------------------------------------------------------------------------
81
82 // Copy constructor - explicit implementation
83 Cell( const Cell< T > & other ) : mCell( other.mCell )
84 {
85 }
86
87//------------------------------------------------------------------------------
88
89 // Move constructor - explicit implementation with noexcept
90 Cell( Cell< T > && other ) noexcept : mCell( std::move( other.mCell ) )
91 {
92 // other.mCell is now in valid but unspecified state (empty for vector)
93 }
94
95//------------------------------------------------------------------------------
96
97 // Copy assignment operator - explicit implementation
98 Cell< T >& operator=( const Cell< T > & other )
99 {
100 if ( this != &other )
101 {
102 mCell = other.mCell;
103 }
104 return *this;
105 }
106
107//------------------------------------------------------------------------------
108
109 // Move assignment operator - explicit implementation with noexcept
110 Cell< T >& operator=( Cell< T > && other ) noexcept
111 {
112 if ( this != &other )
113 {
114 mCell = std::move( other.mCell );
115 // other.mCell is now in valid but unspecified state
116 }
117 return *this;
118 }
119
120//------------------------------------------------------------------------------
121
122 ~Cell() = default;
123
124//------------------------------------------------------------------------------
125
129 T * data()
130 {
131 return mCell.data();
132 }
133
134//------------------------------------------------------------------------------
135
136 const T * data() const
137 {
138 return mCell.data();
139 }
140
141//------------------------------------------------------------------------------
142
145 std::vector< T > &
147 {
148 return mCell;
149 }
150
151//------------------------------------------------------------------------------
152
153 const std::vector< T > &
155 {
156 return mCell;
157 }
158
159//------------------------------------------------------------------------------
160
161 auto
162 operator()( size_t aIndex )
163 -> decltype( mCell[ aIndex ] )
164 {
165 BELFEM_ASSERT( aIndex < mCell.size() ,
166 "Cell index out of bounds: %lu (expect < %lu)",
167 (long unsigned int)aIndex,
168 (long unsigned int)mCell.size() );
169 return mCell[ aIndex ];
170 }
171
172
173//------------------------------------------------------------------------------
174
175 auto
176 operator()( size_t aIndex ) const
177 -> decltype( mCell[ aIndex ] )
178 {
179 BELFEM_ASSERT( aIndex < mCell.size() ,
180 "Cell index out of bounds: %lu (expect < %lu)",
181 (long unsigned int)aIndex,
182 (long unsigned int)mCell.size() );
183 return mCell[ aIndex ];
184 }
185
186//------------------------------------------------------------------------------
187
188 size_t
189 size() const
190 {
191 return mCell.size();
192 }
193
194//------------------------------------------------------------------------------
195
198 void
199 set_size( const size_t aSize )
200 {
201 mCell.resize( aSize );
202 }
203
204//------------------------------------------------------------------------------
205
206 void
207 set_size( const size_t aSize, const T & aValue )
208 {
209 mCell.resize( aSize, aValue );
210 }
211
212//------------------------------------------------------------------------------
213
214 auto
215 begin() -> decltype( mCell.begin() )
216 {
217 return mCell.begin();
218 }
219
220//------------------------------------------------------------------------------
221
222 auto
223 end() -> decltype( mCell.end() )
224 {
225 return mCell.end();
226 }
227
228//------------------------------------------------------------------------------
229
230 auto
231 begin() const -> decltype( mCell.begin() )
232 {
233 return mCell.begin();
234 }
235
236//------------------------------------------------------------------------------
237
238 auto
239 end() const -> decltype( mCell.end() )
240 {
241 return mCell.end();
242 }
243
244//------------------------------------------------------------------------------
245
248 void
250 {
251 mCell.clear();
252 }
253
254//------------------------------------------------------------------------------
255
256 void
257 reserve( const size_t aSize )
258 {
259 mCell.reserve( aSize );
260 }
261
262//------------------------------------------------------------------------------
263
264 void
265 push( const T & aValue )
266 {
267 mCell.push_back( aValue );
268 }
269
270//------------------------------------------------------------------------------
271
272 void
273 push( T && aValue )
274 {
275 mCell.push_back( std::move( aValue ) );
276 }
277
278//------------------------------------------------------------------------------
279
280 template< typename... Args >
281 void
282 emplace( Args&&... args )
283 {
284 mCell.emplace_back( std::forward< Args >( args )... );
285 }
286
287//------------------------------------------------------------------------------
288
289 T
291 {
292 T aPop = std::move( mCell.back() ); // Move instead of copy
293 mCell.pop_back();
294 return aPop;
295 }
296
297
298//------------------------------------------------------------------------------
299
300 void
302 {
303 mCell.shrink_to_fit();
304 }
305
306//------------------------------------------------------------------------------
307
308 T &
310 {
311#if !defined( NDEBUG ) || defined( DEBUG )
312 return mCell.at( 0 );
313#else
314 return mCell[ 0 ];
315#endif
316 }
317
318//------------------------------------------------------------------------------
319
320 const T &
321 first() const
322 {
323#if !defined( NDEBUG ) || defined( DEBUG )
324 return mCell.at( 0 );
325#else
326 return mCell[ 0 ];
327#endif
328 }
329
330//------------------------------------------------------------------------------
331
332 T &
334 {
335#if !defined( NDEBUG ) || defined( DEBUG )
336 return mCell.at( mCell.size()-1 );
337#else
338 return mCell[ mCell.size()-1 ];
339#endif
340 }
341
342//------------------------------------------------------------------------------
343
344 const T &
345 last() const
346 {
347#if !defined( NDEBUG ) || defined( DEBUG )
348 return mCell.at( mCell.size()-1 );
349#else
350 return mCell[ mCell.size()-1 ];
351#endif
352 }
353
354//------------------------------------------------------------------------------
355
359 void
360 swap( Cell< T > & other ) noexcept
361 {
362 mCell.swap( other.mCell );
363 }
364
365//------------------------------------------------------------------------------
366
367 bool
368 empty() const
369 {
370 return mCell.empty();
371 }
372
373//------------------------------------------------------------------------------
374
375 size_t
376 capacity() const
377 {
378 return mCell.capacity();
379 }
380
381//------------------------------------------------------------------------------
382
383 auto
384 insert( typename std::vector< T >::const_iterator pos, const T & value )
385 -> decltype( mCell.insert( pos, value ) )
386 {
387 return mCell.insert( pos, value );
388 }
389
390//------------------------------------------------------------------------------
391
392 auto
393 insert( typename std::vector< T >::const_iterator pos, T && value )
394 -> decltype( mCell.insert( pos, std::move( value ) ) )
395 {
396 return mCell.insert( pos, std::move( value ) );
397 }
398
399//------------------------------------------------------------------------------
400
401 auto
402 erase( typename std::vector< T >::const_iterator pos )
403 -> decltype( mCell.erase( pos ) )
404 {
405 return mCell.erase( pos );
406 }
407
408//------------------------------------------------------------------------------
409
413 auto
414 erase( typename std::vector< T >::const_iterator first,
415 typename std::vector< T >::const_iterator last )
416 -> decltype( mCell.erase( first, last ) )
417 {
418 return mCell.erase( first, last );
419 }
420
421//------------------------------------------------------------------------------
422
423 void
424 print( const std::string aLabel="" ) const ;
425
426//------------------------------------------------------------------------------
427 };
428
429 template< typename T >
430 void
431 sort( Cell< T > & aCell )
432 {
433 std::vector< T > & tVec = aCell.vector_data();
434
435 std::sort( tVec.begin(), tVec.end() );
436 }
437
438//------------------------------------------------------------------------------
439
440 template< typename T, class C >
441 void
442 sort( Cell< T > & aCell, C & aComp, const size_t aNumberOfItems=0 )
443 {
444 std::vector< T > & tVec = aCell.vector_data();
445
446 if( aNumberOfItems==0 )
447 {
448 std::sort( tVec.begin(), tVec.end(), aComp );
449 }
450 else
451 {
452 std::sort( tVec.begin(), tVec.begin()+aNumberOfItems, aComp );
453 }
454 }
455
456//------------------------------------------------------------------------------
457
460 template< typename T >
461 void
462 unique( Cell< T > & aCell )
463 {
464 std::vector< T > & tVec = aCell.vector_data();
465
466 std::sort( tVec.begin(), tVec.end() );
467
468 tVec.erase( std::unique( tVec.begin(), tVec.end() ), tVec.end() );
469 }
470
471//------------------------------------------------------------------------------
472
477 template< typename T >
478 index_t
479 find_index_in_unique_cell( const Cell< T > & aCell, const T & aMember )
480 {
481 auto tIterator = std::lower_bound( aCell.vector_data().begin(),
482 aCell.vector_data().end(), aMember );
483
484 BELFEM_ASSERT( tIterator != aCell.vector_data().end()
485 && ! ( aMember < *tIterator ),
486 "member not found in cell (is the cell sorted and unique?)" );
487
488 return tIterator - aCell.vector_data().begin();
489 }
490
491//------------------------------------------------------------------------------
492
493 template< typename T >
494 void
496 {
497 std::vector< T > & tVec = aCell.vector_data();
498
499 std::reverse( tVec.begin(), tVec.end() );
500 }
501
502//------------------------------------------------------------------------------
503
504 template< typename T >
505 void
506 append( Cell< T > & aA, const Cell< T > & aB )
507 {
508 aA.vector_data().reserve(aA.vector_data().size() + aB.vector_data().size());
509
510 aA.vector_data().insert(
511 aA.vector_data().end(),
512 aB.vector_data().begin(),
513 aB.vector_data().end()
514 );
515 }
516
517//------------------------------------------------------------------------------
518
519 template< typename T >
520 void
521 append_move( Cell< T > & aTarget, Cell< T > & aSource )
522 {
523 aTarget.vector_data().reserve(aTarget.vector_data().size() + aSource.vector_data().size());
524
525 aTarget.vector_data().insert(
526 aTarget.vector_data().end(),
527 std::make_move_iterator(aSource.vector_data().begin()),
528 std::make_move_iterator(aSource.vector_data().end()));
529
530 aSource.clear();
531 }
532
533//------------------------------------------------------------------------------
534
538 template< typename T >
539 void
540 swap( Cell< T > & aA, Cell< T > & aB ) noexcept
541 {
542 aA.swap( aB );
543 }
544
545//------------------------------------------------------------------------------
546
547// turn off annoying waning
548#ifdef BELFEM_CLANG
549#pragma clang diagnostic push
550#pragma clang diagnostic ignored "-Wformat-security"
551#elif BELFEM_GCC
552#pragma GCC diagnostic push
553#pragma GCC diagnostic ignored "-Wformat"
554#elif BELFEM_INTEL
555#pragma warning push
556#pragma warning disable 1595
557#endif
558
559 template < typename T > void
560 Cell< T >::print( const std::string aLabel ) const
561 {
562 FILE * tOutFile = stdout;
563
564 fprintf( tOutFile, "\n%s = [ ... \n", aLabel.c_str() );
565
566 const Cell< T > & tThis = *this;
567
568 uint tLength = tThis.size();
569
570 for( uint i=0; i< tLength; ++i )
571 {
572 // use std::ostringstream for generic types (including std::string)
573 std::ostringstream tStream;
574 tStream << tThis( i );
575 fprintf( tOutFile, "%s; ", tStream.str().c_str() );
576
577 if( i < tLength-1 )
578 {
579 fprintf( tOutFile, "...\n" );
580 }
581 else
582 {
583 fprintf( tOutFile, "];\n" );
584 }
585 }
586 }
587
588// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
589
590 template <>
591 inline void
592 Cell< real >::print( const std::string aLabel ) const
593 {
594 FILE * tOutFile = stdout;
595
596 fprintf( tOutFile, "%s = [ ... \n", aLabel.c_str() );
597
598 const Cell< real > & tThis = *this;
599
600 uint tLength = tThis.size();
601
602 for( uint i=0; i< tLength; ++i )
603 {
604
605 fprintf( tOutFile, "%+.15e; ", ( double ) tThis( i ) );
606
607
608 if( i < tLength-1 )
609 {
610 fprintf( tOutFile, "...\n" );
611 }
612 else
613 {
614 fprintf( tOutFile, "];\n" );
615 }
616 }
617 }
618
619#ifdef BELFEM_CLANG
620#pragma clang diagnostic pop
621#elif BELFEM_GCC
622#pragma GCC diagnostic pop
623#elif BELFEM_INTEL
624#pragma warning pop
625#endif
626
627
628//------------------------------------------------------------------------------
629} /* namespace belfem */
630
631#endif //BELFEM_CL_CELL_HPP
#define BELFEM_ASSERT(aCheck,...)
Definition assert.hpp:244
A bounds-checked wrapper around std::vector.
Definition cl_Cell.hpp:45
T pop()
Definition cl_Cell.hpp:290
Cell(const Cell< T > &other)
Definition cl_Cell.hpp:83
auto begin() const -> decltype(mCell.begin())
Definition cl_Cell.hpp:231
void print(const std::string aLabel="") const
Definition cl_Cell.hpp:560
bool empty() const
Definition cl_Cell.hpp:368
void set_size(const size_t aSize)
New elements are value-initialized ( zero for arithmetic T, nullptr for pointers ).
Definition cl_Cell.hpp:199
Cell(const std::initializer_list< T > &aInitList)
Definition cl_Cell.hpp:75
T & first()
Definition cl_Cell.hpp:309
size_t size() const
Definition cl_Cell.hpp:189
auto erase(typename std::vector< T >::const_iterator pos) -> decltype(mCell.erase(pos))
Definition cl_Cell.hpp:402
void swap(Cell< T > &other) noexcept
Swap contents with another Cell.
Definition cl_Cell.hpp:360
void emplace(Args &&... args)
Definition cl_Cell.hpp:282
const T & last() const
Definition cl_Cell.hpp:345
size_t capacity() const
Definition cl_Cell.hpp:376
void clear()
Empties the Cell.
Definition cl_Cell.hpp:249
auto begin() -> decltype(mCell.begin())
Definition cl_Cell.hpp:215
void set_size(const size_t aSize, const T &aValue)
Definition cl_Cell.hpp:207
Cell(Cell< T > &&other) noexcept
Definition cl_Cell.hpp:90
Cell< T > & operator=(const Cell< T > &other)
Definition cl_Cell.hpp:98
T & last()
Definition cl_Cell.hpp:333
const T * data() const
Definition cl_Cell.hpp:136
auto end() -> decltype(mCell.end())
Definition cl_Cell.hpp:223
std::vector< T > & vector_data()
The underlying vector.
Definition cl_Cell.hpp:146
auto insert(typename std::vector< T >::const_iterator pos, T &&value) -> decltype(mCell.insert(pos, std::move(value)))
Definition cl_Cell.hpp:393
Cell()=default
auto insert(typename std::vector< T >::const_iterator pos, const T &value) -> decltype(mCell.insert(pos, value))
Definition cl_Cell.hpp:384
Cell< T > & operator=(Cell< T > &&other) noexcept
Definition cl_Cell.hpp:110
Cell(const std::size_t aReserve)
Creates an empty Cell with capacity for aReserve elements.
Definition cl_Cell.hpp:63
void push(const T &aValue)
Definition cl_Cell.hpp:265
auto end() const -> decltype(mCell.end())
Definition cl_Cell.hpp:239
void reserve(const size_t aSize)
Definition cl_Cell.hpp:257
void shrink_to_fit()
Definition cl_Cell.hpp:301
~Cell()=default
const T & first() const
Definition cl_Cell.hpp:321
const std::vector< T > & vector_data() const
Definition cl_Cell.hpp:154
T * data()
Returns a borrowed pointer into contiguous storage, possibly nullptr when the Cell is empty ( test si...
Definition cl_Cell.hpp:129
auto operator()(size_t aIndex) -> decltype(mCell[aIndex])
Definition cl_Cell.hpp:162
Cell(const std::size_t aSize, const T aInitializationValue)
Definition cl_Cell.hpp:68
void push(T &&aValue)
Definition cl_Cell.hpp:273
auto erase(typename std::vector< T >::const_iterator first, typename std::vector< T >::const_iterator last) -> decltype(mCell.erase(first, last))
Erase range of elements.
Definition cl_Cell.hpp:414
auto operator()(size_t aIndex) const -> decltype(mCell[aIndex])
Definition cl_Cell.hpp:176
Definition cl_Cell.cpp:19
void error_out_of_bounds(const index_t aI, const index_t aN)
Definition cl_Cell.cpp:21
USER GUIDES:
Definition cl_Capacitor.cpp:16
void reverse(Cell< T > &aCell)
Definition cl_Cell.hpp:495
void append(Cell< T > &aA, const Cell< T > &aB)
Definition cl_Cell.hpp:506
std::pair< real, unit > value
Definition typedefs.hpp:73
void swap(Cell< T > &aA, Cell< T > &aB) noexcept
Swap specialization for Cell.
Definition cl_Cell.hpp:540
unsigned int uint
Definition typedefs.hpp:30
void unique(Cell< T > &aCell)
Sorts aCell in place and removes the duplicates.
Definition cl_Cell.hpp:462
index_t find_index_in_unique_cell(const Cell< T > &aCell, const T &aMember)
returns the position of a member inside a cell.
Definition cl_Cell.hpp:479
void sort(Cell< T > &aCell)
Definition cl_Cell.hpp:431
uint32_t index_t
Definition typedefs.hpp:52
void append_move(Cell< T > &aTarget, Cell< T > &aSource)
Definition cl_Cell.hpp:521