File: attributes.rst

package info (click to toggle)
adios2 2.10.2%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 33,764 kB
  • sloc: cpp: 175,964; ansic: 160,510; f90: 14,630; yacc: 12,668; python: 7,275; perl: 7,126; sh: 2,825; lisp: 1,106; xml: 1,049; makefile: 579; lex: 557
file content (230 lines) | stat: -rw-r--r-- 7,338 bytes parent folder | download | duplicates (2)
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
Attributes
==========

.. _sec:tutorials_basics_attributes:

In the previous tutorial, we learned how to write/read variables.

In this tutorial, we will explore how to write/read attributes. Attributes are metadata related to the whole dataset or
to a specific variable. In this tutorial, we will only focus on attributes related to the whole dataset, but we will
explain how variable's attributes can be used too.

Start editing the skeleton file `ADIOS2/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead_tutorialSkeleton.cpp <https://github.com/ornladios/ADIOS2/blob/master/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead_tutorialSkeleton.cpp>`_.

1. In an MPI application first we need to always initialize MPI. We do that with the following lines:

.. code-block:: cpp

   int rank, size;
   int provided;

   // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP
   MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
   MPI_Comm_size(MPI_COMM_WORLD, &size);

2.  Now we need to create a application variable which will be used to define an ADIOS2 variable.

.. code-block:: cpp

   std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

3. Then, we need to create an ADIOS2 instance.

.. code-block:: cpp

   adios2::ADIOS adios(MPI_COMM_WORLD);

4. Then, we create the following writer function:

.. code-block:: cpp

   void writer(adios2::ADIOS &adios, int rank, int size, std::vector<float> &myFloats)
   {
      ...
   }

5. In this writer function, we define an IO object, and a float vector variable as follows:

.. code-block:: cpp

   adios2::IO bpIO = adios.DeclareIO("BPFile_N2N");

   const std::size_t Nx = myFloats.size();
   adios2::Variable<float> bpFloats = bpIO.DefineVariable<float>(
     "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims);

6. Now, we will define various types of attributes as follows:

.. code-block:: cpp

   bpIO.DefineAttribute<std::string>("Single_String", "File generated with ADIOS2");

   std::vector<std::string> myStrings = {"one", "two", "three"};
   bpIO.DefineAttribute<std::string>("Array_of_Strings", myStrings.data(), myStrings.size());

   bpIO.DefineAttribute<double>("Attr_Double", 0.f);
   std::vector<double> myDoubles = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   bpIO.DefineAttribute<double>("Array_of_Doubles", myDoubles.data(), myDoubles.size());

.. note::

   if we want to define an attribute for a specific variable, we can use one of the following API:

   .. code-block:: cpp

      template <class T>
      Attribute<T> DefineAttribute(const std::string &name, const T *data, const size_t size,
                                   const std::string &variableName = "", const std::string separator = "/",
                                   const bool allowModification = false);

      template <class T>
      Attribute<T> DefineAttribute(const std::string &name, const T &value,
                                   const std::string &variableName = "", const std::string separator = "/",
                                   const bool allowModification = false);

   As we can see, by default the attributes don't change over multiple steps, but we can change that by setting
   ``allowModification`` to ``true``.

7. Then, we open a file for writing:

.. code-block:: cpp

   adios2::Engine bpWriter = bpIO.Open("fileAttributes.bp", adios2::Mode::Write);

8. Now, we write the data and close the file:

.. code-block:: cpp

   bpWriter.BeginStep();
   bpWriter.Put<float>(bpFloats, myFloats.data());
   bpWriter.EndStep();
   bpWriter.Close();

9. Steps 1-8 are used for writing, we will define a reader function in the rest of the steps:

.. code-block:: cpp

   void reader(adios2::ADIOS &adios, int rank, int size)
   {
      ...
   }

10. In this reader function, we define an IO object, and open the file for reading:

.. code-block:: cpp

   adios2::IO bpIO = adios.DeclareIO("BPFile_N2N");
   adios2::Engine bpReader = bpIO.Open("fileAttributes.bp", adios2::Mode::Read);

11. Now, we check the available attributes as follows:

.. code-block:: cpp

   bpReader.BeginStep();
   const auto attributesInfo = bpIO.AvailableAttributes();

   for (const auto &attributeInfoPair : attributesInfo)
   {
     std::cout << "Attribute: " << attributeInfoPair.first;
     for (const auto &attributePair : attributeInfoPair.second)
     {
         std::cout << "\tKey: " << attributePair.first << "\tValue: " << attributePair.second
                   << "\n";
     }
     std::cout << "\n";
   }

12. Now we will inquire and get the attributes as follows:

.. code-block:: cpp

    adios2::Attribute<float> singleString = bpIO.InquireAttribute<float>("Single_String");
    if (singleString)
    {
        std::cout << singleString.Name() << ": " << singleString.Data()[0] << "\n";
    }
    adios2::Attribute<std::string> arrayOfStrings =
        bpIO.InquireAttribute<std::string>("Array_of_Strings");
    if (arrayOfStrings)
    {
        std::cout << arrayOfStrings.Name() << ": ";
        for (const auto &value : arrayOfStrings.Data())
        {
            std::cout << value << " ";
        }
        std::cout << "\n";
    }
    adios2::Attribute<double> attrDouble = bpIO.InquireAttribute<double>("Attr_Double");
    if (attrDouble)
    {
        std::cout << attrDouble.Name() << ": " << attrDouble.Data()[0] << "\n";
    }
    adios2::Attribute<double> arrayOfDoubles = bpIO.InquireAttribute<double>("Array_of_Doubles");
    if (arrayOfDoubles)
    {
        std::cout << arrayOfDoubles.Name() << ": ";
        for (const auto &value : arrayOfDoubles.Data())
        {
            std::cout << value << " ";
        }
        std::cout << "\n";
    }

13. Afterward, we will inquire and get the variable as follows:

.. code-block:: cpp

    adios2::Variable<float> bpFloats = bpIO.InquireVariable<float>("bpFloats");
    const std::size_t Nx = 10;
    std::vector<float> myFloats(Nx);
    if (bpFloats)
    {
        bpFloats.SetSelection({{Nx * rank}, {Nx}});
        bpReader.Get(bpFloats, myFloats.data());
    }
    bpReader.EndStep();

14. Finally, we close the file:

.. code-block:: cpp

   bpReader.Close();

15. In the main function, we call the writer and reader functions as follows:

.. code-block:: cpp

   writer(adios, rank, size, myFloats);
   reader(adios, rank, size);

16. Finally, we finalize MPI:

.. code-block:: cpp

   MPI_Finalize();

17. The final code should look as follows (excluding try/catch and optional usage MPI), and it was derived from the
    example `ADIOS2/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp <https://github.com/ornladios/ADIOS2/blob/master/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp>`_.

.. literalinclude:: ../../../../examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp
   :language: cpp

18. You can compile and run it as follows:

.. code-block:: bash

   cd Path-To-ADIOS2/examples/hello/bpAttributeWriteRead
   mkdir build
   cd build
   cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ ..
   cmake --build .
   mpirun -np 2 ./adios2_hello_bpAttributeWriteRead_mpi

19. You can check the content of the output file "fileAttributes.bp" using *bpls* as follows:

.. code-block:: bash

   Path-To-ADIOS2/build/bin/bpls ./fileAttributes.bp

     float    bpFloats  {20}