Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
* Distributed under the OSI-approved Apache License, Version 2.0. See
* accompanying file Copyright.txt for details.
*
* Write local arrays from multiple processors.
*
* If one cannot or does not want to organize arrays present on each process
* as one global array, still one can write them out with the same name.
* Reading, however, needs to be handled differently: each process' array has
* to be read separately, using Writeblock selections. The size of each process
* block should be discovered by the reading application by inquiring per-block
* size information of the variable, and allocate memory for reading
* accordingly.
*
* bpls can show the size of each block of the variable:
* bpls -D <file> <variable>
*
*
* Created on: Jun 2, 2017
* Author: pnorbert
*/
#include <iostream>
#include <vector>
#include <adios2.h>
#ifdef ADIOS2_HAVE_MPI
#include <mpi.h>
#endif
int main(int argc, char *argv[])
{
int rank = 0, nproc = 1;
#ifdef ADIOS2_HAVE_MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
#endif
const bool adiosDebug = true;
const int NSTEPS = 5;
// generate different random numbers on each process,
// but always the same sequence at each run
srand(rank * 32767);
#ifdef ADIOS2_HAVE_MPI
adios2::ADIOS adios(MPI_COMM_WORLD);
#endif
// Application variables for output
// random size per process, 5..10 each
unsigned int Nx = rand() % 6 + 5;
// Local array, size is fixed over time on each process
std::vector<double> v1(Nx);
// random size per process, a different size at each step
unsigned int Nelems;
// Local array, size is changing over time on each process
std::vector<double> v2;
try
{
// Get io settings from the config file or
// create one with default settings here
adios2::IO &io = adios.DeclareIO("Output");
/*
* Define local array: type, name, local size
* Global dimension and starting offset must be an empty vector
*/
io.DefineVariable<double>("v1", {}, {}, {Nx});
/*
* Define local array: type, name
* Global dimension and starting offset must be an empty vector
* but local size must NOT be an empty vector.
* We can use {adios2::UnknownDim} for this purpose or any number
* but we will modify it before writing
*/
adios2::Variable<double> &varV2 =
io.DefineVariable<double>("v2", {}, {}, {adios2::UnknownDim});
// Open file. "w" means we overwrite any existing file on disk,
// but Advance() will append steps to the same file.
auto writer = io.Open("localArray.bp", adios2::OpenMode::Write);
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
if (writer == nullptr)
throw std::ios_base::failure(
"ERROR: failed to open file with ADIOS\n");
for (int step = 0; step < NSTEPS; step++)
{
for (int i = 0; i < Nx; i++)
{
v1[i] = rank * 1.0 + step * 0.1;
}
writer->Write<double>(varV1, v1.data());
// random size per process per step, 5..10 each
Nelems = rand() % 6 + 5;
v2.reserve(Nelems);
for (int i = 0; i < Nelems; i++)
{
v2[i] = rank * 1.0 + step * 0.1;
}
// Set the size of the array now because we did not know
// the size at the time of definition
varV2.SetSelection({}, {Nelems});
writer->Write<double>(varV2, v2.data());
writer->Advance();
}
writer->Close();
}
catch (std::invalid_argument &e)
{
if (rank == 0)
{
std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
std::cout << e.what() << "\n";
}
}
catch (std::ios_base::failure &e)
{
if (rank == 0)
{
std::cout << "System exception, STOPPING PROGRAM\n";
std::cout << e.what() << "\n";
}
}
catch (std::exception &e)
{
if (rank == 0)
{
std::cout << "Exception, STOPPING PROGRAM\n";
std::cout << e.what() << "\n";
}
}
#ifdef ADIOS2_HAVE_MPI
MPI_Finalize();
#endif
return 0;
}