Skip to content

Commit

Permalink
fix: Restart files contain incorrect types for ArrayOfArrays (#3434)
Browse files Browse the repository at this point in the history
* add conduit write/read for ArrayOfArrays

* update baseline
  • Loading branch information
rrsettgast authored Nov 12, 2024
1 parent 3b0d907 commit 1c89619
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 87 deletions.
3 changes: 1 addition & 2 deletions .integrated_tests.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
baselines:
bucket: geosx
baseline: integratedTests/baseline_integratedTests-pr3374-8621-bbb3cb2

baseline: integratedTests/baseline_integratedTests-pr3434-8663-1be8ad2
allow_fail:
all: ''
streak: ''
4 changes: 4 additions & 0 deletions BASELINE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines.
Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining.
These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD).

PR #3434 (2024-11-09)
=====================
Bugfix: Fixed output of ArrayOfArray objects to restart files.

PR #3374 (2024-11-09)
====================
Bugfix for gravity treatment in flux for thermal.
Expand Down
127 changes: 127 additions & 0 deletions src/coreComponents/dataRepository/wrapperHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,133 @@ pullDataFromConduitNode( Array< T, NDIM, PERMUTATION > & var,
std::memcpy( var.data(), valuesNode.data_ptr(), numBytesFromArray );
}



template< typename T, typename INDEX_TYPE >
std::enable_if_t< bufferOps::can_memcpy< T > >
pushDataToConduitNode( ArrayOfArrays< T, INDEX_TYPE > const & var2,
conduit::Node & node )
{
ArrayOfArraysView< T const, INDEX_TYPE > const & var = var2.toViewConst();
internal::logOutputType( LvArray::system::demangleType( var ), "Output array via external pointer: " );

// ArrayOfArrays::m_numArrays
INDEX_TYPE const numArrays = var.size();
conduit::DataType const numArraysType( conduitTypeInfo< INDEX_TYPE >::id, 1 );
node[ "__numberOfArrays__" ].set( numArraysType, const_cast< void * >( static_cast< void const * >(&numArrays) ) );

// ArrayOfArrays::m_offsets
INDEX_TYPE const * const offsets = var.getOffsets();
conduit::DataType const offsetsType( conduitTypeInfo< INDEX_TYPE >::id, numArrays+1 );
node[ "__offsets__" ].set_external( offsetsType, const_cast< void * >( static_cast< void const * >( offsets ) ) );

// ArrayOfArrays::m_sizes
INDEX_TYPE const * const sizes = var.getSizes();
conduit::DataType const sizesType( conduitTypeInfo< INDEX_TYPE >::id, numArrays );
node[ "__sizes__" ].set_external( sizesType, const_cast< void * >( static_cast< void const * >( sizes ) ) );

// **** WARNING: alters the uninitialized values in the ArrayOfArrays ****
T * const values = const_cast< T * >(var.getValues());
for( INDEX_TYPE i = 0; i < numArrays; ++i )
{
INDEX_TYPE const curOffset = offsets[ i ];
INDEX_TYPE const nextOffset = offsets[ i + 1 ];
for( INDEX_TYPE j = curOffset + var.sizeOfArray( i ); j < nextOffset; ++j )
{
if constexpr ( std::is_arithmetic< T >::value )
{
values[ j ] = 0;
}
else
{
values[ j ] = T();
}
}
}

constexpr int conduitTypeID = conduitTypeInfo< T >::id;
constexpr int sizeofConduitType = conduitTypeInfo< T >::sizeOfConduitType;
conduit::DataType const dtype( conduitTypeID, offsets[numArrays] * sizeof( T ) / sizeofConduitType );

// Push the data into conduit
node[ "__values__" ].set_external( dtype, values );
}

template< typename T, typename INDEX_TYPE >
std::enable_if_t< bufferOps::can_memcpy< T > >
pullDataFromConduitNode( ArrayOfArrays< T, INDEX_TYPE > & var,
conduit::Node const & node )
{

// numArrays node
conduit::Node const & numArraysNode = node.fetch_existing( "__numberOfArrays__" );
INDEX_TYPE const * const numArrays = numArraysNode.value();

// offsets node
conduit::Node const & offsetsNode = node.fetch_existing( "__offsets__" );
conduit::DataType const & offsetsDataType = offsetsNode.dtype();
INDEX_TYPE const * const offsets = offsetsNode.value();
INDEX_TYPE const sizeOffsets = offsetsDataType.number_of_elements();

// sizes node
conduit::Node const & sizesNode = node.fetch_existing( "__sizes__" );
conduit::DataType const & sizesDataType = sizesNode.dtype();
INDEX_TYPE const * const sizes = sizesNode.value();
INDEX_TYPE const sizeSizes = sizesDataType.number_of_elements();

// Check that the numArrays, sizes and offsets are consistent.
GEOS_ERROR_IF_NE( *numArrays, sizeSizes );
GEOS_ERROR_IF_NE( *numArrays+1, sizeOffsets );

// values node
conduit::Node const & valuesNode = node.fetch_existing( "__values__" );
conduit::DataType const & valuesDataType = valuesNode.dtype();
const INDEX_TYPE valuesSize = valuesDataType.number_of_elements();

// should preallocate var.m_values with estimated sizes
INDEX_TYPE const arraySizeEstimate = (*numArrays)==0 ? 0 : valuesSize / (*numArrays);
var.resize( *numArrays, arraySizeEstimate );
var.reserveValues( valuesSize );

// correctly set the sizes and capacities of each sub-array
localIndex allocatedSize = 0;
for( INDEX_TYPE i = 0; i < *numArrays; ++i )
{
INDEX_TYPE const arrayAllocation = offsets[i+1] - offsets[i];
var.setCapacityOfArray( i, arrayAllocation );
var.resizeArray( i, sizes[ i ] );
allocatedSize += arrayAllocation;
}

// make sure that the allocated size is the same as the number of values read
GEOS_ERROR_IF_NE( valuesSize, allocatedSize );

// make sure the allocatedSize is consistent wit the last offset
GEOS_ERROR_IF_NE( allocatedSize, offsets[sizeOffsets-1] );

// get a view because the ArrayOfArraysView data accessors are protected
ArrayOfArraysView< T const, INDEX_TYPE > const & varView = var.toViewConst();
INDEX_TYPE const * const varOffsets = varView.getOffsets();
INDEX_TYPE const * const varSizes = varView.getSizes();

// check that the offsets that are read are the same as the ones that were allocated
GEOS_ERROR_IF_NE( varOffsets[0], offsets[0] );

// check each subarray has the identical capacity and size
for( INDEX_TYPE i = 0; i<*numArrays; ++i )
{
GEOS_ERROR_IF_NE( varOffsets[i+1], offsets[i+1] );
GEOS_ERROR_IF_NE( varSizes[i], sizes[i] );
}

// copy the values
localIndex numBytesFromArray = allocatedSize * sizeof( T );
GEOS_ERROR_IF_NE( numBytesFromArray, valuesDataType.strided_bytes() );
std::memcpy( const_cast< T * >(varView.getValues()), valuesNode.data_ptr(), numBytesFromArray );
}



template< typename T >
void pushDataToConduitNode( InterObjectRelation< T > const & var,
conduit::Node & node )
Expand Down
Loading

0 comments on commit 1c89619

Please sign in to comment.