Skip to content

Commit a662865

Browse files
committed
Properly deal with undefined datasets
1 parent 6527acf commit a662865

File tree

3 files changed

+85
-17
lines changed

3 files changed

+85
-17
lines changed

examples/14_toml_template.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
#include <openPMD/auxiliary/TemplateFile.hpp>
12
#include <openPMD/openPMD.hpp>
23

3-
int main()
4+
void write()
45
{
56
std::string config = R"(
67
{
@@ -24,7 +25,11 @@ int main()
2425
auto E = iteration.meshes["E"];
2526
E["x"].resetDataset(ds);
2627
E["y"].resetDataset(ds);
27-
E["z"].resetDataset(ds);
28+
/*
29+
* Don't specify datatype and extent for this one to indicate that this
30+
* information is not yet known.
31+
*/
32+
E["z"]; //.resetDataset(ds);
2833

2934
ds.extent = {10};
3035

@@ -53,3 +58,35 @@ int main()
5358
electrons.particlePatches["extent"]["y"].resetDataset(ds);
5459
electrons.particlePatches["extent"]["z"].resetDataset(ds);
5560
}
61+
62+
void read()
63+
{
64+
std::string config = R"(
65+
{
66+
"iteration_encoding": "variable_based",
67+
"toml": {
68+
"mode": "template"
69+
}
70+
}
71+
)";
72+
openPMD::Series read(
73+
"../samples/tomlTemplate.toml", openPMD::Access::READ_ONLY, config);
74+
75+
std::string jsonConfig = R"(
76+
{
77+
"iteration_encoding": "variable_based",
78+
"json": {
79+
"mode": "template"
80+
}
81+
}
82+
)";
83+
openPMD::Series cloned(
84+
"../samples/jsonTemplate.json", openPMD::Access::CREATE, jsonConfig);
85+
openPMD::auxiliary::initializeFromTemplate(cloned, read, 0);
86+
}
87+
88+
int main()
89+
{
90+
write();
91+
read();
92+
}

src/IO/JSON/JSONIOHandlerImpl.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,15 @@ void JSONIOHandlerImpl::createDataset(
351351
break;
352352
}
353353
case IOMode::Template:
354-
dset["extent"] = parameter.extent;
354+
if (parameter.extent != Extent{0})
355+
{
356+
dset["extent"] = parameter.extent;
357+
}
358+
else
359+
{
360+
// no-op
361+
// If extent is empty, don't bother writing it
362+
}
355363
break;
356364
}
357365

@@ -1471,7 +1479,14 @@ Extent JSONIOHandlerImpl::getExtent(nlohmann::json &j, IOMode mode)
14711479
}
14721480
break;
14731481
case IOMode::Template:
1474-
res = j["extent"].get<Extent>();
1482+
if (j.contains("extent"))
1483+
{
1484+
res = j["extent"].get<Extent>();
1485+
}
1486+
else
1487+
{
1488+
res = {0};
1489+
}
14751490
break;
14761491
}
14771492
return res;

src/RecordComponent.cpp

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace internal
4242
RecordComponent impl{
4343
std::shared_ptr<RecordComponentData>{this, [](auto const *) {}}};
4444
impl.setUnitSI(1);
45-
impl.resetDataset(Dataset(Datatype::CHAR, {1}));
45+
m_dataset = Dataset(Datatype::UNDEFINED, {0});
4646
}
4747
} // namespace internal
4848

@@ -83,18 +83,28 @@ RecordComponent &RecordComponent::resetDataset(Dataset d)
8383
rc.m_hasBeenExtended = true;
8484
}
8585

86-
if (d.dtype == Datatype::UNDEFINED)
87-
{
88-
throw error::WrongAPIUsage(
89-
"[RecordComponent] Must set specific datatype.");
90-
}
86+
// if (d.dtype == Datatype::UNDEFINED)
87+
// {
88+
// throw error::WrongAPIUsage(
89+
// "[RecordComponent] Must set specific datatype.");
90+
// }
9191
// if( d.extent.empty() )
9292
// throw std::runtime_error("Dataset extent must be at least 1D.");
9393
if (std::any_of(
9494
d.extent.begin(), d.extent.end(), [](Extent::value_type const &i) {
9595
return i == 0u;
9696
}))
97-
return makeEmpty(std::move(d));
97+
{
98+
if (d.dtype != Datatype::UNDEFINED)
99+
{
100+
return makeEmpty(std::move(d));
101+
}
102+
else
103+
{
104+
rc.m_dataset = std::move(d);
105+
return *this;
106+
}
107+
}
98108

99109
rc.m_isEmpty = false;
100110
if (written())
@@ -215,12 +225,18 @@ void RecordComponent::flush(
215225
/*
216226
* This catches when a user forgets to use resetDataset.
217227
*/
218-
if (rc.m_dataset.dtype == Datatype::UNDEFINED)
219-
{
220-
throw error::WrongAPIUsage(
221-
"[RecordComponent] Must set specific datatype (Use "
222-
"resetDataset call).");
223-
}
228+
/*
229+
* Suggestion for keeping this check:
230+
* Use a std::optional<Dataset> in RecordComponentData, throw an error
231+
* if it is still empty here, let users explicitly set Undefined
232+
* datatypes for backend-specific actions.
233+
*/
234+
// if (rc.m_dataset.dtype == Datatype::UNDEFINED)
235+
// {
236+
// throw error::WrongAPIUsage(
237+
// "[RecordComponent] Must set specific datatype (Use "
238+
// "resetDataset call).");
239+
// }
224240
if (!written())
225241
{
226242
if (constant())

0 commit comments

Comments
 (0)