1 #ifndef ADIOS2_QUERY_H
2 #define ADIOS2_QUERY_H
3
4 #include <ios> //std::ios_base::failure
5 #include <iostream> //std::cout
6
7 #include <numeric> // accumulate
8 #include <stdexcept> //std::invalid_argument std::exception
9 #include <vector>
10
11 //#include "adios2.h"
12 #include "adios2/common/ADIOSTypes.h"
13 #include "adios2/core/ADIOS.h"
14 #include "adios2/core/Engine.h"
15 #include "adios2/core/IO.h"
16 #include "adios2/core/Variable.h"
17 namespace adios2
18 {
19 namespace query
20 {
21 enum Op
22 {
23 GT,
24 LT,
25 GE,
26 LE,
27 NE,
28 EQ
29 };
30
31 enum Relation
32 {
33 AND,
34 OR,
35 NOT
36 };
37
strToRelation(std::string relationStr)38 static adios2::query::Relation strToRelation(std::string relationStr) noexcept
39 {
40 if ((relationStr.compare("or") == 0) || (relationStr.compare("OR") == 0))
41 return adios2::query::Relation::OR;
42
43 return adios2::query::Relation::AND; // default
44 }
45
strToQueryOp(std::string opStr)46 static adios2::query::Op strToQueryOp(std::string opStr) noexcept
47 {
48 if ((opStr.compare("lt") == 0) || (opStr.compare("LT") == 0))
49 return adios2::query::Op::LT;
50 if ((opStr.compare("gt") == 0) || (opStr.compare("GT") == 0))
51 return adios2::query::Op::GT;
52 if ((opStr.compare("ge") == 0) || (opStr.compare("GE") == 0))
53 return adios2::query::Op::GE;
54 if ((opStr.compare("le") == 0) || (opStr.compare("LE") == 0))
55 return adios2::query::Op::LE;
56 if ((opStr.compare("eq") == 0) || (opStr.compare("EQ") == 0))
57 return adios2::query::Op::EQ;
58 if ((opStr.compare("ne") == 0) || (opStr.compare("NE") == 0))
59 return adios2::query::Op::NE;
60
61 return adios2::query::Op::EQ; // default
62 }
63
split(const std::string & s,char delim)64 static adios2::Dims split(const std::string &s, char delim)
65 {
66 adios2::Dims dim;
67
68 std::stringstream ss(s);
69 std::string item;
70
71 while (getline(ss, item, delim))
72 {
73 std::stringstream curr(item);
74 size_t val;
75 curr >> val;
76 dim.push_back(val);
77 }
78
79 return dim;
80 }
81
82 //
83 // classes
84 //
85 class Range
86 {
87 public:
88 adios2::query::Op m_Op;
89 std::string m_StrValue;
90 // void* m_Value = nullptr;
91
92 // template<class T> bool Check(T val) const ;
93
94 template <class T>
95 bool CheckInterval(T &min, T &max) const;
96
Print()97 void Print() { std::cout << "===> " << m_StrValue << std::endl; }
98 }; // class Range
99
100 class RangeTree
101 {
102 public:
AddLeaf(adios2::query::Op op,std::string value)103 void AddLeaf(adios2::query::Op op, std::string value)
104 {
105 Range range;
106 range.m_Op = op;
107 range.m_StrValue = value;
108
109 m_Leaves.push_back(range);
110 }
111
AddNode(RangeTree & node)112 void AddNode(RangeTree &node) { m_SubNodes.push_back(node); }
113
SetRelation(adios2::query::Relation r)114 void SetRelation(adios2::query::Relation r) { m_Relation = r; }
115
Print()116 void Print()
117 {
118 for (auto leaf : m_Leaves)
119 leaf.Print();
120 for (auto node : m_SubNodes)
121 node.Print();
122 }
123
124 // template<class T> bool Check(T value) const ;
125
126 template <class T>
127 bool CheckInterval(T &min, T &max) const;
128
129 adios2::query::Relation m_Relation = adios2::query::Relation::AND;
130 std::vector<Range> m_Leaves;
131 std::vector<RangeTree> m_SubNodes;
132 }; // class RangeTree
133
134 class QueryBase
135 {
136 public:
~QueryBase()137 virtual ~QueryBase(){};
138 virtual bool IsCompatible(const adios2::Box<adios2::Dims> &box) = 0;
139 virtual void Print() = 0;
140 virtual void BlockIndexEvaluate(adios2::core::IO &, adios2::core::Engine &,
141 std::vector<Box<Dims>> &touchedBlocks) = 0;
142
GetIntersection(const Box<Dims> & box1,const Box<Dims> & box2)143 Box<Dims> GetIntersection(const Box<Dims> &box1,
144 const Box<Dims> &box2) noexcept
145 {
146 Box<Dims> b1 = adios2::helper::StartEndBox(box1.first, box1.second);
147 Box<Dims> b2 = adios2::helper::StartEndBox(box2.first, box2.second);
148
149 Box<Dims> result = adios2::helper::IntersectionBox(b1, b2);
150 return adios2::helper::StartCountBox(result.first, result.second);
151 }
152
UseOutputRegion(const adios2::Box<adios2::Dims> & region)153 bool UseOutputRegion(const adios2::Box<adios2::Dims> ®ion)
154 {
155 if (!IsCompatible(region))
156 return false;
157
158 m_OutputRegion = region;
159 BroadcastOutputRegion(region);
160 return true;
161 }
162
163 virtual void
164 BroadcastOutputRegion(const adios2::Box<adios2::Dims> ®ion) = 0;
165
166 void ApplyOutputRegion(std::vector<Box<Dims>> &touchedBlocks,
167 const adios2::Box<Dims> &referenceRegion);
168
169 adios2::Box<adios2::Dims> m_OutputRegion;
170
171 private:
172 // bool ResetToOutputRegion(Box<Dims>& block);
173 };
174
175 class QueryVar : public QueryBase
176 {
177 public:
QueryVar(const std::string & varName)178 QueryVar(const std::string &varName) : m_VarName(varName) {}
~QueryVar()179 ~QueryVar() {}
180
GetVarName()181 std::string &GetVarName() { return m_VarName; }
182 void BlockIndexEvaluate(adios2::core::IO &, adios2::core::Engine &,
183 std::vector<Box<Dims>> &touchedBlocks);
BroadcastOutputRegion(const adios2::Box<adios2::Dims> & region)184 void BroadcastOutputRegion(const adios2::Box<adios2::Dims> ®ion)
185 {
186 m_OutputRegion = region;
187 }
188
Print()189 void Print() { m_RangeTree.Print(); }
190
IsCompatible(const adios2::Box<adios2::Dims> & box)191 bool IsCompatible(const adios2::Box<adios2::Dims> &box)
192 {
193 if ((m_Selection.first.size() == 0) || (box.first.size() == 0))
194 return true;
195
196 if (box.first.size() != m_Selection.first.size())
197 return false;
198
199 for (int n = 0; n < box.second.size(); n++)
200 if (box.second[n] != m_Selection.second[n])
201 return false;
202
203 return true;
204 }
205
SetSelection(adios2::Dims & start,adios2::Dims & count)206 void SetSelection(adios2::Dims &start, adios2::Dims &count)
207 {
208 m_Selection.first = start;
209 m_Selection.second = count;
210 }
211
212 bool IsSelectionValid(adios2::Dims &varShape) const;
213
214 bool TouchSelection(adios2::Dims &start, adios2::Dims &count) const;
215
216 void LoadSelection(const std::string &startStr,
217 const std::string &countStr);
218
LimitToSelection(std::vector<Box<Dims>> & touchedBlocks)219 void LimitToSelection(std::vector<Box<Dims>> &touchedBlocks)
220 {
221 for (auto it = touchedBlocks.begin(); it != touchedBlocks.end(); it++)
222 {
223 Box<Dims> overlap = GetIntersection(m_Selection, *it);
224 // adios2::helper::IntersectionBox(m_Selection, *it);
225 it->first = overlap.first;
226 it->second = overlap.second;
227 }
228 }
229
230 RangeTree m_RangeTree;
231 adios2::Box<adios2::Dims> m_Selection;
232
233 std::string m_VarName;
234
235 private:
236 }; // class QueryVar
237
238 class QueryComposite : public QueryBase
239 {
240 public:
QueryComposite(adios2::query::Relation relation)241 QueryComposite(adios2::query::Relation relation) : m_Relation(relation) {}
~QueryComposite()242 ~QueryComposite()
243 {
244 for (auto n : m_Nodes)
245 delete n;
246 m_Nodes.clear();
247 }
248
BroadcastOutputRegion(const adios2::Box<adios2::Dims> & region)249 void BroadcastOutputRegion(const adios2::Box<adios2::Dims> ®ion)
250 {
251 if (m_Nodes.size() == 0)
252 return;
253
254 for (auto n : m_Nodes)
255 n->BroadcastOutputRegion(region);
256 }
257
258 void BlockIndexEvaluate(adios2::core::IO &, adios2::core::Engine &,
259 std::vector<Box<Dims>> &touchedBlocks);
260
261 bool AddNode(QueryBase *v);
262
Print()263 void Print()
264 {
265 std::cout << " Composite query" << std::endl;
266 for (auto n : m_Nodes)
267 n->Print();
268 }
269
IsCompatible(const adios2::Box<adios2::Dims> & box)270 bool IsCompatible(const adios2::Box<adios2::Dims> &box)
271 {
272 if (m_Nodes.size() == 0)
273 return false;
274 return (m_Nodes[0])->IsCompatible(box);
275 }
276
277 private:
278 adios2::query::Relation m_Relation = adios2::query::Relation::AND;
279
280 std::vector<QueryBase *> m_Nodes;
281 }; // class QueryComposite
282
283 /*
284 */
285
286 } // namespace query
287 } // namespace adiso2
288
289 #endif // define
290