GEOS
wrapperHelpers.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 Total, S.A
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_DATAREPOSITORY_WRAPPERHELPERS_HPP_
21 #define GEOS_DATAREPOSITORY_WRAPPERHELPERS_HPP_
22 
23 
25 #define RESTART_TYPE_LOGGING 0
26 
27 // Source includes
28 #include "BufferOps.hpp"
29 #include "BufferOpsDevice.hpp"
30 #include "DefaultValue.hpp"
31 #include "ConduitRestart.hpp"
32 #include "common/DataTypes.hpp"
33 #include "common/GeosxMacros.hpp"
34 #include "common/Span.hpp"
35 #include "codingUtilities/traits.hpp"
36 
37 #if defined(GEOS_USE_PYGEOSX)
38 #include "LvArray/src/python/python.hpp"
39 #endif
40 
41 // TPL includes
42 #include <conduit.hpp>
43 
44 // System includes
45 #include <cstring>
46 
47 #if RESTART_TYPE_LOGGING
48 #include <unordered_set>
49 #endif
50 
51 namespace geos
52 {
53 namespace dataRepository
54 {
55 namespace wrapperHelpers
56 {
57 namespace internal
58 {
59 
60 inline void logOutputType( string const & typeString, string const & msg )
61 {
62 #if RESTART_TYPE_LOGGING
63  static std::unordered_set< string > m_types;
64 
65  if( !m_types.count( typeString ) )
66  {
67  m_types.insert( typeString );
68  GEOS_LOG( msg << typeString );
69  }
70 #else
71  GEOS_DEBUG_VAR( typeString );
72  GEOS_DEBUG_VAR( msg );
73 #endif
74 }
75 
76 template< typename T, typename ... INDICES >
77 string getIndicesToComponent( T const &, int const component, INDICES const ... existingIndices )
78 {
79  GEOS_ERROR_IF_NE( component, 0 );
80  return LvArray::indexing::getIndexString( existingIndices ... );
81 }
82 
83 template< typename ... INDICES >
84 string getIndicesToComponent( R1Tensor const &, int const component, INDICES const ... existingIndices )
85 { return LvArray::indexing::getIndexString( existingIndices ..., component ); }
86 
87 template< typename T >
88 T const * getPointerToComponent( T const & var, int const component )
89 {
90  GEOS_ERROR_IF_NE( component, 0 );
91  return &var;
92 }
93 
94 inline
95 real64 const * getPointerToComponent( R1Tensor const & var, int const component )
96 {
97  GEOS_ERROR_IF_GE( component, 3 );
98  return &var[ component ];
99 }
100 
101 } // namespace internal
102 
103 template< typename T >
104 class ArrayDimLabels
105 {
106 public:
107 
108  void set( integer const, Span< string const > )
109  {
110  GEOS_ERROR( "Dimension labels are only available in Array wrappers" );
111  }
112 
113  Span< string const > get( integer const ) const
114  {
115  GEOS_ERROR( "Dimension labels are only available in Array wrappers" );
116  return {};
117  }
118 };
119 
120 template< typename T, int NDIM, typename PERM >
121 class ArrayDimLabels< Array< T, NDIM, PERM > >
122 {
123 public:
124 
125  void set( integer const dim, Span< string const > labels )
126  {
127  GEOS_ERROR_IF_LT( dim, 0 );
128  GEOS_ERROR_IF_GE( dim, NDIM );
129  m_values[dim].resize( labels.size() );
130  std::copy( labels.begin(), labels.end(), m_values[dim].begin() );
131  }
132 
133  Span< string const > get( integer const dim ) const
134  {
135  GEOS_ERROR_IF_LT( dim, 0 );
136  GEOS_ERROR_IF_GE( dim, NDIM );
137  return { m_values[dim].begin(), m_values[dim].end() };
138  }
139 
140 private:
141 
142  string_array m_values[NDIM]{};
143 };
144 
145 template< typename T >
146 inline std::enable_if_t< traits::HasMemberFunction_size< T >, size_t >
147 size( T const & value )
148 { return value.size(); }
149 
150 template< typename T >
151 inline std::enable_if_t< !traits::HasMemberFunction_size< T >, size_t >
152 size( T const & GEOS_UNUSED_PARAM( value ) )
153 { return 1; }
154 
155 
156 inline char *
157 dataPtr( string & var )
158 { return const_cast< char * >( var.data() ); }
159 
160 inline char *
161 dataPtr( Path & var )
162 { return const_cast< char * >( var.data() ); }
163 
164 template< typename T >
165 inline std::enable_if_t< traits::HasMemberFunction_data< T >, typename traits::Pointer< T > >
166 dataPtr( T & value )
167 { return value.data(); }
168 
169 template< typename T >
170 inline std::enable_if_t< !traits::HasMemberFunction_data< T >, typename traits::Pointer< T > >
171 dataPtr( T & value )
172 { return &value; }
173 
174 template< class T >
175 inline typename traits::ConstPointer< T >
176 dataPtr( T const & value )
177 { return dataPtr( const_cast< T & >( value ) ); }
178 
179 
180 template< typename T >
181 inline std::enable_if_t< traits::HasMemberFunction_resize< T > >
182 resize( T & value, localIndex const newSize )
183 { value.resize( newSize ); }
184 
185 template< typename T >
186 inline std::enable_if_t< !traits::HasMemberFunction_resize< T > >
187 resize( T & GEOS_UNUSED_PARAM( value ),
188  localIndex const GEOS_UNUSED_PARAM( newSize ) )
189 {}
190 
191 
192 template< typename T, int NDIM, typename PERMUTATION >
193 inline std::enable_if_t< DefaultValue< Array< T, NDIM, PERMUTATION > >::has_default_value >
194 resizeDefault( Array< T, NDIM, PERMUTATION > & value,
195  localIndex const newSize,
196  DefaultValue< Array< T, NDIM, PERMUTATION > > const & defaultValue )
197 { value.resizeDefault( newSize, defaultValue.value ); }
198 
199 template< typename T >
200 inline void
201 resizeDefault( T & value, localIndex const newSize, DefaultValue< T > const & GEOS_UNUSED_PARAM( defaultValue ) )
202 { resize( value, newSize ); }
203 
204 
205 template< typename T, int NDIM, typename PERMUTATION >
206 inline void
207 resizeDimensions( Array< T, NDIM, PERMUTATION > & value, int num_dims, localIndex const * const dims )
208 { value.resize( num_dims, dims ); }
209 
210 template< typename T >
211 inline void
212 resizeDimensions( T & value, int num_dims, localIndex const * const dims )
213 {
214  if( num_dims != 1 )
215  {
216  GEOS_ERROR( "Data is not multidimensional" );
217  return;
218  }
219  resize( value, dims[ 0 ] );
220 }
221 
222 
223 template< typename T >
224 inline localIndex
225 byteSizeOfElement()
226 { return sizeof( *dataPtr( std::declval< T >() ) ); }
227 
228 
229 template< typename T >
230 inline size_t
231 byteSize( T const & value )
232 { return wrapperHelpers::size( value ) * byteSizeOfElement< T >(); }
233 
234 
235 template< typename T >
236 inline localIndex
237 numElementsFromByteSize( localIndex const byteSize )
238 {
239  GEOS_ERROR_IF_NE( byteSize % byteSizeOfElement< T >(), 0 );
240  return byteSize / byteSizeOfElement< T >();
241 }
242 
243 
244 template< typename T >
245 std::enable_if_t< traits::HasMemberFunction_reserve< T > >
246 reserve( T & value, localIndex const newCapacity )
247 { value.reserve( newCapacity ); }
248 
249 template< typename T >
250 std::enable_if_t< !traits::HasMemberFunction_reserve< T > >
251 reserve( T & GEOS_UNUSED_PARAM( value ), localIndex const GEOS_UNUSED_PARAM( newCapacity ) )
252 {}
253 
254 
255 template< typename T >
256 std::enable_if_t< traits::HasMemberFunction_capacity< T const >, localIndex >
257 capacity( T const & value )
258 { return value.capacity(); }
259 
260 template< typename T >
261 std::enable_if_t< !traits::HasMemberFunction_capacity< T const >, localIndex >
262 capacity( T const & value )
263 { return wrapperHelpers::size( value ); }
264 
265 
266 
267 template< typename T >
268 std::enable_if_t< traits::HasMemberFunction_setName< T > >
269 setName( T & value, string const & name )
270 { value.setName( name ); }
271 
272 template< typename T >
273 std::enable_if_t< !traits::HasMemberFunction_setName< T > >
274 setName( T & GEOS_UNUSED_PARAM( value ), string const & GEOS_UNUSED_PARAM( name ) )
275 {}
276 
277 template< typename T >
278 std::enable_if_t< traits::HasMemberFunction_move< T > >
279 move( T & value, LvArray::MemorySpace const space, bool const touch )
280 { value.move( space, touch ); }
281 
282 template< typename T >
283 std::enable_if_t< !traits::HasMemberFunction_move< T > >
284 move( T & GEOS_UNUSED_PARAM( value ),
285  LvArray::MemorySpace const GEOS_UNUSED_PARAM( space ),
286  bool const GEOS_UNUSED_PARAM( touch ) )
287 {}
288 
289 // This is for an object that needs to be packed.
290 template< typename T >
291 std::enable_if_t< !bufferOps::can_memcpy< typename traits::Pointer< T > > >
292 pushDataToConduitNode( T const & var, conduit::Node & node )
293 {
294  internal::logOutputType( LvArray::system::demangleType( var ), "Packing for output: " );
295 
296  // Get the number of bytes in the packed object.
297  localIndex const byteSize = bufferOps::PackSize( var );
298 
299  // Create a conduit data type that describes the array.
300  conduit::DataType const dtype( conduitTypeInfo< buffer_unit_type >::id, byteSize );
301 
302  // Allocate the array in the "__values__" child.
303  conduit::Node & valuesNode = node[ "__values__" ];
304  valuesNode.set( dtype );
305 
306  // Get the pointer to the array and pack the object into it.
307  buffer_unit_type * buffer = valuesNode.value();
308  bufferOps::Pack< true >( buffer, var );
309 }
310 
311 // This is for an object that needs to be packed.
312 template< typename T >
313 std::enable_if_t< !bufferOps::can_memcpy< typename traits::Pointer< T > > >
314 pullDataFromConduitNode( T & var, conduit::Node const & node )
315 {
316  conduit::Node const & valuesNode = node.fetch_existing( "__values__" );
317 
318  // Get the number of bytes in the array and a pointer to the array.
319  localIndex const byteSize = valuesNode.dtype().number_of_elements();
320  buffer_unit_type const * buffer = valuesNode.value();
321 
322  // Unpack the object from the array.
323  localIndex const bytesRead = bufferOps::Unpack( buffer, var );
324  GEOS_ERROR_IF_NE( bytesRead, byteSize );
325 }
326 
327 // This is for an string since the type of char is different on different platforms :(.
328 inline
329 void
330 pushDataToConduitNode( string const & var, conduit::Node & node )
331 {
332  internal::logOutputType( LvArray::system::demangleType( var ), "Output via external pointer: " );
333 
334  constexpr int conduitTypeID = conduitTypeInfo< signed char >::id;
335  conduit::DataType const dtype( conduitTypeID, var.size() );
336 
337  signed char * const ptr = const_cast< signed char * >( reinterpret_cast< signed char const * >( var.data() ) );
338  node[ "__values__" ].set_external( dtype, ptr );
339 }
340 
341 // This is for Path since it derives from string. See overload for string.
342 inline
343 void
344 pushDataToConduitNode( Path const & var, conduit::Node & node )
345 {
346  pushDataToConduitNode( static_cast< string const & >(var), node );
347 }
348 
349 // This is for an object that doesn't need to be packed but isn't an LvArray.
350 template< typename T >
351 std::enable_if_t< bufferOps::can_memcpy< typename traits::Pointer< T > > >
352 pushDataToConduitNode( T const & var, conduit::Node & node )
353 {
354  internal::logOutputType( LvArray::system::demangleType( var ), "Output via external pointer: " );
355 
356  constexpr int conduitTypeID = conduitTypeInfo< typename traits::Pointer< T > >::id;
357  constexpr int sizeofConduitType = conduitTypeInfo< typename traits::Pointer< T > >::sizeOfConduitType;
358  localIndex const numBytes = byteSize( var );
359  conduit::DataType const dtype( conduitTypeID, numBytes / sizeofConduitType );
360 
361  void * const ptr = const_cast< void * >( static_cast< void const * >( dataPtr( var ) ) );
362  node[ "__values__" ].set_external( dtype, ptr );
363 }
364 
365 // This is for an object that doesn't need to be packed but isn't an LvArray or a SortedArray.
366 template< typename T >
367 std::enable_if_t< bufferOps::can_memcpy< typename traits::Pointer< T > > >
368 pullDataFromConduitNode( T & var, conduit::Node const & node )
369 {
370  conduit::Node const & valuesNode = node.fetch_existing( "__values__" );
371 
372  localIndex const byteSize = LvArray::integerConversion< localIndex >( valuesNode.dtype().strided_bytes() );
373  localIndex const numElements = numElementsFromByteSize< T >( byteSize );
374 
375  resize( var, numElements );
376 
377  std::memcpy( dataPtr( var ), valuesNode.data_ptr(), byteSize );
378 }
379 
380 // This is for a SortedArray that doesn't need to be packed.
381 template< typename T >
382 std::enable_if_t< bufferOps::can_memcpy< T > >
383 pullDataFromConduitNode( SortedArray< T > & var, conduit::Node const & node )
384 {
385  conduit::Node const & valuesNode = node.fetch_existing( "__values__" );
386 
387  localIndex const byteSize = LvArray::integerConversion< localIndex >( valuesNode.dtype().strided_bytes() );
388  localIndex const numElements = numElementsFromByteSize< T >( byteSize );
389 
390  T const * const values = reinterpret_cast< T const * >( valuesNode.data_ptr() );
391  var.insert( values, values + numElements );
392 }
393 
394 
395 // This is an LvArray that doesn't need to be packed.
396 template< typename T, int NDIM, typename PERMUTATION >
397 std::enable_if_t< bufferOps::can_memcpy< T > >
398 pushDataToConduitNode( Array< T, NDIM, PERMUTATION > const & var,
399  conduit::Node & node )
400 {
401  internal::logOutputType( LvArray::system::demangleType( var ), "Output array via external pointer: " );
402 
403  // Push the data into conduit
404  constexpr int conduitTypeID = conduitTypeInfo< T >::id;
405  constexpr int sizeofConduitType = conduitTypeInfo< T >::sizeOfConduitType;
406  conduit::DataType const dtype( conduitTypeID, var.size() * sizeof( T ) / sizeofConduitType );
407  void * const ptr = const_cast< void * >( static_cast< void const * >( var.data() ) );
408  node[ "__values__" ].set_external( dtype, ptr );
409 
410  // Create a copy of the dimensions
411  camp::idx_t temp[ NDIM + 1 ];
412  for( int i = 0; i < NDIM; ++i )
413  {
414  temp[ i ] = var.size( i );
415  }
416 
417  // If T is something like a Tensor than there is an extra implicit dimension.
418  constexpr int const implicitDimensionLength = conduitTypeInfo< T >::numConduitValues;
419  constexpr bool const hasImplicitDimension = implicitDimensionLength != 1;
420  constexpr int totalNumDimensions = NDIM + hasImplicitDimension;
421  if( hasImplicitDimension )
422  {
423  temp[ NDIM ] = implicitDimensionLength;
424  }
425 
426  // push the dimensions into the node
427  conduit::DataType const dimensionType( conduitTypeInfo< camp::idx_t >::id, totalNumDimensions );
428  node[ "__dimensions__" ].set( dimensionType, temp );
429 
430  // Create a copy of the permutation
431  constexpr std::array< camp::idx_t, NDIM > const perm = RAJA::as_array< PERMUTATION >::get();
432  for( int i = 0; i < NDIM; ++i )
433  {
434  temp[ i ] = perm[ i ];
435  }
436 
437  if( hasImplicitDimension )
438  {
439  temp[ NDIM ] = NDIM;
440  }
441 
442  node[ "__permutation__" ].set( dimensionType, temp );
443 }
444 
445 // This is an LvArray that doesn't need to be packed.
446 template< typename T, int NDIM, typename PERMUTATION >
447 std::enable_if_t< bufferOps::can_memcpy< T > >
448 pullDataFromConduitNode( Array< T, NDIM, PERMUTATION > & var,
449  conduit::Node const & node )
450 {
451  // Get the number of dimensions written out, accounting for an implicit dimension and the permutation.
452  constexpr int const implicitDimensionLength = conduitTypeInfo< T >::numConduitValues;
453  constexpr bool const hasImplicitDimension = implicitDimensionLength != 1;
454  constexpr int totalNumDimensions = NDIM + hasImplicitDimension;
455 
456  // Check that the permutations match.
457  conduit::Node const & permutationNode = node.fetch_existing( "__permutation__" );
458  GEOS_ERROR_IF_NE( permutationNode.dtype().number_of_elements(), totalNumDimensions );
459 
460  constexpr std::array< camp::idx_t, NDIM > const perm = RAJA::as_array< PERMUTATION >::get();
461  camp::idx_t const * const permFromConduit = permutationNode.value();
462  for( int i = 0; i < NDIM; ++i )
463  {
464  GEOS_ERROR_IF_NE_MSG( permFromConduit[ i ], perm[ i ],
465  "The permutation of the data in conduit and the provided Array don't match." );
466  }
467 
468  if( hasImplicitDimension )
469  {
470  GEOS_ERROR_IF_NE_MSG( permFromConduit[ NDIM ], NDIM,
471  "The permutation of the data in conduit and the provided Array don't match." );
472  }
473 
474  // Now pull out the dimensions and resize the array.
475  conduit::Node const & dimensionNode = node.fetch_existing( "__dimensions__" );
476  GEOS_ERROR_IF_NE( dimensionNode.dtype().number_of_elements(), totalNumDimensions );
477  camp::idx_t const * const dims = dimensionNode.value();
478 
479  if( hasImplicitDimension )
480  {
481  GEOS_ERROR_IF_NE( dims[ NDIM ], implicitDimensionLength );
482  }
483 
484  var.resize( NDIM, dims );
485 
486  // Finally memcpy
487  conduit::Node const & valuesNode = node.fetch_existing( "__values__" );
488  localIndex numBytesFromArray = var.size() * sizeof( T );
489  GEOS_ERROR_IF_NE( numBytesFromArray, valuesNode.dtype().strided_bytes() );
490  std::memcpy( var.data(), valuesNode.data_ptr(), numBytesFromArray );
491 }
492 
493 
494 
495 template< typename T, typename INDEX_TYPE >
496 std::enable_if_t< bufferOps::can_memcpy< T > >
497 pushDataToConduitNode( ArrayOfArrays< T, INDEX_TYPE > const & var2,
498  conduit::Node & node )
499 {
500  ArrayOfArraysView< T const, INDEX_TYPE > const & var = var2.toViewConst();
501  internal::logOutputType( LvArray::system::demangleType( var ), "Output array via external pointer: " );
502 
503  // ArrayOfArrays::m_numArrays
504  INDEX_TYPE const numArrays = var.size();
505  conduit::DataType const numArraysType( conduitTypeInfo< INDEX_TYPE >::id, 1 );
506  node[ "__numberOfArrays__" ].set( numArraysType, const_cast< void * >( static_cast< void const * >(&numArrays) ) );
507 
508  // ArrayOfArrays::m_offsets
509  INDEX_TYPE const * const offsets = var.getOffsets();
510  conduit::DataType const offsetsType( conduitTypeInfo< INDEX_TYPE >::id, numArrays+1 );
511  node[ "__offsets__" ].set_external( offsetsType, const_cast< void * >( static_cast< void const * >( offsets ) ) );
512 
513  // ArrayOfArrays::m_sizes
514  INDEX_TYPE const * const sizes = var.getSizes();
515  conduit::DataType const sizesType( conduitTypeInfo< INDEX_TYPE >::id, numArrays );
516  node[ "__sizes__" ].set_external( sizesType, const_cast< void * >( static_cast< void const * >( sizes ) ) );
517 
518  // **** WARNING: alters the uninitialized values in the ArrayOfArrays ****
519  T * const values = const_cast< T * >(var.getValues());
520  for( INDEX_TYPE i = 0; i < numArrays; ++i )
521  {
522  INDEX_TYPE const curOffset = offsets[ i ];
523  INDEX_TYPE const nextOffset = offsets[ i + 1 ];
524  for( INDEX_TYPE j = curOffset + var.sizeOfArray( i ); j < nextOffset; ++j )
525  {
526  if constexpr ( std::is_arithmetic< T >::value )
527  {
528  values[ j ] = 0;
529  }
530  else
531  {
532  values[ j ] = T();
533  }
534  }
535  }
536 
537  constexpr int conduitTypeID = conduitTypeInfo< T >::id;
538  constexpr int sizeofConduitType = conduitTypeInfo< T >::sizeOfConduitType;
539  conduit::DataType const dtype( conduitTypeID, offsets[numArrays] * sizeof( T ) / sizeofConduitType );
540 
541  // Push the data into conduit
542  node[ "__values__" ].set_external( dtype, values );
543 }
544 
545 template< typename T, typename INDEX_TYPE >
546 std::enable_if_t< bufferOps::can_memcpy< T > >
547 pullDataFromConduitNode( ArrayOfArrays< T, INDEX_TYPE > & var,
548  conduit::Node const & node )
549 {
550 
551  // numArrays node
552  conduit::Node const & numArraysNode = node.fetch_existing( "__numberOfArrays__" );
553  INDEX_TYPE const * const numArrays = numArraysNode.value();
554 
555  // offsets node
556  conduit::Node const & offsetsNode = node.fetch_existing( "__offsets__" );
557  conduit::DataType const & offsetsDataType = offsetsNode.dtype();
558  INDEX_TYPE const * const offsets = offsetsNode.value();
559  INDEX_TYPE const sizeOffsets = offsetsDataType.number_of_elements();
560 
561  // sizes node
562  conduit::Node const & sizesNode = node.fetch_existing( "__sizes__" );
563  conduit::DataType const & sizesDataType = sizesNode.dtype();
564  INDEX_TYPE const * const sizes = sizesNode.value();
565  INDEX_TYPE const sizeSizes = sizesDataType.number_of_elements();
566 
567  // Check that the numArrays, sizes and offsets are consistent.
568  GEOS_ERROR_IF_NE( *numArrays, sizeSizes );
569  GEOS_ERROR_IF_NE( *numArrays+1, sizeOffsets );
570 
571  // values node
572  conduit::Node const & valuesNode = node.fetch_existing( "__values__" );
573  conduit::DataType const & valuesDataType = valuesNode.dtype();
574  const INDEX_TYPE valuesSize = valuesDataType.number_of_elements();
575 
576  // should preallocate var.m_values with estimated sizes
577  INDEX_TYPE const arraySizeEstimate = (*numArrays)==0 ? 0 : valuesSize / (*numArrays);
578  var.resize( *numArrays, arraySizeEstimate );
579  var.reserveValues( valuesSize );
580 
581  // correctly set the sizes and capacities of each sub-array
582  localIndex allocatedSize = 0;
583  for( INDEX_TYPE i = 0; i < *numArrays; ++i )
584  {
585  INDEX_TYPE const arrayAllocation = offsets[i+1] - offsets[i];
586  var.setCapacityOfArray( i, arrayAllocation );
587  var.resizeArray( i, sizes[ i ] );
588  allocatedSize += arrayAllocation;
589  }
590 
591  // make sure that the allocated size is the same as the number of values read
592  GEOS_ERROR_IF_NE( valuesSize, allocatedSize );
593 
594  // make sure the allocatedSize is consistent wit the last offset
595  GEOS_ERROR_IF_NE( allocatedSize, offsets[sizeOffsets-1] );
596 
597  // get a view because the ArrayOfArraysView data accessors are protected
598  ArrayOfArraysView< T const, INDEX_TYPE > const & varView = var.toViewConst();
599  INDEX_TYPE const * const varOffsets = varView.getOffsets();
600  INDEX_TYPE const * const varSizes = varView.getSizes();
601 
602  // check that the offsets that are read are the same as the ones that were allocated
603  GEOS_ERROR_IF_NE( varOffsets[0], offsets[0] );
604 
605  // check each subarray has the identical capacity and size
606  for( INDEX_TYPE i = 0; i<*numArrays; ++i )
607  {
608  GEOS_ERROR_IF_NE( varOffsets[i+1], offsets[i+1] );
609  GEOS_ERROR_IF_NE( varSizes[i], sizes[i] );
610  }
611 
612  // copy the values
613  localIndex numBytesFromArray = allocatedSize * sizeof( T );
614  GEOS_ERROR_IF_NE( numBytesFromArray, valuesDataType.strided_bytes() );
615  std::memcpy( const_cast< T * >(varView.getValues()), valuesNode.data_ptr(), numBytesFromArray );
616 }
617 
618 
619 
620 template< typename T >
621 void pushDataToConduitNode( InterObjectRelation< T > const & var,
622  conduit::Node & node )
623 {return pushDataToConduitNode( var.base(), node ); }
624 
625 template< typename T >
626 void pullDataFromConduitNode( InterObjectRelation< T > & var,
627  conduit::Node const & node )
628 { return pullDataFromConduitNode( var.base(), node ); }
629 
630 
632 template< typename T, int NDIM, int USD >
633 std::enable_if_t< std::is_arithmetic< T >::value || traits::is_tensorT< T > >
634 addBlueprintField( ArrayView< T const, NDIM, USD > const & var,
635  conduit::Node & fields,
636  string const & fieldName,
637  string const & topology,
638  std::vector< string > const & componentNames )
639 {
640  GEOS_ERROR_IF_LE( var.size(), 0 );
641 
642  using ConduitType = typename conduitTypeInfo< T >::type;
643  constexpr int conduitTypeID = conduitTypeInfo< T >::id;
644  constexpr int numComponentsPerValue = conduitTypeInfo< T >::numConduitValues;
645 
646  localIndex const totalNumberOfComponents = numComponentsPerValue * var.size() / var.size( 0 );
647  if( !componentNames.empty() )
648  {
649  GEOS_ERROR_IF_NE( localIndex( componentNames.size() ), totalNumberOfComponents );
650  }
651 
652  var.move( hostMemorySpace, false );
653 
654  conduit::DataType dtype( conduitTypeID, var.size( 0 ) );
655  dtype.set_stride( sizeof( ConduitType ) * numComponentsPerValue * var.strides()[ 0 ] );
656 
657  localIndex curComponent = 0;
658  LvArray::forValuesInSliceWithIndices( var[ 0 ], [&fields, &fieldName, &topology, &componentNames, totalNumberOfComponents, &dtype, &curComponent]
659  ( T const & val, auto const ... indices )
660  {
661  for( int i = 0; i < numComponentsPerValue; ++i )
662  {
663  string name;
664  if( totalNumberOfComponents == 1 )
665  {
666  name = fieldName;
667  }
668  else if( componentNames.empty() )
669  {
670  string indexString = internal::getIndicesToComponent( val, i, indices ... );
671  indexString.erase( indexString.begin() );
672  indexString.pop_back();
673  indexString.pop_back();
674  name = fieldName + indexString;
675  }
676  else
677  {
678  name = componentNames[ curComponent++ ];
679  }
680 
681  conduit::Node & field = fields[ name ];
682  field[ "association" ] = "element";
683  field[ "volume_dependent" ] = "false";
684  field[ "topology" ] = topology;
685 
686  void const * pointer = internal::getPointerToComponent( val, i );
687  field[ "values" ].set_external( dtype, const_cast< void * >( pointer ) );
688  }
689  } );
690 }
691 
692 template< typename T >
693 void addBlueprintField( T const &,
694  conduit::Node & fields,
695  string const &,
696  string const &,
697  std::vector< string > const & )
698 {
699  GEOS_ERROR( "Cannot create a mcarray out of " << LvArray::system::demangleType< T >() <<
700  "\nWas trying to write it to " << fields.path() );
701  GEOS_UNUSED_VAR( fields );
702 }
703 
704 template< typename T, int NDIM, int USD >
705 std::enable_if_t< std::is_arithmetic< T >::value || traits::is_tensorT< T > >
706 populateMCArray( ArrayView< T const, NDIM, USD > const & var,
707  conduit::Node & node,
708  std::vector< string > const & componentNames )
709 {
710  GEOS_ERROR_IF_LE( var.size(), 0 );
711 
712  using ConduitType = typename conduitTypeInfo< T >::type;
713  constexpr int conduitTypeID = conduitTypeInfo< T >::id;
714  constexpr int numComponentsPerValue = conduitTypeInfo< T >::numConduitValues;
715 
716  if( !componentNames.empty() )
717  {
718  GEOS_ERROR_IF_NE( localIndex( componentNames.size() ), numComponentsPerValue * var.size() / var.size( 0 ) );
719  }
720 
721  var.move( hostMemorySpace, false );
722 
723  conduit::DataType dtype( conduitTypeID, var.size( 0 ) );
724  dtype.set_stride( sizeof( ConduitType ) * numComponentsPerValue * var.strides()[ 0 ] );
725 
726  localIndex curComponent = 0;
727  LvArray::forValuesInSliceWithIndices( var[ 0 ], [&componentNames, &node, &dtype, &curComponent]
728  ( T const & val, auto const ... indices )
729  {
730  for( int i = 0; i < numComponentsPerValue; ++i )
731  {
732  string const name = componentNames.empty() ? internal::getIndicesToComponent( val, i, indices ... ) :
733  componentNames[ curComponent++ ];
734 
735  void const * pointer = internal::getPointerToComponent( val, i );
736  node[ name ].set_external( dtype, const_cast< void * >( pointer ) );
737  }
738  } );
739 }
740 
741 template< typename T >
742 void populateMCArray( T const &,
743  conduit::Node & node,
744  std::vector< string > const & )
745 {
746  GEOS_ERROR( "Cannot create a mcarray out of " << LvArray::system::demangleType< T >() <<
747  "\nWas trying to write it to " << node.path() );
748  GEOS_UNUSED_VAR( node );
749 }
750 
751 template< typename T >
752 std::enable_if_t< std::is_arithmetic< T >::value, std::unique_ptr< Array< T, 1 > > >
753 averageOverSecondDim( ArrayView< T const, 1, 0 > const & var )
754 {
755  std::unique_ptr< Array< T, 1 > > ret = std::make_unique< Array< T, 1 > >();
756 
757  ret->resize( var.size() );
758  ret->template setValues< serialPolicy >( var );
759 
760  return ret;
761 }
762 
763 template< typename T, int NDIM, int USD >
764 std::enable_if_t< std::is_arithmetic< T >::value, std::unique_ptr< Array< T, NDIM - 1 > > >
765 averageOverSecondDim( ArrayView< T const, NDIM, USD > const & var )
766 {
767  std::unique_ptr< Array< T, NDIM - 1 > > ret = std::make_unique< Array< T, NDIM - 1 > >();
768 
769  localIndex newDims[ NDIM - 1 ];
770  newDims[ 0 ] = var.size( 0 );
771  for( int i = 2; i < NDIM; ++i )
772  {
773  newDims[ i - 1 ] = var.size( i );
774  }
775 
776  ret->resize( NDIM - 1, newDims );
777 
778  ArrayView< T, NDIM - 1 > const & output = *ret;
779 
780  localIndex const numSamples = var.size( 1 );
781  forAll< serialPolicy >( var.size( 0 ), [var, numSamples, &output] ( localIndex const i )
782  {
783  LvArray::sumOverFirstDimension( var[ i ], output[ i ] );
784 
785  LvArray::forValuesInSlice( output[ i ], [numSamples] ( T & val )
786  {
787  val /= numSamples;
788  } );
789  } );
790 
791  return ret;
792 }
793 
794 template< typename T >
795 std::unique_ptr< int > averageOverSecondDim( T const & )
796 {
797  GEOS_ERROR( "Cannot average over the second dimension of " << LvArray::system::demangleType< T >() );
798  return std::unique_ptr< int >( nullptr );
799 }
800 
801 template< typename T, int NDIM, int USD >
802 int numArrayDims( ArrayView< T const, NDIM, USD > const & GEOS_UNUSED_PARAM( var ) )
803 {
804  return NDIM;
805 }
806 
807 template< typename T >
808 int numArrayDims( T const & GEOS_UNUSED_PARAM( var ) )
809 {
810  return 0;
811 }
812 
813 template< typename T, int NDIM, int USD >
814 localIndex numArrayComp( ArrayView< T const, NDIM, USD > const & var )
815 {
816  return LvArray::indexing::multiplyAll< NDIM - 1 >( var.dims() + 1 );
817 }
818 
819 template< typename T >
820 localIndex numArrayComp( ArrayView< T const, 1, 0 > const & GEOS_UNUSED_PARAM( var ) )
821 {
822  return 1;
823 }
824 
825 template< typename T >
826 localIndex numArrayComp( T const & GEOS_UNUSED_PARAM( var ) )
827 {
828  return 0;
829 }
830 
831 template< bool DO_PACKING, typename T, typename IDX >
832 inline std::enable_if_t< bufferOps::is_packable_by_index< T >, localIndex >
833 PackByIndex( buffer_unit_type * & buffer, T & var, IDX & idx )
834 { return bufferOps::PackByIndex< DO_PACKING >( buffer, var, idx ); }
835 
836 template< bool DO_PACKING, typename T, typename IDX >
837 inline std::enable_if_t< !bufferOps::is_packable_by_index< T >, localIndex >
838 PackByIndex( buffer_unit_type * &, T &, IDX & )
839 {
840  GEOS_ERROR( "Trying to pack data type (" << LvArray::system::demangleType< T >() << ") by index. Operation not supported." );
841  return 0;
842 }
843 
844 template< typename T, typename IDX >
845 inline std::enable_if_t< bufferOps::is_packable_by_index< T >, localIndex >
846 UnpackByIndex( buffer_unit_type const * & buffer, T & var, IDX & idx )
847 { return bufferOps::UnpackByIndex( buffer, var, idx ); }
848 
849 template< typename T, typename IDX >
850 inline std::enable_if_t< !bufferOps::is_packable_by_index< T >, localIndex >
851 UnpackByIndex( buffer_unit_type const * &, T &, IDX & )
852 {
853  GEOS_ERROR( "Trying to unpack data type (" << LvArray::system::demangleType< T >() << ") by index. Operation not supported." );
854  return 0;
855 }
856 
857 
858 template< bool DO_PACKING, typename T >
859 inline std::enable_if_t< bufferOps::is_container< T > || bufferOps::can_memcpy< T >, localIndex >
860 PackDevice( buffer_unit_type * & buffer, T const & var, parallelDeviceEvents & events )
861 { return bufferOps::PackDevice< DO_PACKING >( buffer, var, events ); }
862 
863 
864 template< bool DO_PACKING, typename T >
865 inline std::enable_if_t< !bufferOps::is_container< T > && !bufferOps::can_memcpy< T >, localIndex >
866 PackDevice( buffer_unit_type * &, T const &, parallelDeviceEvents & )
867 {
868  GEOS_ERROR( "Trying to pack data type (" << LvArray::system::demangleType< T >() << ") on device. Operation not supported." );
869  return 0;
870 }
871 
872 template< bool DO_PACKING, typename T, typename IDX >
873 inline std::enable_if_t< bufferOps::is_container< T >, localIndex >
874 PackByIndexDevice( buffer_unit_type * & buffer, T const & var, IDX & idx, parallelDeviceEvents & events )
875 { return bufferOps::PackByIndexDevice< DO_PACKING >( buffer, var, idx, events ); }
876 
877 template< bool DO_PACKING, typename T, typename IDX >
878 inline std::enable_if_t< !bufferOps::is_container< T >, localIndex >
879 PackByIndexDevice( buffer_unit_type * &, T const &, IDX &, parallelDeviceEvents & )
880 {
881  GEOS_ERROR( "Trying to pack data type (" << LvArray::system::demangleType< T >() << ") by index on device. Operation not supported." );
882  return 0;
883 }
884 
885 template< typename T >
886 inline std::enable_if_t< bufferOps::is_container< T >, localIndex >
887 UnpackDevice( buffer_unit_type const * & buffer, T const & var, parallelDeviceEvents & events )
888 { return bufferOps::UnpackDevice( buffer, var, events ); }
889 
890 template< typename T >
891 inline std::enable_if_t< !bufferOps::is_container< T >, localIndex >
892 UnpackDevice( buffer_unit_type const * &, T const &, parallelDeviceEvents & )
893 {
894  GEOS_ERROR( "Trying to unpack data type (" << LvArray::system::demangleType< T >() << ") on device. Operation not supported." );
895  return 0;
896 }
897 
898 template< typename T, typename IDX >
899 inline std::enable_if_t< bufferOps::is_container< T >, localIndex >
900 UnpackByIndexDevice( buffer_unit_type const * & buffer, T const & var, IDX & idx, parallelDeviceEvents & events, MPI_Op op=MPI_REPLACE )
901 { return bufferOps::UnpackByIndexDevice( buffer, var, idx, events, op ); }
902 
903 template< typename T, typename IDX >
904 inline std::enable_if_t< !bufferOps::is_container< T >, localIndex >
905 UnpackByIndexDevice( buffer_unit_type const * &, T &, IDX &, parallelDeviceEvents &, MPI_Op )
906 {
907  GEOS_ERROR( "Trying to unpack data type (" << LvArray::system::demangleType< T >() << ") by index on device. Operation not supported." );
908  return 0;
909 }
910 
911 
912 template< bool DO_PACKING, typename T >
914 PackDataDevice( buffer_unit_type * & buffer, T const & var, parallelDeviceEvents & events )
915 { return bufferOps::PackDataDevice< DO_PACKING >( buffer, var, events ); }
916 
917 template< bool DO_PACKING, typename T, typename IDX >
918 inline std::enable_if_t< bufferOps::is_container< T >, localIndex >
919 PackDataByIndexDevice( buffer_unit_type * & buffer, T const & var, IDX & idx, parallelDeviceEvents & events )
920 { return bufferOps::PackDataByIndexDevice< DO_PACKING >( buffer, var, idx, events ); }
921 
922 template< bool DO_PACKING, typename T, typename IDX >
923 inline std::enable_if_t< !bufferOps::is_container< T >, localIndex >
924 PackDataByIndexDevice( buffer_unit_type * &, T const &, IDX &, parallelDeviceEvents & )
925 {
926  GEOS_ERROR( "Trying to pack data type (" << LvArray::system::demangleType< T >() << ") by index on device. Operation not supported." );
927  return 0;
928 }
929 
930 template< typename T >
931 inline std::enable_if_t< bufferOps::is_container< T >, localIndex >
932 UnpackDataDevice( buffer_unit_type const * & buffer, T const & var, parallelDeviceEvents & events )
933 { return bufferOps::UnpackDataDevice( buffer, var, events ); }
934 
935 template< typename T >
936 inline std::enable_if_t< !bufferOps::is_container< T >, localIndex >
937 UnpackDataDevice( buffer_unit_type const * &, T const &, parallelDeviceEvents & )
938 {
939  GEOS_ERROR( "Trying to unpack data type (" << LvArray::system::demangleType< T >() << ") on device. Operation not supported." );
940  return 0;
941 }
942 
943 template< typename T, typename IDX >
944 inline std::enable_if_t< bufferOps::is_container< T >, localIndex >
945 UnpackDataByIndexDevice( buffer_unit_type const * & buffer, T const & var, IDX & idx, parallelDeviceEvents & events, MPI_Op op )
946 { return bufferOps::UnpackDataByIndexDevice( buffer, var, idx, events, op ); }
947 
948 template< typename T, typename IDX >
949 inline std::enable_if_t< !bufferOps::is_container< T >, localIndex >
950 UnpackDataByIndexDevice( buffer_unit_type const * &, T const &, IDX &, parallelDeviceEvents &, MPI_Op )
951 {
952  GEOS_ERROR( "Trying to unpack data type (" << LvArray::system::demangleType< T >() << ") by index on device. Operation not supported." );
953  return 0;
954 }
955 
956 #if defined(GEOS_USE_PYGEOSX)
957 
958 template< typename T >
959 inline std::enable_if_t< LvArray::python::CanCreate< T >, PyObject * >
960 createPythonObject( T & object )
961 { return LvArray::python::create( object ); }
962 
963 template< typename T >
964 inline std::enable_if_t< !LvArray::python::CanCreate< T >, PyObject * >
965 createPythonObject( T & )
966 { return nullptr; }
967 
968 #endif
969 
970 } // namespace wrapperHelpers
971 } // namespace dataRepository
972 } // namespace geos
973 
974 #undef RESTART_TYPE_LOGGING
975 
976 #endif // GEOS_DATAREPOSITORY_WRAPPERHELPERS_HPP_
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:84
#define GEOS_DEBUG_VAR(...)
Mark a debug variable and silence compiler warnings.
Definition: GeosxMacros.hpp:87
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
Definition: GeosxMacros.hpp:72
#define GEOS_ERROR_IF_LE(lhs, rhs)
Raise a hard error if one value compares less than or equal to the other.
Definition: Logger.hpp:387
#define GEOS_ERROR_IF_LT(lhs, rhs)
Raise a hard error if one value compares less than the other.
Definition: Logger.hpp:355
#define GEOS_ERROR_IF_GE(lhs, rhs)
Raise a hard error if one value compares greater than or equal to the other.
Definition: Logger.hpp:323
#define GEOS_LOG(...)
Log a message on screen.
Definition: Logger.hpp:40
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
Definition: Logger.hpp:157
#define GEOS_ERROR_IF_NE(lhs, rhs)
Raise a hard error if two values are not equal.
Definition: Logger.hpp:259
#define GEOS_ERROR_IF_NE_MSG(lhs, rhs, msg)
Raise a hard error if two values are not equal.
Definition: Logger.hpp:243
internal::Helper< T > DefaultValue
A templated alias to hold default values.
LvArray::Array< T, NDIM, PERMUTATION, localIndex, LvArray::ChaiBuffer > Array
Multidimensional array type. See LvArray:Array for details.
Definition: DataTypes.hpp:142
array1d< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:392
std::set< T > set
A set of local indices.
Definition: DataTypes.hpp:263
double real64
64-bit floating point type.
Definition: DataTypes.hpp:99
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:85
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82
Tensor< real64, 3 > R1Tensor
Alias for a local (stack-based) rank-1 tensor type.
Definition: DataTypes.hpp:166
signed char buffer_unit_type
Type stored in communication buffers.
Definition: DataTypes.hpp:109
LvArray::ArrayView< T, NDIM, USD, localIndex, LvArray::ChaiBuffer > ArrayView
Multidimensional array view type. See LvArray:ArrayView for details.
Definition: DataTypes.hpp:148