OpenCAEPoro  v0.5.0
A simulator for multicomponent porous media flow
OCPOutput.hpp
Go to the documentation of this file.
1 
12 #ifndef __OCP_OUTPUT_HEADER__
13 #define __OCP_OUTPUT_HEADER__
14 
15 // Standard header files
16 #include <iomanip>
17 #include <iostream>
18 
19 // OpenCAEPoro header files
20 #include "OCPControl.hpp"
21 #include "Output4Vtk.hpp"
22 #include "ParamOutput.hpp"
23 #include "Reservoir.hpp"
24 #include "UtilOutput.hpp"
25 #include "UtilTiming.hpp"
26 
27 #ifdef USE_METIS
28 #include "metis.h"
29 #endif
30 
31 using namespace std;
32 
34 class OCPIJK
35 {
36 public:
37  OCPIJK() = default;
38  OCPIJK(const USI& i, const USI& j, const USI& k)
39  : I(i)
40  , J(j)
41  , K(k){};
42  OCPIJK(const COOIJK& src)
43  {
44  I = src.I;
45  J = src.J;
46  K = src.K;
47  };
48  OCPIJK& operator=(const COOIJK& src)
49  {
50  I = src.I;
51  J = src.J;
52  K = src.K;
53  return *this;
54  }
55  USI I, J, K;
56 };
57 
59 template <typename T>
61 {
62 public:
63  OCPType_Sum& operator=(const Type_A_o& src)
64  {
65  activity = src.activity;
66  obj = src.obj;
67  return *this;
68  }
69  OCPType_Sum& operator=(const Type_B_o& src)
70  {
71  activity = src.activity;
72  obj.assign(src.obj.begin(), src.obj.end());
73  return *this;
74  }
75  OCP_BOOL activity{OCP_FALSE};
76  vector<T> obj;
77  vector<USI>
79 };
80 
82 class SumItem
83 {
84 public:
85  SumItem(const string& item,
86  const string& obj,
87  const string& unit,
88  const string& type)
89  : Item(item)
90  , Obj(obj)
91  , Unit(unit)
92  , Type(type){};
93  string Item;
94  string Obj;
95  string Unit;
96  string Type;
97  vector<OCP_DBL> val;
98 };
99 
101 // Note: It contains the most interested information in each time step, which usually
102 // will be convert to figures for later analysis.
103 class Summary
104 {
105 public:
107  void InputParam(const OutputSummary& summary_param);
108 
110  void Setup(const Reservoir& reservoir, const OCP_DBL& totalTime);
111 
113  void SetVal(const Reservoir& reservoir, const OCPControl& ctrl);
114 
116  void PrintInfo(const string& dir) const;
117 
118 private:
119  vector<SumItem> Sumdata;
120 
121  OCP_BOOL FPR{OCP_FALSE};
122  OCP_BOOL FTR{OCP_FALSE};
123  OCP_BOOL FOPR{OCP_FALSE};
124  OCP_BOOL FOPT{OCP_FALSE};
125  OCP_BOOL FGPR{OCP_FALSE};
126  OCP_BOOL FGPt{OCP_FALSE};
127  OCP_BOOL FWPR{OCP_FALSE};
128  OCP_BOOL FWPT{OCP_FALSE};
129  OCP_BOOL FGIR{OCP_FALSE};
130  OCP_BOOL FGIT{OCP_FALSE};
131  OCP_BOOL FWIR{OCP_FALSE};
132  OCP_BOOL FWIT{OCP_FALSE};
133 
134  OCPType_Sum<string> WOPR;
135  OCPType_Sum<string> WOPT;
136  OCPType_Sum<string> WGPR;
137  OCPType_Sum<string> WGPT;
138  OCPType_Sum<string> WWPR;
139  OCPType_Sum<string> WWPT;
140  OCPType_Sum<string> WGIR;
141  OCPType_Sum<string> WGIT;
142  OCPType_Sum<string> WWIR;
143  OCPType_Sum<string> WWIT;
144  OCPType_Sum<string> WBHP;
146 
147  OCPType_Sum<OCPIJK> BPR;
148  OCPType_Sum<OCPIJK> SOIL;
149  OCPType_Sum<OCPIJK> SGAS;
150  OCPType_Sum<OCPIJK> SWAT;
151 };
152 
155 {
156 public:
158  void Setup(const OCP_DBL& totalTime);
159 
161  void SetVal(const Reservoir& reservoir, const OCPControl& ctrl);
162 
164  void PrintFastReview(const string& dir) const;
165 
166 private:
167  vector<OCP_DBL> time;
168  vector<OCP_DBL> dt;
169  vector<OCP_DBL> dPmax;
170  vector<OCP_DBL> dVmax;
171  vector<OCP_DBL> dSmax;
172  vector<OCP_DBL> dNmax;
173  vector<OCP_DBL> cfl;
174 };
175 
178 {
179  friend class Out4RPT;
180  friend class Out4VTK;
181 
182 public:
183  void SetBasicGridProperty(const BasicGridPropertyParam& param);
184 
185 private:
186  OCP_BOOL PRE{OCP_FALSE};
187  OCP_BOOL PGAS{OCP_FALSE};
188  OCP_BOOL PWAT{OCP_FALSE};
189  OCP_BOOL SOIL{OCP_FALSE};
190  OCP_BOOL SGAS{OCP_FALSE};
191  OCP_BOOL SWAT{OCP_FALSE};
192  OCP_BOOL DENO{OCP_FALSE};
193  OCP_BOOL DENG{OCP_FALSE};
194  OCP_BOOL DENW{OCP_FALSE};
195  OCP_BOOL KRO{OCP_FALSE};
196  OCP_BOOL KRG{OCP_FALSE};
197  OCP_BOOL KRW{OCP_FALSE};
198  OCP_BOOL BOIL{OCP_FALSE};
199  OCP_BOOL BGAS{OCP_FALSE};
200  OCP_BOOL BWAT{OCP_FALSE};
201  OCP_BOOL VOIL{OCP_FALSE};
202  OCP_BOOL VGAS{OCP_FALSE};
203  OCP_BOOL VWAT{OCP_FALSE};
204  OCP_BOOL XMF{OCP_FALSE};
205  OCP_BOOL YMF{OCP_FALSE};
206  OCP_BOOL PCW{OCP_FALSE};
207 };
208 
210 class Out4RPT
211 {
212 public:
213  void InputParam(const OutputRPTParam& RPTparam);
214  void Setup(const string& dir, const Reservoir& reservoir);
215  void PrintRPT(const string& dir, const Reservoir& rs, const OCP_DBL& days) const;
216  template <typename T>
217  void PrintRPT_Scalar(ofstream& ifs,
218  const string& dataName,
219  const OCP_DBL& days,
220  const T* gridVal,
221  const USI& gap,
222  const vector<GB_Pair>& gbPair,
223  const bool& useActive,
224  const OCP_DBL& alpha = 1.0) const;
225  void GetIJKGrid(USI& i, USI& j, USI& k, const OCP_USI& n) const;
226 
227 private:
228  OCP_BOOL useRPT{OCP_FALSE};
229  OCP_USI numGrid;
230  OCP_USI nx;
231  OCP_USI ny;
232  USI IJKspace;
233  BasicGridProperty bgp;
234 };
235 
236 template <typename T>
237 void Out4RPT::PrintRPT_Scalar(ofstream& myRPT,
238  const string& dataName,
239  const OCP_DBL& days,
240  const T* gridVal,
241  const USI& gap,
242  const vector<GB_Pair>& gbPair,
243  const bool& useActive,
244  const OCP_DBL& alpha) const
245 {
246  USI I, J, K;
247  OCP_USI bId;
248 
249  myRPT << OCP_SEP01(50) << "\n";
250  myRPT << dataName << " " << fixed << setprecision(3) << days
251  << " DAYS";
252 
253  if (useActive) {
254  for (OCP_USI n = 0; n < numGrid; n++) {
255  if (n % nx == 0) myRPT << "\n";
256  if (n % (nx * ny) == 0) myRPT << "\n\n";
257 
258  if (n % nx == 0) {
259  GetIJKGrid(I, J, K, n);
260  myRPT << GetIJKformat("*", to_string(J), to_string(K), IJKspace);
261  }
262 
263  if (gbPair[n].IsAct()) {
264  bId = gbPair[n].GetId();
265  myRPT << setw(10) << fixed << setprecision(3)
266  << gridVal[bId * gap] * alpha;
267  } else {
268  myRPT << setw(10) << " --- ";
269  }
270  }
271  } else {
272  for (OCP_USI n = 0; n < numGrid; n++) {
273  if (n % nx == 0) myRPT << "\n";
274  if (n % (nx * ny) == 0) myRPT << "\n\n";
275 
276  if (n % nx == 0) {
277  GetIJKGrid(I, J, K, n);
278  myRPT << GetIJKformat("*", to_string(J), to_string(K), IJKspace);
279  }
280  myRPT << setw(10) << fixed << setprecision(3) << gridVal[n * gap] * alpha;
281  }
282  }
283 
284  myRPT << "\n\n\n";
285 }
286 
287 class Out4VTK
288 {
289 public:
290  void InputParam(const OutputVTKParam& VTKParam);
291  void Setup(const string& dir, const Reservoir& rs, const USI& ndates);
292  void PrintVTK(const string& dir, const Reservoir& rs, const OCP_DBL& days) const;
293  OCP_BOOL IfOutputVTK() const { return useVTK; }
294 
295 private:
296  OCP_BOOL useVTK{OCP_FALSE};
297  mutable USI index{0};
298  BasicGridProperty bgp;
299  Output4Vtk out4vtk;
300 
301  // test for Parallel version
302 #ifdef USE_METIS
303  mutable class MyMetisTest
304  {
305  friend class Out4VTK;
306 
307  private:
308  OCP_BOOL useMetis{OCP_FALSE};
309 
310  OCP_USI nb;
311  OCP_USI nw;
312  OCP_USI ng;
313 
314  mutable idx_t nvtxs;
315  mutable idx_t nedges;
316  mutable idx_t ncon{1};
317  mutable idx_t nparts{8};
318  mutable vector<idx_t> xadj;
319  mutable vector<idx_t> adjncy;
320  mutable vector<idx_t> adjwgt;
321  mutable vector<idx_t> vwgt;
322  mutable vector<idx_t> part;
323  mutable vector<USI> partitions;
324  const idx_t MAXWEIGHT = 100000000;
325 
326  public:
327  void Setup(const Reservoir& rs)
328  {
329  if (!useMetis) return;
330  nb = rs.GetBulkNum();
331  nw = rs.GetWellNum();
332  ng = rs.grid.GetGridNum();
333 
334  nvtxs = nb + nw;
335  nedges = 0;
336  vector<vector<OCP_USI>> tmpConn = rs.conn.neighbor;
337  vector<OCP_USI> tmp;
338  for (USI w = 0; w < rs.allWells.numWell; w++) {
339  tmp.clear();
340  for (USI p = 0; p < rs.allWells.GetWellPerfNum(w); p++) {
341  OCP_USI n = rs.allWells.wells[w].PerfLocation(p);
342  tmpConn[n].push_back(nb + w);
343  tmp.push_back(n);
344  }
345  tmpConn.push_back(tmp);
346  nedges += rs.allWells.GetWellPerfNum(w) * 2;
347  }
348 
349  const vector<vector<OCP_USI>>& myConn = tmpConn;
350 
351  for (OCP_USI n = 0; n < nb; n++) {
352  nedges += rs.conn.neighborNum[n];
353  }
354  nedges -= nb;
355 
356  // generate xadj adjncy adjwgt
357  xadj.resize(nvtxs + 1);
358  xadj[0] = 0;
359  adjncy.reserve(nedges);
360  adjwgt.reserve(nedges);
361  // Bulk
362  for (OCP_USI n = 0; n < nb; n++) {
363  xadj[n + 1] = xadj[n] + myConn[n].size() - 1;
364  USI i = 0;
365  // left
366  for (i = 0; i < rs.conn.selfPtr[n]; i++) {
367  adjncy.push_back(myConn[n][i]);
368  adjwgt.push_back(1);
369  }
370  // right
371  for (i = rs.conn.selfPtr[n] + 1; i < rs.conn.neighborNum[n]; i++) {
372  adjncy.push_back(myConn[n][i]);
373  adjwgt.push_back(1);
374  }
375  // well
376  for (i = rs.conn.neighborNum[n]; i < myConn[n].size(); i++) {
377  adjncy.push_back(myConn[n][i]);
378  adjwgt.push_back(MAXWEIGHT);
379  }
380  }
381  // Well
382  for (USI w = 0; w < nw; w++) {
383  xadj[nb + w + 1] += xadj[nb + w] + myConn[nb + w].size();
384  for (auto v : myConn[nb + w]) {
385  adjncy.push_back(v);
386  adjwgt.push_back(MAXWEIGHT);
387  }
388  }
389  // Setup active/inactive grid flags
390  // inactive grids' flags equal nparts
391  part.resize(nvtxs, 0);
392  partitions.resize(ng + nw, nparts);
393  }
394 
395  void MyPartitionFunc(decltype(METIS_PartGraphKway)* METIS_PartGraphFunc) const
396  {
397 
398  if (!useMetis) return;
399  idx_t objval;
400  int ret = METIS_PartGraphFunc(&nvtxs, &ncon, xadj.data(), adjncy.data(),
401  vwgt.data(), NULL, adjwgt.data(), &nparts,
402  NULL, NULL, NULL, &objval, part.data());
403 
404  if (ret != rstatus_et::METIS_OK) {
405  OCP_ABORT("METIS ERROR");
406  }
407  cout << "METIS_OK" << endl;
408  cout << "objval: " << objval << endl;
409  }
410 
411  void SetPartitions(const vector<USI> b2g) const
412  {
413  if (!useMetis) return;
414  // bulk
415  OCP_USI n = 0;
416  for (n = 0; n < nb; n++) {
417  partitions[b2g[n]] = part[n];
418  }
419  // well
420  for (USI w = 0; w < nw; w++) {
421  partitions[ng + w] = part[n];
422  n++;
423  }
424  }
425  } metisTest;
426 #endif // USE_METIS
427 };
428 
430 // Note: The most commonly used is the summary file, which usually gives the
431 // information of bulks and wells in each time step, such as average pressure, oil
432 // production rate of wells. If other information at critical dates is of interest, you
433 // can chose the PRT file (TODO). Also, some infomation will be printed on the screen
434 // at the critical dates to make sure the program is at the right way.
436 {
437  friend class OpenCAEPoro;
438 
439 public:
440  void InputParam(const ParamOutput& paramOutput);
441  void Setup(const Reservoir& reservoir, const OCPControl& ctrl);
442  void SetVal(const Reservoir& reservoir, const OCPControl& ctrl);
443  void PrintInfo() const;
444  void PrintInfoSched(const Reservoir& rs,
445  const OCPControl& ctrl,
446  const OCP_DBL& time) const;
447  OCP_BOOL IfOutputVTK() const { return out4VTK.IfOutputVTK(); }
448 
449 private:
450  string workDir;
451  Summary summary;
452  CriticalInfo crtInfo;
453  Out4RPT out4RPT;
454  Out4VTK out4VTK;
455 
456  mutable OCP_DBL outputTime{0};
457 };
458 
459 #endif /* end if __OCPOUTPUT_HEADER__ */
460 
461 /*----------------------------------------------------------------------------*/
462 /* Brief Change History of This File */
463 /*----------------------------------------------------------------------------*/
464 /* Author Date Actions */
465 /*----------------------------------------------------------------------------*/
466 /* Shizhe Li Oct/01/2021 Create file */
467 /* Chensong Zhang Oct/15/2021 Format file */
468 /* Chensong Zhang Jan/08/2022 Update Doxygen */
469 /*----------------------------------------------------------------------------*/
unsigned int USI
Generic unsigned integer.
Definition: OCPConst.hpp:23
double OCP_DBL
Double precision.
Definition: OCPConst.hpp:27
unsigned int OCP_USI
Long unsigned integer.
Definition: OCPConst.hpp:25
unsigned int OCP_BOOL
OCP_BOOL in OCP.
Definition: OCPConst.hpp:29
OCPControl class declaration.
Output reservoir information in vtk format.
ParamOutput class declaration.
Reservoir class declaration.
#define OCP_ABORT(msg)
Abort if critical error happens.
Definition: UtilError.hpp:47
Supply basic tools used to output files.
Elapsed wall-time and CPU-cycles declaration.
vector< Well > wells
well set.
Definition: AllWells.hpp:174
USI GetWellPerfNum(const USI &i) const
Return the num of perforations of well i.
Definition: AllWells.hpp:147
USI numWell
num of wells.
Definition: AllWells.hpp:173
Basic grid properties for output.
Definition: OCPOutput.hpp:178
vector< USI > selfPtr
Self-pointer, the indices of the i-th bulk in neighbor[i]: numBulk.
Definition: BulkConn.hpp:116
vector< vector< OCP_USI > > neighbor
Neighboring information of each bulk: activeGridNum.
Definition: BulkConn.hpp:113
vector< USI > neighborNum
Number of neighbors of the i-th bulk: numBulk, self-included.
Definition: BulkConn.hpp:119
A structure of three-dimensional coordinates.
Definition: ParamOutput.hpp:24
Collect important information of each time step for fast review.
Definition: OCPOutput.hpp:155
All control parameters except for well controllers.
Definition: OCPControl.hpp:94
3D coordinate representation in OpenCAEPoro
Definition: OCPOutput.hpp:35
The OCPOutput class manages different kinds of ways to output information.
Definition: OCPOutput.hpp:436
TODO: Add Doxygen.
Definition: OCPOutput.hpp:61
vector< USI > index
Records the index of bulk or well, whose properties will be printed.
Definition: OCPOutput.hpp:78
Top-level data structure for the OpenCAEPoro simulator.
Definition: OCP.hpp:27
void InputParam(ParamRead &param)
Read input parameters to an internal structure.
Definition: OCP.cpp:24
Collect more detailed information of each time step.
Definition: OCPOutput.hpp:211
BulkConn conn
Bulk's connection info.
Definition: Reservoir.hpp:76
USI GetWellNum() const
Return the num of Well.
Definition: Reservoir.hpp:68
Grid grid
Init Grid info.
Definition: Reservoir.hpp:73
AllWells allWells
Wells class info.
Definition: Reservoir.hpp:75
OCP_USI GetBulkNum() const
Return the num of Bulk.
Definition: Reservoir.hpp:66
The SumItem class is an auxiliary structure storing summary data to output.
Definition: OCPOutput.hpp:83
The Summary class manages the output in the summary file.
Definition: OCPOutput.hpp:104
Used to store the contents of keyword whose contents are in form of string.
Definition: ParamOutput.hpp:46
Used to store the contents of keyword whose contents are in form of coordinates.
Definition: ParamOutput.hpp:38