6
6
#include < numeric>
7
7
8
8
#include < catch2/catch.hpp>
9
+ #include < optional>
9
10
10
11
#if openPMD_HAVE_ADIOS2 && openPMD_HAVE_MPI
11
12
#include < adios2.h>
@@ -120,24 +121,13 @@ static void create_file_in_serial(bool use_group_table)
120
121
" __openPMD_groups/data" , step, " " , " /" , true );
121
122
IO.DefineAttribute <size_t >(
122
123
" __openPMD_groups/data/meshes" , step, " " , " /" , true );
123
- IO.DefineAttribute <size_t >(
124
- " __openPMD_groups/data/meshes/theta" , step, " " , " /" , true );
125
124
}
126
125
127
126
std::vector<int > data{0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
128
127
engine.Put (variable, data.data ());
129
128
if (step % 2 == 1 )
130
129
{
131
130
engine.Put (variable2, data.data ());
132
- if (use_group_table)
133
- {
134
- IO.DefineAttribute <size_t >(
135
- " __openPMD_groups/data/meshes/e_chargeDensity" ,
136
- step,
137
- " " ,
138
- " /" ,
139
- true );
140
- }
141
131
}
142
132
143
133
engine.EndStep ();
@@ -147,13 +137,16 @@ static void create_file_in_serial(bool use_group_table)
147
137
}
148
138
}
149
139
150
- auto read_file_in_parallel (bool use_group_table) -> void
140
+ auto read_file_in_parallel (
141
+ std::optional<std::string> const &dont_verify_homogeneous_extents) -> void
151
142
{
152
143
openPMD::Series read (
153
144
" ../samples/read_variablebased_randomaccess.bp" ,
154
145
openPMD::Access::READ_ONLY,
155
146
MPI_COMM_WORLD,
156
- " adios2.engine.type = \" bp5\" " );
147
+ json::merge (
148
+ " adios2.engine.type = \" bp5\" " ,
149
+ dont_verify_homogeneous_extents.value_or (" {}" )));
157
150
for (auto &[index, iteration] : read.snapshots ())
158
151
{
159
152
auto data = iteration.meshes [" theta" ].loadChunk <int >({0 }, {10 });
@@ -163,42 +156,56 @@ auto read_file_in_parallel(bool use_group_table) -> void
163
156
REQUIRE (data.get ()[i] == int (i));
164
157
}
165
158
// clang-format off
166
- /*
167
- * Step 0:
168
- * uint64_t /data/snapshot attr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
169
- * Step 1:
170
- * int32_t /data/meshes/e_chargeDensity {10}
171
- * uint64_t /data/snapshot attr = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
172
- * Step 2:
173
- * uint64_t /data/snapshot attr = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}
174
- * Step 3:
175
- * int32_t /data/meshes/e_chargeDensity {10}
176
- * uint64_t /data/snapshot attr = {30, 31, 32, 33, 34, 35, 36, 37, 38, 39}
177
- * Step 4:
178
- * uint64_t /data/snapshot attr = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
179
- */
159
+ /*
160
+ * Step 0:
161
+ * uint64_t /data/snapshot attr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
162
+ * Step 1:
163
+ * int32_t /data/meshes/e_chargeDensity {10}
164
+ * uint64_t /data/snapshot attr = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
165
+ * Step 2:
166
+ * uint64_t /data/snapshot attr = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}
167
+ * Step 3:
168
+ * int32_t /data/meshes/e_chargeDensity {10}
169
+ * uint64_t /data/snapshot attr = {30, 31, 32, 33, 34, 35, 36, 37, 38, 39}
170
+ * Step 4:
171
+ * uint64_t /data/snapshot attr = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
172
+ */
180
173
// clang-format on
181
174
size_t adios_step = index / 10 ; // 10 iterations per step
182
175
bool step_has_charge_density = adios_step % 2 == 1 ;
183
- if (use_group_table)
176
+ // Without a group table, the groups need to be recovered from
177
+ // attributes and variables found in the ADIOS2 file. But since the
178
+ // e_chargeDensity mesh exists only in a subselection of steps, its
179
+ // attributes will leak into the other steps, making the API see just an
180
+ // empty mesh. The behavior now depends on how strictly we are parsing:
181
+ //
182
+ // 1. If verify_homogeneous_extent == true (default): The reader will
183
+ // notice that no extent is defined anywhere, the mesh will be erased
184
+ // with a warning.
185
+ // 2. If verify_homogeneous_extent == false: An empty mesh will be
186
+ // returned.
187
+ if (!dont_verify_homogeneous_extents.has_value ())
184
188
{
185
189
REQUIRE (
186
190
iteration.meshes .contains (" e_chargeDensity" ) ==
187
191
step_has_charge_density);
192
+ if (step_has_charge_density)
193
+ {
194
+ REQUIRE (iteration.meshes [" e_chargeDensity" ].scalar ());
195
+ }
188
196
}
189
197
else
190
198
{
191
- // Without a group table, the groups need to be recovered from
192
- // attributes and variables found in the ADIOS2 file. But since the
193
- // e_chargeDensity mesh exists only in a subselection of steps, its
194
- // attributes will leak into the other steps, making the API think
195
- // that there is data where there is none.
196
199
REQUIRE (iteration.meshes .contains (" e_chargeDensity" ));
197
200
// Only when the variable is also found, the reading routines will
198
201
// correctly determine that this is a scalar mesh.
199
202
REQUIRE (
200
203
iteration.meshes [" e_chargeDensity" ].scalar () ==
201
204
step_has_charge_density);
205
+ if (!step_has_charge_density)
206
+ {
207
+ REQUIRE (iteration.meshes [" e_chargeDensity" ].size () == 0 );
208
+ }
202
209
}
203
210
if (step_has_charge_density)
204
211
{
@@ -222,13 +229,14 @@ auto read_variablebased_randomaccess() -> void
222
229
create_file_in_serial (true );
223
230
}
224
231
MPI_Barrier (MPI_COMM_WORLD);
225
- read_file_in_parallel (true );
232
+ // read_file_in_parallel(std::nullopt );
226
233
if (rank == 0 )
227
234
{
228
235
create_file_in_serial (false );
229
236
}
230
237
MPI_Barrier (MPI_COMM_WORLD);
231
- read_file_in_parallel (false );
238
+ read_file_in_parallel (std::nullopt);
239
+ read_file_in_parallel (R"( {"verify_homogeneous_extents": false})" );
232
240
}
233
241
} // namespace read_variablebased_randomaccess
234
242
#else
0 commit comments