@@ -40,6 +40,18 @@ std::vector<std::string> getBackends()
40
40
41
41
auto const backends = getBackends();
42
42
43
+ std::vector<std::string> testedFileExtensions ()
44
+ {
45
+ auto allExtensions = getFileExtensions ();
46
+ auto newEnd = std::remove_if (
47
+ allExtensions.begin (), allExtensions.end (), [](std::string const &ext) {
48
+ // sst and ssc need a receiver for testing
49
+ // bp4 is already tested via bp
50
+ return ext == " sst" || ext == " ssc" || ext == " bp4" | ext == " json" ;
51
+ });
52
+ return {allExtensions.begin (), newEnd};
53
+ }
54
+
43
55
#else
44
56
45
57
TEST_CASE (" none" , " [parallel]" )
@@ -1368,4 +1380,213 @@ TEST_CASE("adios2_ssc", "[parallel][adios2]")
1368
1380
{
1369
1381
adios2_ssc ();
1370
1382
}
1383
+
1384
+ void append_mode (
1385
+ std::string const &extension,
1386
+ bool variableBased,
1387
+ std::string jsonConfig = " {}" )
1388
+ {
1389
+ std::string filename =
1390
+ (variableBased ? " ../samples/append/append_variablebased."
1391
+ : " ../samples/append/append_groupbased." ) +
1392
+ extension;
1393
+ MPI_Barrier (MPI_COMM_WORLD);
1394
+ if (auxiliary::directory_exists (" ../samples/append" ))
1395
+ {
1396
+ auxiliary::remove_directory (" ../samples/append" );
1397
+ }
1398
+ MPI_Barrier (MPI_COMM_WORLD);
1399
+ std::vector<int > data (10 , 0 );
1400
+ auto writeSomeIterations = [&data](
1401
+ WriteIterations &&writeIterations,
1402
+ std::vector<uint64_t > indices) {
1403
+ for (auto index : indices)
1404
+ {
1405
+ auto it = writeIterations[index];
1406
+ auto dataset = it.meshes [" E" ][" x" ];
1407
+ dataset.resetDataset ({Datatype::INT, {10 }});
1408
+ dataset.storeChunk (data, {0 }, {10 });
1409
+ // test that it works without closing too
1410
+ it.close ();
1411
+ }
1412
+ };
1413
+ {
1414
+ Series write (filename, Access::APPEND, MPI_COMM_WORLD, jsonConfig);
1415
+ if (variableBased)
1416
+ {
1417
+ if (write.backend () != " ADIOS2" )
1418
+ {
1419
+ return ;
1420
+ }
1421
+ write.setIterationEncoding (IterationEncoding::variableBased);
1422
+ }
1423
+ writeSomeIterations (
1424
+ write.writeIterations (), std::vector<uint64_t >{0 , 1 });
1425
+ }
1426
+ {
1427
+ Series write (filename, Access::APPEND, MPI_COMM_WORLD, jsonConfig);
1428
+ if (variableBased)
1429
+ {
1430
+ write.setIterationEncoding (IterationEncoding::variableBased);
1431
+ }
1432
+ if (write.backend () == " MPI_ADIOS1" )
1433
+ {
1434
+ REQUIRE_THROWS_WITH (
1435
+ write.flush (),
1436
+ Catch::Equals (
1437
+ " Operation unsupported in ADIOS1: Appending to existing "
1438
+ " file on disk (use Access::CREATE to overwrite)" ));
1439
+ // destructor will be noisy now
1440
+ return ;
1441
+ }
1442
+
1443
+ writeSomeIterations (
1444
+ write.writeIterations (), std::vector<uint64_t >{2 , 3 });
1445
+ write.flush ();
1446
+ }
1447
+ {
1448
+ using namespace std ::chrono_literals;
1449
+ /*
1450
+ * Put a little sleep here to trigger writing of a different /date
1451
+ * attribute. ADIOS2 v2.7 does not like that so this test ensures that
1452
+ * we deal with it.
1453
+ */
1454
+ std::this_thread::sleep_for (1s);
1455
+ Series write (filename, Access::APPEND, MPI_COMM_WORLD, jsonConfig);
1456
+ if (variableBased)
1457
+ {
1458
+ write.setIterationEncoding (IterationEncoding::variableBased);
1459
+ }
1460
+ if (write.backend () == " MPI_ADIOS1" )
1461
+ {
1462
+ REQUIRE_THROWS_WITH (
1463
+ write.flush (),
1464
+ Catch::Equals (
1465
+ " Operation unsupported in ADIOS1: Appending to existing "
1466
+ " file on disk (use Access::CREATE to overwrite)" ));
1467
+ // destructor will be noisy now
1468
+ return ;
1469
+ }
1470
+
1471
+ writeSomeIterations (
1472
+ write.writeIterations (), std::vector<uint64_t >{4 , 3 });
1473
+ write.flush ();
1474
+ }
1475
+ {
1476
+ Series read (filename, Access::READ_ONLY, MPI_COMM_WORLD);
1477
+ if (variableBased || extension == " bp5" )
1478
+ {
1479
+ // in variable-based encodings, iterations are not parsed ahead of
1480
+ // time but as they go
1481
+ unsigned counter = 0 ;
1482
+ for (auto const &iteration : read.readIterations ())
1483
+ {
1484
+ REQUIRE (iteration.iterationIndex == counter);
1485
+ ++counter;
1486
+ }
1487
+ REQUIRE (counter == 5 );
1488
+ }
1489
+ else
1490
+ {
1491
+ REQUIRE (read.iterations .size () == 5 );
1492
+ }
1493
+ /*
1494
+ * Roadmap: for now, reading this should work by ignoring the last
1495
+ * duplicate iteration.
1496
+ * After merging https://github.com/openPMD/openPMD-api/pull/949, we
1497
+ * should see both instances when reading.
1498
+ * Final goal: Read only the last instance.
1499
+ */
1500
+ helper::listSeries (read);
1501
+ }
1502
+ #if 100000000 * ADIOS2_VERSION_MAJOR + 1000000 * ADIOS2_VERSION_MINOR + \
1503
+ 10000 * ADIOS2_VERSION_PATCH + 100 * ADIOS2_VERSION_TWEAK >= \
1504
+ 208002700
1505
+ // AppendAfterSteps has a bug before that version
1506
+ if (extension == " bp5" )
1507
+ {
1508
+ {
1509
+ Series write (
1510
+ filename,
1511
+ Access::APPEND,
1512
+ MPI_COMM_WORLD,
1513
+ json::merge (
1514
+ jsonConfig,
1515
+ R"( {"adios2":{"engine":{"parameters":{"AppendAfterSteps":-3}}}})" ));
1516
+ if (variableBased)
1517
+ {
1518
+ write.setIterationEncoding (IterationEncoding::variableBased);
1519
+ }
1520
+ if (write.backend () == " ADIOS1" )
1521
+ {
1522
+ REQUIRE_THROWS_WITH (
1523
+ write.flush (),
1524
+ Catch::Equals (
1525
+ " Operation unsupported in ADIOS1: Appending to "
1526
+ " existing "
1527
+ " file on disk (use Access::CREATE to overwrite)" ));
1528
+ // destructor will be noisy now
1529
+ return ;
1530
+ }
1531
+
1532
+ writeSomeIterations (
1533
+ write.writeIterations (), std::vector<uint64_t >{4 , 5 });
1534
+ write.flush ();
1535
+ }
1536
+ {
1537
+ Series read (filename, Access::READ_ONLY, MPI_COMM_WORLD);
1538
+ // in variable-based encodings, iterations are not parsed ahead of
1539
+ // time but as they go
1540
+ unsigned counter = 0 ;
1541
+ for (auto const &iteration : read.readIterations ())
1542
+ {
1543
+ REQUIRE (iteration.iterationIndex == counter);
1544
+ ++counter;
1545
+ }
1546
+ REQUIRE (counter == 6 );
1547
+ helper::listSeries (read);
1548
+ }
1549
+ }
1550
+ #endif
1551
+ }
1552
+
1553
+ TEST_CASE (" append_mode" , " [parallel]" )
1554
+ {
1555
+ for (auto const &t : testedFileExtensions ())
1556
+ {
1557
+ if (t == " bp" || t == " bp4" || t == " bp5" )
1558
+ {
1559
+ std::string jsonConfigOld = R"END(
1560
+ {
1561
+ "adios2":
1562
+ {
1563
+ "schema": 0,
1564
+ "engine":
1565
+ {
1566
+ "usesteps" : true
1567
+ }
1568
+ }
1569
+ })END" ;
1570
+ std::string jsonConfigNew = R"END(
1571
+ {
1572
+ "adios2":
1573
+ {
1574
+ "schema": 20210209,
1575
+ "engine":
1576
+ {
1577
+ "usesteps" : true
1578
+ }
1579
+ }
1580
+ })END" ;
1581
+ append_mode (t, false , jsonConfigOld);
1582
+ append_mode (t, false , jsonConfigNew);
1583
+ append_mode (t, true , jsonConfigOld);
1584
+ append_mode (t, true , jsonConfigNew);
1585
+ }
1586
+ else
1587
+ {
1588
+ append_mode (t, false );
1589
+ }
1590
+ }
1591
+ }
1371
1592
#endif
0 commit comments