OpenCAEPoro  0.2.0 Sep/22/2022
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  dVlim = 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 = 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  OCP_INT pos = tmp.find_last_of('=');
57 
58  if (pos == string::npos) OCP_ABORT("Unknown Usage! See -h");
59 
60  key = tmp.substr(0, pos);
61  value = tmp.substr(pos + 1, tmp.size() - pos);
62 
63  switch (Map_Str2Int(&key[0],key.size()))
64  {
65 
66  case Map_Str2Int("method",6):
67  if (value == "FIM") {
68  method = FIM;
69  } else if (value == "FIMn") {
70  method = FIMn;
71  } else if (value == "IMPEC") {
72  method = IMPEC;
73  } else if (value == "AIMc") {
74  method = AIMc;
75  } else if (value == "AIMs") {
76  method = AIMs;
77  } else if (value == "AIMt") {
78  method = AIMt;
79  } else {
80  OCP_ABORT("Wrong method param in command line!");
81  }
82  activity = true;
83  if (method == FIM || method == FIMn || method == AIMc) {
84  if (timeInit <= 0) timeInit = 0.1;
85  if (timeMax <= 0) timeMax = 10.0;
86  if (timeMin <= 0) timeMin = 0.1;
87  } else {
88  if (timeInit <= 0) timeInit = 0.1;
89  if (timeMax <= 0) timeMax = 1.0;
90  if (timeMin <= 0) timeMin = 0.1;
91  }
92  break;
93 
94  case Map_Str2Int("dtInit", 6):
95  timeInit = stod(value);
96  break;
97 
98  case Map_Str2Int("dtMin", 5):
99  timeMin = stod(value);
100  break;
101 
102  case Map_Str2Int("dtMax", 5):
103  timeMax = stod(value);
104  break;
105 
106  case Map_Str2Int("pl", 2):
107  printLevel = stoi(value);
108  break;
109 
110  default:
111  OCP_ABORT("Unknown Options: " + key + " See -h");
112  break;
113  }
114 
115  buffer.clear();
116  }
117 
118 
119 
120 
121 
122 
123  if (argc >= 6 && false) {
124  activity = true;
125  if (string(optset[2]) == "FIM") {
126  method = FIM;
127  } else if (string(optset[2]) == "FIMn") {
128  method = FIMn;
129  } else if (string(optset[2]) == "IMPEC") {
130  method = IMPEC;
131  } else if (string(optset[2]) == "AIMc") {
132  method = AIMc;
133  } else if (string(optset[2]) == "AIMs") {
134  method = AIMs;
135  } else if (string(optset[2]) == "AIMt") {
136  method = AIMt;
137  }else {
138  OCP_ABORT("Wrong method param in command line!");
139  }
140  timeInit = stod(optset[3]);
141  timeMax = stod(optset[4]);
142  timeMin = stod(optset[5]);
143  if (argc >= 7) {
144  printLevel = stoi(optset[6]);
145  }
146  }
147 }
148 
149 void OCPControl::InputParam(const ParamControl& CtrlParam)
150 {
151  workDir = CtrlParam.dir;
152  if (CtrlParam.method == "IMPEC") {
153  method = IMPEC;
154  } else if (CtrlParam.method == "FIM") {
155  method = FIM;
156  } else if (CtrlParam.method == "FIMn") {
157  method = FIMn;
158  } else if (CtrlParam.method == "AIMc") {
159  method = AIMc;
160  } else if (CtrlParam.method == "AIMs") {
161  method = AIMs;
162  } else if (CtrlParam.method == "AIMt") {
163  method = AIMt;
164  }else {
165  OCP_ABORT("Wrong method specified!");
166  }
167 
168  linearsolveFile = CtrlParam.linearSolve;
169  criticalTime = CtrlParam.criticalTime;
170 
171  USI t = CtrlParam.criticalTime.size();
172  ctrlTimeSet.resize(t);
173  ctrlPreTimeSet.resize(t);
174  ctrlNRSet.resize(t);
175 
176  USI n = CtrlParam.tuning_T.size();
177  vector<USI> ctrlCriticalTime(n + 1);
178  for (USI i = 0; i < n; i++) {
179  ctrlCriticalTime[i] = CtrlParam.tuning_T[i].d;
180  }
181  ctrlCriticalTime.back() = t;
182  for (USI i = 0; i < n; i++) {
183  for (USI d = ctrlCriticalTime[i]; d < ctrlCriticalTime[i + 1]; d++) {
184  ctrlTimeSet[d] = ControlTime(CtrlParam.tuning_T[i].Tuning[0]);
185  ctrlPreTimeSet[d] = ControlPreTime(CtrlParam.tuning_T[i].Tuning[1]);
186  ctrlNRSet[d] = ControlNR(CtrlParam.tuning_T[i].Tuning[2]);
187  }
188  }
189 }
190 
191 void OCPControl::ApplyControl(const USI& i, const Reservoir& rs)
192 {
193  ctrlTime = ctrlTimeSet[i];
194  ctrlPreTime = ctrlPreTimeSet[i];
195  ctrlNR = ctrlNRSet[i];
196  end_time = criticalTime[i + 1];
197  wellChange = rs.allWells.GetWellChange();
198  InitTime(i);
199 }
200 
201 void OCPControl::InitTime(const USI& i)
202 {
203  OCP_DBL dt = criticalTime[i + 1] - current_time;
204  if (dt <= 0) OCP_ABORT("Non-positive time stepsize!");
205 
206  static bool firstflag = true;
207  if (wellChange || firstflag) {
208  current_dt = min(dt, ctrlTime.timeInit);
209  firstflag = false;
210  }
211  else {
212  current_dt = min(dt, init_dt);
213  }
214 
215 }
216 
217 void OCPControl::SetupFastControl(const USI& argc, const char* optset[])
218 {
219  ctrlFast.ReadParam(argc, optset);
220  if (ctrlFast.activity) {
221  method = ctrlFast.method;
222  switch (method) {
223  case IMPEC:
224  case AIMt:
225  linearsolveFile = "./csr.fasp";
226  break;
227  case AIMs:
228  case AIMc:
229  case FIM:
230  case FIMn:
231  linearsolveFile = "./bsr.fasp";
232  break;
233  default:
234  OCP_ABORT("Wrong method in command line!");
235  break;
236  }
237  USI n = ctrlTimeSet.size();
238  for (USI i = 0; i < n; i++) {
239  ctrlTimeSet[i].timeInit = ctrlFast.timeInit;
240  ctrlTimeSet[i].timeMax = ctrlFast.timeMax;
241  ctrlTimeSet[i].timeMin = ctrlFast.timeMin;
242  }
243  printLevel = ctrlFast.printLevel;
244  }
245 }
246 
248 {
249  last_dt = current_dt;
250  current_time += current_dt;
251 
252  OCP_DBL c1, c2, c3, c4, c;
253  c1 = c2 = c3 = c4 = 10;
254 
255  const OCP_DBL dPmax = reservoir.bulk.GetdPmax();
256  const OCP_DBL dNmax = reservoir.bulk.GetdNmax();
257  const OCP_DBL dSmax = reservoir.bulk.GetdSmax();
258  const OCP_DBL dVmax = reservoir.bulk.GetdVmax();
259 
260  //cout << dPmax << " " << dSmax << endl;
261 
262  if (dPmax > TINY) c1 = ctrlPreTime.dPlim / dPmax;
263  if (dSmax > TINY) c2 = ctrlPreTime.dSlim / dSmax;
264  if (dNmax > TINY) c3 = ctrlPreTime.dNlim / dNmax;
265  if (dVmax > TINY) c4 = ctrlPreTime.dVlim / dVmax;
266 
267  c = min(min(c1, c2), min(c3, c4));
268  c = max(ctrlTime.minChopFac, c);
269  c = min(ctrlTime.maxIncreFac, c);
270 
271  current_dt *= c;
272 
273  if (current_dt > ctrlTime.timeMax) current_dt = ctrlTime.timeMax;
274  if (current_dt < ctrlTime.timeMin) current_dt = ctrlTime.timeMin;
275 
276  init_dt = current_dt;
277 
278  OCP_DBL dt = end_time - current_time;
279  if (current_dt > dt) current_dt = dt;
280 
281 
282  // cout << "FactorT: " << c << " Next dt: " << dt << endl;
283 }
284 
285 void OCPControl::CalNextTstepFIM(const Reservoir& reservoir)
286 {
287  last_dt = current_dt;
288  current_time += current_dt;
289 
290  OCP_DBL c1, c2, c;
291  c1 = c2 = 10;
292 
293  const OCP_DBL dPmaxB = reservoir.bulk.GetdPmax();
294  const OCP_DBL dPmaxW = reservoir.allWells.GetdBHPmax();
295  const OCP_DBL dPmax = max(dPmaxB, dPmaxW);
296  const OCP_DBL dSmax = reservoir.bulk.GetdSmax();
297 
298  if (dPmax > TINY) c1 = ctrlPreTime.dPlim / dPmax;
299  if (dSmax > TINY) c2 = ctrlPreTime.dSlim / dSmax;
300 
301  OCP_DBL c3 = 1.5;
302 
303  if (iterNR < 30) { // temp
304  c3 = 2;
305  } else if (iterNR > 8) {
306  c3 = 0.5;
307  }
308 
309  c = min(min(c1, c2), c3);
310  c = max(ctrlTime.minChopFac, c);
311  c = min(ctrlTime.maxIncreFac, c);
312 
313  current_dt *= c;
314  if (current_dt > ctrlTime.timeMax) current_dt = ctrlTime.timeMax;
315  if (current_dt < ctrlTime.timeMin) current_dt = ctrlTime.timeMin;
316 
317  init_dt = current_dt;
318 
319  const OCP_DBL dt = end_time - current_time;
320  if (current_dt > dt) current_dt = dt;
321 
322 }
323 
325 {
326  numTstep += 1;
327  iterNR_total += iterNR;
328  iterLS_total += iterLS;
329  iterNR = 0;
330  iterLS = 0;
331 }
332 
334 {
335  wastedIterNR += iterNR;
336  iterNR = 0;
337  wastedIterLS += iterLS;
338  iterLS = 0;
339 }
340 
341 /*----------------------------------------------------------------------------*/
342 /* Brief Change History of This File */
343 /*----------------------------------------------------------------------------*/
344 /* Author Date Actions */
345 /*----------------------------------------------------------------------------*/
346 /* Shizhe Li Oct/01/2021 Create file */
347 /* Chensong Zhang Oct/15/2021 Format file */
348 /*----------------------------------------------------------------------------*/
const USI AIMs
Adaptive implicit.
Definition: OCPConst.hpp:72
const OCP_DBL TINY
Small constant.
Definition: OCPConst.hpp:36
const USI AIMt
improved version of IMPEC, loacl FIM after IMPEC
Definition: OCPConst.hpp:73
unsigned int USI
Generic unsigned integer.
Definition: OCPConst.hpp:22
double OCP_DBL
Double precision.
Definition: OCPConst.hpp:26
const USI FIMn
Solution method = FIM.
Definition: OCPConst.hpp:75
const USI FIM
Solution method = FIM.
Definition: OCPConst.hpp:71
const USI AIMc
Adaptive implicit -— Collins.
Definition: OCPConst.hpp:74
const USI IMPEC
Solution method = IMPEC.
Definition: OCPConst.hpp:70
int OCP_INT
Long integer.
Definition: OCPConst.hpp:25
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_DBL GetdVmax() const
Return dVmax.
Definition: Bulk.hpp:178
OCP_DBL GetdSmax() const
Return dSmax.
Definition: Bulk.hpp:176
OCP_DBL GetdNmax() const
Return dNmax.
Definition: Bulk.hpp:174
OCP_DBL GetdPmax() const
Return dPmax.
Definition: Bulk.hpp:172
Params for Newton iterations and linear iterations.
Definition: OCPControl.hpp:59
OCP_DBL NRtol
Maximum non-linear convergence error.
Definition: OCPControl.hpp:67
OCP_DBL NRdSmin
Minimum Saturation change in a Newton iteration.
Definition: OCPControl.hpp:71
OCP_DBL NRdPmax
Maximum Pressure change in a Newton iteration.
Definition: OCPControl.hpp:68
USI maxNRiter
Maximum number of Newton iterations in a timestep.
Definition: OCPControl.hpp:66
OCP_DBL NRdSmax
Maximum Saturation change in a Newton iteration.
Definition: OCPControl.hpp:69
OCP_DBL Verrmax
Definition: OCPControl.hpp:72
OCP_DBL NRdPmin
Minimum Pressure change in a Newton iteration.
Definition: OCPControl.hpp:70
Params for convergence and material balance error checks.
Definition: OCPControl.hpp:44
OCP_DBL dVlim
Ideal max relative Verr (pore - fluid) change.
Definition: OCPControl.hpp:54
OCP_DBL dSlim
Ideal max Saturation change.
Definition: OCPControl.hpp:52
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:53
Params for choosing time stepsize in time marching.
Definition: OCPControl.hpp:27
OCP_DBL cutFacNR
Factor by which timestep 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 timestep.
Definition: OCPControl.hpp:34
OCP_DBL timeMin
Min time step during running.
Definition: OCPControl.hpp:36
OCP_DBL minChopFac
Min choppable timestep.
Definition: OCPControl.hpp:38
OCP_DBL maxIncreFac
Max timestep increase factor.
Definition: OCPControl.hpp:37
USI method
IMPEC or FIM.
Definition: OCPControl.hpp:84
USI printLevel
Decide the depth for printfing.
Definition: OCPControl.hpp:88
OCP_DBL timeMax
Maximum time step during running.
Definition: OCPControl.hpp:86
OCP_DBL timeMin
Minmum time step during running.
Definition: OCPControl.hpp:87
OCP_DBL timeInit
Maximum Init step length of next timestep.
Definition: OCPControl.hpp:85
void ApplyControl(const USI &i, const Reservoir &rs)
Apply control for time step i.
Definition: OCPControl.cpp:191
void SetupFastControl(const USI &argc, const char *optset[])
Setup fast Control.
Definition: OCPControl.cpp:217
void CalNextTstepIMPEC(const Reservoir &reservoir)
Calculate the next time step according to max change of some variables.
Definition: OCPControl.cpp:247
void InputParam(const ParamControl &CtrlParam)
Input parameters for control.
Definition: OCPControl.cpp:149
void UpdateIters()
Update the number of iterations.
Definition: OCPControl.cpp:324
void ResetIterNRLS()
Reset the number of iterations.
Definition: OCPControl.cpp:333
void InitTime(const USI &i)
Initialize time step i.
Definition: OCPControl.cpp:201
vector< OCP_DBL > criticalTime
string method
Decide which method to use to discrete the fluid equations.
string dir
Current work directory.
string linearSolve
Fasp file.
vector< TuningPair > tuning_T
Tuning set.