Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
GIDI_arrays.cc
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# Copyright 2019, Lawrence Livermore National Security, LLC.
4# This file is part of the gidiplus package (https://github.com/LLNL/gidiplus).
5# gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT).
6# SPDX-License-Identifier: MIT
7# <<END-copyright>>
8*/
9
10#include <stdlib.h>
11#include <algorithm>
12
13#include "GIDI.hpp"
14#include <HAPI.hpp>
15
16namespace GIDI {
17
18namespace Array {
19
20/* *********************************************************************************************************//**
21 * Helper function to parse the *shape* attribute for an Array instance.
22 *
23 * @param a_node [in] The **HAPI::Node** to be parsed and used to construct the shape. This must be a reference to the array node.
24 *
25 * @return Returns a *std::vector<int>* of the shape.
26 ***********************************************************************************************************/
27
28static std::vector<std::size_t> parseArrayShape( HAPI::Node const &a_node ) {
29
30 std::string shape = a_node.attribute_as_string( GIDI_shapeChars );
31 std::vector<std::size_t> shapeInts;
32
33 auto shapeItems = LUPI::Misc::splitString( shape, ',', true );
34 for( auto iter = shapeItems.begin( ); iter != shapeItems.end( ); ++iter ) {
35 shapeInts.push_back( static_cast<std::size_t>( atoi( (*iter).c_str( ) ) ) );
36 }
37
38 return( shapeInts );
39}
40
41/*! \class FullArray
42 * The class for storing any **GNDS** array as a flattened full array. It is the array returned by the
43 * Array.constructArray method. Note, this class is never used to store a **GNDS** array node, but to
44 * provide a convenient way to access data in any of the ways an array can be stored compactly in **GNDS**.
45 */
46
47/* *********************************************************************************************************//**
48 * Constructs a FullArray using the arguments *a_shape*. The values for *m_flattenedValues* are set to 0.0.
49 *
50 * @param a_shape [in] The shape of the full array.
51 ***********************************************************************************************************/
52
53FullArray::FullArray( std::vector<std::size_t> const &a_shape ) :
54 m_shape( a_shape ) {
55
56 std::size_t size = 1;
57 for( auto iter = a_shape.begin( ); iter != a_shape.end( ); ++iter ) size *= *iter;
58 m_flattenedValues.resize( size, 0.0 );
59}
60
61/* *********************************************************************************************************//**
62 * Constructs a FullArray using the arguments *a_shape* and *a_flattenedValues*.
63 *
64 * @param a_shape [in] The shape of the full array.
65 * @param a_flattenedValues [in] The values of the array. Its size must be the same has that specified by *a_shape*.
66 ***********************************************************************************************************/
67
68FullArray::FullArray( std::vector<std::size_t> const &a_shape, std::vector<double> const &a_flattenedValues ) :
69 m_shape( a_shape ) {
70
71 std::size_t size = 1;
72 for( auto iter = a_shape.begin( ); iter != a_shape.end( ); ++iter ) size *= *iter;
73
74 if( size != static_cast<std::size_t>( a_flattenedValues.size( ) ) ) throw Exception( "FullArray::FullArray: a_shape and a_flattenedValues are not the same size." );
75
76 m_flattenedValues.resize( size );
77 for( std::size_t index = 0; index < size; ++index ) m_flattenedValues[index] = a_flattenedValues[index];
78}
79
80/*! \class Array
81 * The class for storing any **GNDS** array.
82 */
83
84/* *********************************************************************************************************//**
85 * @param a_node [in] The **HAPI::Node** to be parsed and used to construct the Array2d.
86 * @param a_setupInfo [in] Information create my the Protare constructor to help in parsing.
87 * @param a_useSystem_strtod [in] Flag passed to the function nfu_stringToListOfDoubles.
88 ***********************************************************************************************************/
89
90Array::Array( HAPI::Node const &a_node, SetupInfo &a_setupInfo, int a_useSystem_strtod ) :
91 Form( a_node, a_setupInfo, FormType::array ),
92 m_shape( parseArrayShape( a_node ) ),
93 m_compression( a_node.attribute_as_string( GIDI_compressionChars ) ),
94 m_symmetry( a_node.attribute_as_string( GIDI_symmetryChars ) ),
95 m_permutation( a_node.attribute_as_string( GIDI_permutationChars ) ),
96 m_storageOrder( a_node.attribute_as_string( GIDI_storageOrderChars ) ) {
97
98 if( m_compression == "" ) m_compression = GIDI_noneChars;
99
100 if( ( m_compression == GIDI_noneChars ) || ( m_compression == GIDI_diagonalChars ) || ( m_compression == GIDI_flattenedChars ) ) {
101 for( HAPI::Node child = a_node.first_child( ); !child.empty( ); child.to_next_sibling( ) ) {
102 std::string name( child.name( ) );
103 if( name != GIDI_valuesChars ) throw Exception( "For '" + moniker( ) + "' array, child node not 'values' but '" + name + "'." );
104
105 std::string label1( child.attribute_as_string( GIDI_labelChars ) );
106 if( label1 == "" ) {
107 parseValuesOfDoubles( child, a_setupInfo, m_values, a_useSystem_strtod ); }
108 else if( label1 == GIDI_startingIndices ) {
109 if( m_compression != GIDI_diagonalChars ) throw Exception( "Invalid values' label '" + label1 + "'." );
110 parseValuesOfInts( child, a_setupInfo, m_starts ); }
111 else if( label1 == GIDI_startsChars ) {
112 if( m_compression != GIDI_flattenedChars ) throw Exception( "Invalid values' label " + label1 + "." );
113 parseValuesOfInts( child, a_setupInfo, m_starts ); }
114 else if( label1 == GIDI_lengthsChars ) {
115 if( m_compression != GIDI_flattenedChars ) throw Exception( "Invalid values' label '" + label1 + "'." );
116 parseValuesOfInts( child, a_setupInfo, m_length ); }
117 else {
118 throw Exception( "Invalid values' label '" + label1 + "'." );
119 }
120 } }
121 else { // m_compression == GIDI_embeddedChars
122 for( HAPI::Node child = a_node.first_child( ); !child.empty( ); child.to_next_sibling( ) ) {
123 std::string name( child.name( ) );
124 if( name != GIDI_arrayChars ) throw Exception( "For 'embedded' array, child node not 'array' but '" + name + "'." );
125
126 m_array.push_back( new Array( child, a_setupInfo, a_useSystem_strtod ) );
127 }
128 }
129}
130
131/* *********************************************************************************************************//**
132 ***********************************************************************************************************/
133
135
136 for( auto iter = m_array.begin( ); iter != m_array.end( ); ++iter ) delete *iter;
137}
138
139/* *********************************************************************************************************//**
140 * Calculates the size of *this* which is the product of all the *m_shape* values.
141 *
142 * @return The product of the *m_shape* values.
143 ***********************************************************************************************************/
144
145std::size_t Array::size( ) const {
146
147 std::size_t size1 = 1;
148 for( auto iter = m_shape.begin( ); iter != m_shape.end( ); ++iter ) size1 *= *iter;
149
150 return( size1 );
151}
152
153/* *********************************************************************************************************//**
154 * Returns an array that is a FullArray instance of *this*. Note, this does not currently handle symmetry, permutation
155 * or storageOrder.
156 *
157 * @return Return a FullArray of *this*.
158 ***********************************************************************************************************/
159
161
162 std::vector<double> values( size( ) );
163
164 if( m_compression == GIDI_noneChars ) {
165 values = m_values.vector( ); }
166 else if( m_compression == GIDI_diagonalChars ) {
167 throw Exception( "Array::constructArray: compression '" + m_compression + "' not supported." ); }
168 else if( m_compression == GIDI_flattenedChars ) {
169 std::size_t index = 0;
170 for( std::size_t index1 = 0; index1 < m_starts.size( ); ++index1 ) {
171 std::size_t length = static_cast<std::size_t>( m_length[index1] );
172 std::size_t start = static_cast<std::size_t>( m_starts[index1] );
173
174 for( std::size_t index2 = 0; index2 < length; ++index2, ++index ) values[start+index2] = m_values[index];
175 } }
176 else {
177 throw Exception( "Array::constructArray: compression '" + m_compression + "' not supported." );
178 }
179
180 FullArray fullArray( m_shape, values );
181 return( fullArray );
182}
183
184/* *********************************************************************************************************//**
185 * Fills the argument *a_writeInfo* with the XML lines that represent *this*. Recursively enters each sub-node.
186 * Currently does nothing.
187 *
188 * @param a_writeInfo [in/out] Instance containing incremental indentation and other information and stores the appended lines.
189 * @param a_indent [in] The amount to indent *this* node.
190 ***********************************************************************************************************/
191
192void Array::toXMLList( LUPI_maybeUnused GUPI::WriteInfo &a_writeInfo, LUPI_maybeUnused std::string const &a_indent ) const {
193
194}
195
196} // End namespace Array.
197
198/* *********************************************************************************************************//**
199 * Function to parse a one-d flattened array.
200 *
201 * @param a_construction [in] Used to pass user options for parsing.
202 * @param a_node [in] The **HAPI::Node** to be parsed.
203 * @param a_setupInfo [in] Information create my the Protare constructor to help in parsing.
204 * @param a_data [out] An empty GIDI::Vector that is filled with the data.
205 *
206 * @return 0 if successfull and 1 otherwise.
207 ***********************************************************************************************************/
208
209int parseFlattened1d( Construction::Settings const &a_construction, HAPI::Node const &a_node, SetupInfo &a_setupInfo, Vector &a_data ) {
210
211 FlattenedArrayData arrayData( a_node, a_setupInfo, 1, a_construction.useSystem_strtod( ) );
212
213 std::size_t size = (std::size_t) arrayData.m_shape[0];
214 a_data.resize( size );
215
216 std::size_t n1 = 0, n2 = size;
217 for( std::size_t i1 = 0; i1 < arrayData.m_numberOfStarts; ++i1 ) {
218 std::size_t offset = (std::size_t) arrayData.m_starts[i1];
219 for( int32_t i2 = 0; i2 < arrayData.m_lengths[i1]; ++i2, ++n1, ++offset ) {
220 if( n1 >= arrayData.m_dValues.size( ) ) throw Exception( "Too many values in flattened array." );
221 if( offset >= n2 ) throw Exception( "requested size is too small." );
222 a_data[offset] = arrayData.m_dValues[n1];
223 }
224 }
225 return( 0 );
226}
227
228/* *********************************************************************************************************//**
229 * Function to parse a flattened array of dimension **a_dimensions**.
230 *
231 * @param a_node [in] The **HAPI::Node** to be parsed.
232 * @param a_setupInfo [in] Information create my the Protare constructor to help in parsing.
233 * @param a_dimensions [in] The dimension of the flattened array to be parsed.
234 * @param a_useSystem_strtod [in] Flag passed to the function nfu_stringToListOfDoubles.
235 ***********************************************************************************************************/
236
237FlattenedArrayData::FlattenedArrayData( HAPI::Node const &a_node, SetupInfo &a_setupInfo, int a_dimensions, int a_useSystem_strtod ) :
238 Form( a_node, a_setupInfo, FormType::flattenedArrayData ),
239 m_numberOfStarts( 0 ),
241 m_starts( ),
242 m_lengths( ) {
243
244 bool m_dValuesPresent( false );
245
246 std::string shape( a_node.attribute_as_string( GIDI_shapeChars ) );
247 auto shapeItems = LUPI::Misc::splitString( shape, ',', true );
248 for( auto iter = shapeItems.begin( ); iter != shapeItems.end( ); ++iter ) {
249 m_shape.push_back( static_cast<std::size_t>( atoi( (*iter).c_str( ) ) ) );
250 }
251
252 if( a_dimensions != (int) m_shape.size( ) ) throw Exception( "a_dimensions != m_shape.size( )" );
253
254 for( HAPI::Node child = a_node.first_child( ); !child.empty( ); child.to_next_sibling( ) ) {
255 std::string name( child.name( ) );
256
257 if( name == GIDI_valuesChars ) {
258 std::string label( child.attribute_as_string( GIDI_labelChars ) );
259 if( label == GIDI_startsChars ) {
260 parseValuesOfInts( child, a_setupInfo, m_starts );
261 m_numberOfStarts = (std::size_t) m_starts.size(); }
262 else if( label == GIDI_lengthsChars ) {
263 parseValuesOfInts( child, a_setupInfo, m_lengths );
264 m_numberOfLengths = (std::size_t) m_lengths.size(); }
265 else if( label == "" ) {
266 m_dValuesPresent = true;
267 parseValuesOfDoubles( child, a_setupInfo, m_dValues, a_useSystem_strtod ); }
268 else {
269 throw Exception( "unknown label for flatteded array sub-element" );
270 } }
271 else {
272 throw Exception( "unknown flattened array sub-element" );
273 }
274 }
275 if( m_starts.data() == nullptr ) throw Exception( "array missing starts element" );
276 if( m_lengths.data() == nullptr ) throw Exception( "array missing lengths element" );
277 if( !m_dValuesPresent ) throw Exception( "array missing dValues element" );
278 if( m_numberOfStarts != m_numberOfLengths ) throw Exception( "m_numberOfStarts != m_numberOfLengths for array" );
279}
280
281/* *********************************************************************************************************//**
282 ***********************************************************************************************************/
283
285
286// smr_freeMemory2( m_starts );
287// smr_freeMemory2( m_lengths );
288}
289
290/* *********************************************************************************************************//**
291 * Sets all elements in the range [*a_start*,*a_end*) to *a_value*.
292 *
293 * @param a_start [in] The starting flat-cell index of *this* to fill with *a_value*.
294 * @param a_end [in] One after the last flat-cell index of *this* to fill with *a_value*.
295 * @param a_value [in] The value to set each double in the range to.
296 ***********************************************************************************************************/
297
298void FlattenedArrayData::setToValueInFlatRange( LUPI_maybeUnused std::size_t a_start, std::size_t a_end, LUPI_maybeUnused double a_value ) {
299
300 std::size_t size = 1;
301 for( auto iter = m_shape.begin( ); iter != m_shape.end( ); ++iter ) size *= *iter;
302 a_end = std::min( a_end, size );
303
304 long numberOfValuesToSet = 0;
305 for( std::size_t startIndex = 0; startIndex < m_numberOfStarts; ++startIndex ) {
306 std::size_t start = static_cast<std::size_t>( m_starts[startIndex] );
307 std::size_t length = static_cast<std::size_t>( m_lengths[startIndex] );
308
309 if( ( start + length ) > a_end ) {
310 if( a_end < start ) break;
311 length = a_end - start;
312 }
313 numberOfValuesToSet += length;
314 }
315
316 for( long index = 0; index < numberOfValuesToSet; ++index ) m_dValues[index] = 0.0;
317}
318
319/* *********************************************************************************************************//**
320 * Fills the argument *a_writeInfo* with the XML lines that represent *this*. Recursively enters each sub-node.
321 *
322 * @param a_writeInfo [in/out] Instance containing incremental indentation and other information and stores the appended lines.
323 * @param a_indent [in] The amount to indent *this* node.
324 ***********************************************************************************************************/
325
326void FlattenedArrayData::toXMLList( GUPI::WriteInfo &a_writeInfo, std::string const &a_indent ) const {
327
328 std::string indent2 = a_writeInfo.incrementalIndent( a_indent );
329 std::vector<int> ints;
330
331 std::string shapeString;
332 std::string sep = "";
333 for( std::size_t i1 = 0; i1 < m_shape.size( ); ++i1 ) {
334 shapeString += sep + intToString( static_cast<int>( m_shape[i1] ) );
335 sep = ",";
336 }
337
338 std::string attributes = a_writeInfo.addAttribute( GIDI_shapeChars, shapeString ) + a_writeInfo.addAttribute( "compression", "flattened" );
339
340 a_writeInfo.addNodeStarter( a_indent, moniker( ), attributes );
341
342 for( std::size_t i1 = 0; i1 < m_numberOfStarts; ++i1 ) ints.push_back( m_starts[i1] );
343 intsToXMLList( a_writeInfo, indent2, ints, " valueType=\"Integer32\" label=\"starts\"" );
344
345 ints.clear( );
346 for( std::size_t i1 = 0; i1 < m_numberOfLengths; ++i1 ) ints.push_back( m_lengths[i1] );
347 intsToXMLList( a_writeInfo, indent2, ints, " valueType=\"Integer32\" label=\"lengths\"" );
348
349 doublesToXMLList( a_writeInfo, indent2, m_dValues.vector() );
350 a_writeInfo.addNodeEnder( moniker( ) );
351}
352
353} // End namespace GIDI.
G4ThreadLocal T * G4GeomSplitter< T >::offset
#define GIDI_startingIndices
Definition GIDI.hpp:265
#define GIDI_permutationChars
Definition GIDI.hpp:275
#define GIDI_valuesChars
Definition GIDI.hpp:260
#define GIDI_diagonalChars
Definition GIDI.hpp:264
#define GIDI_labelChars
Definition GIDI.hpp:438
#define GIDI_shapeChars
Definition GIDI.hpp:261
#define GIDI_startsChars
Definition GIDI.hpp:267
#define GIDI_arrayChars
Definition GIDI.hpp:258
#define GIDI_storageOrderChars
Definition GIDI.hpp:279
#define GIDI_symmetryChars
Definition GIDI.hpp:271
#define GIDI_flattenedChars
Definition GIDI.hpp:266
#define GIDI_noneChars
Definition GIDI.hpp:259
#define GIDI_compressionChars
Definition GIDI.hpp:263
#define GIDI_lengthsChars
Definition GIDI.hpp:268
#define LUPI_maybeUnused
std::size_t size() const
FullArray constructArray() const
void toXMLList(GUPI::WriteInfo &a_writeInfo, std::string const &a_indent) const
Array(HAPI::Node const &a_node, SetupInfo &a_setupInfo, int a_useSystem_strtod)
std::vector< std::size_t > m_shape
Definition GIDI.hpp:897
std::size_t size() const
Definition GIDI.hpp:900
FullArray(std::vector< std::size_t > const &a_shape)
std::vector< double > m_flattenedValues
Definition GIDI.hpp:898
int useSystem_strtod() const
Definition GIDI.hpp:579
std::vector< std::size_t > const & shape() const
Definition GIDI.hpp:955
void toXMLList(GUPI::WriteInfo &a_writeInfo, std::string const &a_indent) const
FlattenedArrayData(HAPI::Node const &a_node, SetupInfo &a_setupInfo, int a_dimensions, int a_useSystem_strtod)
nf_Buffer< int > m_starts
Definition GIDI.hpp:948
nf_Buffer< int > m_lengths
Definition GIDI.hpp:949
std::size_t m_numberOfStarts
Definition GIDI.hpp:946
std::size_t m_numberOfLengths
Definition GIDI.hpp:947
nf_Buffer< double > m_dValues
Definition GIDI.hpp:950
std::vector< std::size_t > m_shape
Definition GIDI.hpp:945
void setToValueInFlatRange(std::size_t a_start, std::size_t a_end, double a_value)
std::string const & label() const
Definition GIDI.hpp:658
Form(FormType a_type)
Definition GIDI_form.cc:25
void resize(std::size_t a_number, double a_value=0.0)
Definition GIDI_data.hpp:80
std::string const & moniker() const
Definition GUPI.hpp:102
void addNodeEnder(std::string const &a_moniker)
Definition GUPI.hpp:59
std::string incrementalIndent(std::string const &indent)
Definition GUPI.hpp:52
void addNodeStarter(std::string const &indent, std::string const &a_moniker, std::string const &a_attributes="")
Definition GUPI.hpp:55
std::string addAttribute(std::string const &a_name, std::string const &a_value) const
Definition GUPI.hpp:60
bool empty() const
Definition HAPI_Node.cc:150
std::string attribute_as_string(const char *a_name) const
Definition HAPI.hpp:179
Node first_child() const
Definition HAPI_Node.cc:82
Definition GIDI.hpp:32
void parseValuesOfDoubles(Construction::Settings const &a_construction, HAPI::Node const &a_node, SetupInfo &a_setupInfo, nf_Buffer< double > &a_vector)
Definition GIDI_misc.cc:88
FormType
Definition GIDI.hpp:118
@ flattenedArrayData
Definition GIDI.hpp:121
void doublesToXMLList(GUPI::WriteInfo &a_writeInfo, std::string const &a_indent, std::vector< double > const &a_values, std::size_t a_start=0, bool a_newLine=true, std::string const &a_valueType="")
Definition GIDI_misc.cc:180
void intsToXMLList(GUPI::WriteInfo &a_writeInfo, std::string const &a_indent, std::vector< int > const &a_values, std::string const &a_attributes)
Definition GIDI_misc.cc:63
void parseValuesOfInts(Construction::Settings const &a_construction, HAPI::Node const &a_node, SetupInfo &a_setupInfo, std::vector< int > &a_vector)
int parseFlattened1d(Construction::Settings const &a_construction, HAPI::Node const &a_node, SetupInfo &a_setupInfo, Vector &data)
std::string intToString(int a_value)
Definition GIDI_misc.cc:415
std::vector< std::string > splitString(std::string const &a_string, char a_delimiter, bool a_strip=false)
Definition LUPI_misc.cc:103