OpenCAEPoro  v0.5.0
A simulator for multicomponent porous media flow
OCPControl.cpp
Go to the documentation of this file.
1 
12 #include "OCPControl.hpp"
13 
14 ControlTime::ControlTime(const vector<OCP_DBL>& src)
15 {
16  timeInit = src[0];
17  timeMax = src[1];
18  timeMin = src[2];
19  maxIncreFac = src[3];
20  minChopFac = src[4];
21  cutFacNR = src[5];
22 }
23 
24 ControlPreTime::ControlPreTime(const vector<OCP_DBL>& src)
25 {
26  dPlim = src[0];
27  dSlim = src[1];
28  dNlim = src[2];
29  eVlim = src[3];
30 }
31 
32 ControlNR::ControlNR(const vector<OCP_DBL>& src)
33 {
34  maxNRiter = src[0];
35  NRtol = src[1];
36  NRdPmax = src[2];
37  NRdSmax = src[3];
38  NRdPmin = src[4];
39  NRdSmin = src[5];
40  Verrmax = src[6];
41 }
42 
43 void FastControl::ReadParam(const USI& argc, const char* optset[])
44 {
45  activity = OCP_FALSE;
46  timeInit = timeMax = timeMin = -1.0;
47 
48  std::stringstream buffer;
49  string tmp;
50  string key;
51  string value;
52  for (USI n = 2; n < argc; n++) {
53  buffer << optset[n];
54  buffer >> tmp;
55 
56  string::size_type pos = tmp.find_last_of('=');
57  if (pos == string::npos) OCP_ABORT("Unknown Usage! See -h");
58 
59  key = tmp.substr(0, pos);
60  value = tmp.substr(pos + 1, tmp.size() - pos);
61 
62  switch (Map_Str2Int(&key[0], key.size())) {
63 
64  case Map_Str2Int("method", 6):
65  if (value == "FIM") {
66  method = FIM;
67  } else if (value == "FIMn") {
68  method = FIMn;
69  } else if (value == "IMPEC") {
70  method = IMPEC;
71  } else if (value == "AIMc") {
72  method = AIMc;
73  } else {
74  OCP_ABORT("Wrong method param in command line!");
75  }
76  activity = OCP_TRUE;
77  if (method == FIM || method == FIMn || method == AIMc) {
78  if (timeInit <= 0) timeInit = 0.1;
79  if (timeMax <= 0) timeMax = 10.0;
80  if (timeMin <= 0) timeMin = 0.1;
81  } else {
82  if (timeInit <= 0) timeInit = 0.1;
83  if (timeMax <= 0) timeMax = 1.0;
84  if (timeMin <= 0) timeMin = 0.1;
85  }
86  break;
87 
88  case Map_Str2Int("dtInit", 6):
89  timeInit = stod(value);
90  break;
91 
92  case Map_Str2Int("dtMin", 5):
93  timeMin = stod(value);
94  break;
95 
96  case Map_Str2Int("dtMax", 5):
97  timeMax = stod(value);
98  break;
99 
100  case Map_Str2Int("verbose", 7):
101  printLevel = MIN(MAX(stoi(value), PRINT_NONE), PRINT_ALL);
102  break;
103 
104  default:
105  OCP_ABORT("Unknown Options: " + key + " See -h");
106  break;
107  }
108 
109  buffer.clear();
110  }
111 
112  if (argc >= 6 && OCP_FALSE) {
113  activity = OCP_TRUE;
114  if (string(optset[2]) == "FIM") {
115  method = FIM;
116  } else if (string(optset[2]) == "FIMn") {
117  method = FIMn;
118  } else if (string(optset[2]) == "IMPEC") {
119  method = IMPEC;
120  } else if (string(optset[2]) == "AIMc") {
121  method = AIMc;
122  } else {
123  OCP_ABORT("Wrong method param in command line!");
124  }
125  timeInit = stod(optset[3]);
126  timeMax = stod(optset[4]);
127  timeMin = stod(optset[5]);
128  if (argc >= 7) {
129  printLevel = stoi(optset[6]);
130  }
131  }
132 }
133 
134 void OCPControl::InputParam(const ParamControl& CtrlParam)
135 {
136  model = CtrlParam.model;
137  workDir = CtrlParam.dir;
138  if (CtrlParam.method == "IMPEC") {
139  method = IMPEC;
140  } else if (CtrlParam.method == "FIM") {
141  method = FIM;
142  } else if (CtrlParam.method == "FIMn") {
143  method = FIMn;
144  } else if (CtrlParam.method == "AIMc") {
145  method = AIMc;
146  } else {
147  OCP_ABORT("Wrong method specified!");
148  }
149 
150  linearSolverFile = CtrlParam.linearSolve;
151  criticalTime = CtrlParam.criticalTime;
152 
153  USI t = CtrlParam.criticalTime.size();
154  ctrlTimeSet.resize(t);
155  ctrlPreTimeSet.resize(t);
156  ctrlNRSet.resize(t);
157 
158  USI n = CtrlParam.tuning_T.size();
159  vector<USI> ctrlCriticalTime(n + 1);
160  for (USI i = 0; i < n; i++) {
161  ctrlCriticalTime[i] = CtrlParam.tuning_T[i].d;
162  }
163  ctrlCriticalTime.back() = t;
164  for (USI i = 0; i < n; i++) {
165  for (USI d = ctrlCriticalTime[i]; d < ctrlCriticalTime[i + 1]; d++) {
166  ctrlTimeSet[d] = ControlTime(CtrlParam.tuning_T[i].Tuning[0]);
167  ctrlPreTimeSet[d] = ControlPreTime(CtrlParam.tuning_T[i].Tuning[1]);
168  ctrlNRSet[d] = ControlNR(CtrlParam.tuning_T[i].Tuning[2]);
169  }
170  }
171 }
172 
173 void OCPControl::ApplyControl(const USI& i, const Reservoir& rs)
174 {
175  ctrlTime = ctrlTimeSet[i];
176  ctrlPreTime = ctrlPreTimeSet[i];
177  ctrlNR = ctrlNRSet[i];
178  end_time = criticalTime[i + 1];
179  wellChange = rs.allWells.GetWellChange();
180  InitTime(i);
181 }
182 
183 void OCPControl::InitTime(const USI& i)
184 {
185  OCP_DBL dt = criticalTime[i + 1] - current_time;
186  if (dt <= 0) OCP_ABORT("Non-positive time stepsize!");
187 
188  static OCP_BOOL firstflag = OCP_TRUE;
189  if (wellChange || firstflag) {
190  current_dt = min(dt, ctrlTime.timeInit);
191  firstflag = OCP_FALSE;
192  } else {
193  current_dt = min(dt, init_dt);
194  }
195 }
196 
197 void OCPControl::SetupFastControl(const USI& argc, const char* optset[])
198 {
199  ctrlFast.ReadParam(argc, optset);
200  if (ctrlFast.activity) {
201  method = ctrlFast.method;
202  switch (method) {
203  case IMPEC:
204  linearSolverFile = "./csr.fasp";
205  break;
206  case AIMc:
207  case FIM:
208  case FIMn:
209  linearSolverFile = "./bsr.fasp";
210  break;
211  default:
212  OCP_ABORT("Wrong method specified from command line!");
213  break;
214  }
215  USI n = ctrlTimeSet.size();
216  for (USI i = 0; i < n; i++) {
217  ctrlTimeSet[i].timeInit = ctrlFast.timeInit;
218  ctrlTimeSet[i].timeMax = ctrlFast.timeMax;
219  ctrlTimeSet[i].timeMin = ctrlFast.timeMin;
220  }
221  }
222  printLevel = ctrlFast.printLevel;
223 }
224 
226 {
227  numTstep += 1;
228  iterNR_total += iterNR;
229  iterLS_total += iterLS;
230  iterNR = 0;
231  iterLS = 0;
232 }
233 
235 {
236  wastedIterNR += iterNR;
237  iterNR = 0;
238  wastedIterLS += iterLS;
239  iterLS = 0;
240 }
241 
242 OCP_BOOL OCPControl::Check(Reservoir& rs, initializer_list<string> il)
243 {
244  OCP_INT flag;
245  for (auto& s : il) {
246 
247  if (s == "BulkP")
248  flag = rs.bulk.CheckP();
249  else if (s == "BulkT")
250  flag = rs.bulk.CheckT();
251  else if (s == "BulkNi")
252  flag = rs.bulk.CheckNi();
253  else if (s == "BulkVe")
254  flag = rs.bulk.CheckVe(0.01);
255  else if (s == "CFL")
256  flag = rs.bulk.CheckCFL(1.0);
257  else if (s == "WellP")
258  flag = rs.allWells.CheckP(rs.bulk);
259  else
260  OCP_ABORT("Check iterm not recognized!");
261 
262  switch (flag) {
263  // Bulk
264  case BULK_SUCCESS:
265  break;
266  case BULK_NEGATIVE_PRESSURE:
267  case BULK_NEGATIVE_TEMPERATURE:
268  case BULK_NEGATIVE_COMPONENTS_MOLES:
269  case BULK_OUTRANGED_VOLUME_ERROR:
270  current_dt *= ctrlTime.cutFacNR;
271  return OCP_FALSE;
272  case BULK_OUTRANGED_CFL:
273  current_dt /= (rs.bulk.GetMaxCFL() + 1);
274  return OCP_FALSE;
275  // Well
276  case WELL_SUCCESS:
277  break;
278  case WELL_NEGATIVE_PRESSURE:
279  current_dt *= ctrlTime.cutFacNR;
280  return OCP_FALSE;
281  case WELL_SWITCH_TO_BHPMODE:
282  case WELL_CROSSFLOW:
283  return OCP_FALSE;
284  default:
285  break;
286  }
287  }
288 
289  return OCP_TRUE;
290 }
291 
292 void OCPControl::CalNextTimeStep(Reservoir& rs, initializer_list<string> il)
293 {
294  last_dt = current_dt;
295  current_time += current_dt;
296 
297  OCP_DBL factor = ctrlTime.maxIncreFac;
298 
299  const OCP_DBL dPmax = max(rs.bulk.GetdPmax(), rs.allWells.GetdBHPmax());
300  const OCP_DBL dTmax = rs.bulk.GetdTmax();
301  const OCP_DBL dNmax = rs.bulk.GetdNmax();
302  const OCP_DBL dSmax = rs.bulk.GetdSmax();
303  const OCP_DBL eVmax = rs.bulk.GeteVmax();
304 
305  for (auto& s : il) {
306  if (s == "dP") {
307  if (dPmax > TINY) factor = min(factor, ctrlPreTime.dPlim / dPmax);
308  } else if (s == "dT") {
309  // no input now -- no value
310  if (dTmax > TINY) factor = min(factor, ctrlPreTime.dTlim / dTmax);
311  } else if (s == "dN") {
312  if (dNmax > TINY) factor = min(factor, ctrlPreTime.dNlim / dNmax);
313  } else if (s == "dS") {
314  if (dSmax > TINY) factor = min(factor, ctrlPreTime.dSlim / dSmax);
315  } else if (s == "eV") {
316  if (eVmax > TINY) factor = min(factor, ctrlPreTime.eVlim / eVmax);
317  } else if (s == "iter") {
318  if (iterNR < 5)
319  factor = min(factor, 2.0);
320  else if (iterNR > 10)
321  factor = min(factor, 0.5);
322  else
323  factor = min(factor, 1.5);
324  }
325  }
326 
327  factor = max(ctrlTime.minChopFac, factor);
328 
329  current_dt *= factor;
330  if (current_dt > ctrlTime.timeMax) current_dt = ctrlTime.timeMax;
331  if (current_dt < ctrlTime.timeMin) current_dt = ctrlTime.timeMin;
332 
333  init_dt = current_dt;
334 
335  const OCP_DBL dt = end_time - current_time;
336  if (current_dt > dt) current_dt = dt;
337 }
338 
339 /*----------------------------------------------------------------------------*/
340 /* Brief Change History of This File */
341 /*----------------------------------------------------------------------------*/
342 /* Author Date Actions */
343 /*----------------------------------------------------------------------------*/
344 /* Shizhe Li Oct/01/2021 Create file */
345 /* Chensong Zhang Oct/15/2021 Format file */
346 /*----------------------------------------------------------------------------*/
const OCP_DBL TINY
Small constant.
Definition: OCPConst.hpp:38
unsigned int USI
Generic unsigned integer.
Definition: OCPConst.hpp:23
double OCP_DBL
Double precision.
Definition: OCPConst.hpp:27
const USI FIMn
Solution method = FIM.
Definition: OCPConst.hpp:84
const USI FIM
Solution method = FIM.
Definition: OCPConst.hpp:82
const USI AIMc
Adaptive implicit -— Collins.
Definition: OCPConst.hpp:83
const USI IMPEC
Solution method = IMPEC.
Definition: OCPConst.hpp:81
int OCP_INT
Long integer.
Definition: OCPConst.hpp:26
unsigned int OCP_BOOL
OCP_BOOL in OCP.
Definition: OCPConst.hpp:29
OCPControl class declaration.
#define OCP_ABORT(msg)
Abort if critical error happens.
Definition: UtilError.hpp:47
constexpr long long Map_Str2Int(const char *mystr, const USI &len)
Definition: UtilInput.hpp:34
OCP_INT CheckP(const Bulk &myBulk)
Check if unreasonable well pressure or perforation pressure occurs.
Definition: AllWells.cpp:336
OCP_DBL GeteVmax() const
Return eVmax.
Definition: Bulk.hpp:453
OCP_INT CheckNi()
Check if negative Ni occurs.
Definition: Bulk.cpp:1285
OCP_INT CheckT() const
Check if negative T occurs.
Definition: Bulk.cpp:1268
OCP_DBL GetMaxCFL() const
Return maxCFL.
Definition: Bulk.hpp:455
OCP_DBL GetdSmax() const
Return dSmax.
Definition: Bulk.hpp:451
OCP_INT CheckP() const
Check if negative P occurs.
Definition: Bulk.cpp:1250
OCP_DBL GetdNmax() const
Return dNmax.
Definition: Bulk.hpp:449
OCP_DBL GetdPmax() const
Return dPmax.
Definition: Bulk.hpp:445
OCP_INT CheckVe(const OCP_DBL &Vlim) const
Check if relative volume error is outranged.
Definition: Bulk.cpp:1311
OCP_DBL GetdTmax() const
Return dTmax.
Definition: Bulk.hpp:447
OCP_INT CheckCFL(const OCP_DBL &cflLim) const
Check if Cfl is outranged.
Definition: Bulk.cpp:1327
Params for Newton iterations and linear iterations.
Definition: OCPControl.hpp:60
OCP_DBL NRtol
Maximum non-linear convergence error.
Definition: OCPControl.hpp:68
OCP_DBL NRdSmin
Minimum Saturation change in a Newton iteration.
Definition: OCPControl.hpp:72
OCP_DBL NRdPmax
Maximum Pressure change in a Newton iteration.
Definition: OCPControl.hpp:69
USI maxNRiter
Maximum number of Newton iterations in a time step.
Definition: OCPControl.hpp:67
OCP_DBL NRdSmax
Maximum Saturation change in a Newton iteration.
Definition: OCPControl.hpp:70
OCP_DBL Verrmax
Maximum Verr (vol error b/w fluid and pore) in a Newton step.
Definition: OCPControl.hpp:73
OCP_DBL NRdPmin
Minimum Pressure change in a Newton iteration.
Definition: OCPControl.hpp:71
Params for convergence and material balance error checks.
Definition: OCPControl.hpp:44
OCP_DBL dSlim
Ideal max Saturation change.
Definition: OCPControl.hpp:53
OCP_DBL eVlim
Ideal max relative Verr (pore - fluid) change.
Definition: OCPControl.hpp:55
OCP_DBL dPlim
Ideal max Pressure change.
Definition: OCPControl.hpp:51
OCP_DBL dNlim
Ideal max relative Ni (moles of components) change.
Definition: OCPControl.hpp:54
OCP_DBL dTlim
Ideal max Temperature change.
Definition: OCPControl.hpp:52
Params for choosing time stepsize in time marching.
Definition: OCPControl.hpp:27
OCP_DBL cutFacNR
Factor by which time step is cut after convergence failure.
Definition: OCPControl.hpp:39
OCP_DBL timeMax
Max time step during running.
Definition: OCPControl.hpp:35
OCP_DBL timeInit
Max init step length of next time step.
Definition: OCPControl.hpp:34
OCP_DBL timeMin
Min time step during running.
Definition: OCPControl.hpp:36
OCP_DBL minChopFac
Min choppable factor.
Definition: OCPControl.hpp:38
OCP_DBL maxIncreFac
Max increase factor.
Definition: OCPControl.hpp:37
USI method
IMPEC or FIM.
Definition: OCPControl.hpp:84
USI printLevel
Decide the depth for printing.
Definition: OCPControl.hpp:88
OCP_DBL timeMax
Maximum time step during running.
Definition: OCPControl.hpp:86
OCP_DBL timeMin
Minimum time step during running.
Definition: OCPControl.hpp:87
OCP_DBL timeInit
Maximum Init step length of next time step.
Definition: OCPControl.hpp:85
void ApplyControl(const USI &i, const Reservoir &rs)
Apply control for time step i.
Definition: OCPControl.cpp:173
void SetupFastControl(const USI &argc, const char *optset[])
Setup fast Control.
Definition: OCPControl.cpp:197
void InputParam(const ParamControl &CtrlParam)
Input parameters for control.
Definition: OCPControl.cpp:134
void UpdateIters()
Update the number of iterations.
Definition: OCPControl.cpp:225
void ResetIterNRLS()
Reset the number of iterations.
Definition: OCPControl.cpp:234
void InitTime(const USI &i)
Initialize time step i.
Definition: OCPControl.cpp:183
vector< OCP_DBL > criticalTime
USI model
model: thermal or isothermal.
string method
Discretization method for fluid equations.
string dir
Current work directory.
string linearSolve
Fasp file.
vector< TuningPair > tuning_T
Tuning set.
Bulk bulk
Active grid info.
Definition: Reservoir.hpp:74
AllWells allWells
Wells class info.
Definition: Reservoir.hpp:75