18 void IsothermalMethod::InitRock(
Bulk& bk)
const
25 void IsothermalMethod::CalRock(
Bulk& bk)
const
41 AllocateReservoir(rs);
43 AllocateLinearSystem(ls, rs, ctrl);
61 UpdateLastTimeStep(rs);
68 ctrl.Check(rs, {
"CFL"});
75 AssembleMatBulks(ls, rs, dt);
76 AssembleMatWells(ls, rs, dt);
93 int status = ls.
Solve();
116 if (!ctrl.Check(rs, {
"BulkP",
"WellP"})) {
125 if (!ctrl.Check(rs, {
"CFL"})) {
126 ResetToLastTimeStep01(rs, ctrl);
127 cout <<
"CFL is too big" << endl;
131 MassConserve(rs, dt);
134 if (!ctrl.Check(rs, {
"BulkNi"})) {
135 ResetToLastTimeStep02(rs, ctrl);
143 if (!ctrl.Check(rs, {
"BulkVe"})) {
144 ResetToLastTimeStep03(rs, ctrl);
160 UpdateLastTimeStep(rs);
162 ctrl.CalNextTimeStep(rs, {
"dP",
"dN",
"dS",
"eV"});
165 void IsoT_IMPEC::AllocateReservoir(
Reservoir& rs)
186 bk.
Ni.resize(nb * nc);
191 bk.
Pj.resize(nb * np);
192 bk.
Pc.resize(nb * np);
194 bk.
S.resize(nb * np);
195 bk.
vj.resize(nb * np);
196 bk.
xij.resize(nb * np * nc);
197 bk.
rho.resize(nb * np);
198 bk.
xi.resize(nb * np);
199 bk.
mu.resize(nb * np);
200 bk.
kr.resize(nb * np);
204 bk.
lNi.resize(nb * nc);
208 bk.
lPj.resize(nb * np);
209 bk.
lPc.resize(nb * np);
211 bk.
lS.resize(nb * np);
212 bk.
vj.resize(nb * np);
213 bk.
lxij.resize(nb * np * nc);
214 bk.
lrho.resize(nb * np);
215 bk.
lxi.resize(nb * np);
216 bk.
lmu.resize(nb * np);
217 bk.
lkr.resize(nb * np);
221 bk.
vfi.resize(nb * nc);
224 bk.
lvfi.resize(nb * nc);
227 bk.
cfl.resize(nb * np);
264 void IsoT_IMPEC::CalFlash(
Bulk& bk)
286 for (
USI j = 0; j < np; j++) {
292 bk.
S[bIdp + j] = bk.
flashCal[pvtnum]->GetS(j);
295 for (
USI i = 0; i < nc; i++) {
296 bk.
xij[bIdp * nc + j * nc + i] = bk.
flashCal[pvtnum]->GetXij(j, i);
298 bk.
vj[bIdp + j] = bk.
flashCal[pvtnum]->GetVj(j);
300 bk.
xi[bIdp + j] = bk.
flashCal[pvtnum]->GetXi(j);
301 bk.
mu[bIdp + j] = bk.
flashCal[pvtnum]->GetMu(j);
306 for (
USI i = 0; i < nc; i++) {
307 bk.
vfi[n * nc + i] = bk.
flashCal[pvtnum]->GetVfi(i);
315 bk.
flow[bk.
SATNUM[n]]->CalKrPc(&bk.
S[bId], &bk.
kr[bId], &bk.
Pc[bId], n);
321 void IsoT_IMPEC::CalFlux(
Reservoir& rs)
const
327 void IsoT_IMPEC::CalBulkFlux(
Reservoir& rs)
const
344 for (
USI j = 0; j < np; j++) {
345 bId_np_j = bId * np + j;
346 eId_np_j = eId * np + j;
351 if ((exbegin) && (exend)) {
352 rho = (bk.
rho[bId_np_j] + bk.
rho[eId_np_j]) / 2;
353 }
else if (exbegin && (!exend)) {
354 rho = bk.
rho[bId_np_j];
355 }
else if ((!exbegin) && (exend)) {
356 rho = bk.
rho[eId_np_j];
358 conn.
upblock[c * np + j] = bId;
373 conn.
upblock[c * np + j] = uId;
377 Akd * bk.
kr[uId * np + j] / bk.
mu[uId * np + j];
405 for (
USI j = 0; j < np; j++) {
406 uId = conn.
upblock[c * np + j];
407 uId_np_j = uId * np + j;
412 for (
USI i = 0; i < nc; i++) {
413 dNi = dt * phaseVelocity * bk.
xi[uId_np_j] * bk.
xij[uId_np_j * nc + i];
414 bk.
Ni[eId * nc + i] += dNi;
415 bk.
Ni[bId * nc + i] -= dNi;
423 for (
USI p = 0; p < wl.PerfNum(); p++) {
424 OCP_USI k = wl.PerfLocation(p);
425 for (
USI i = 0; i < nc; i++) {
426 bk.
Ni[k * nc + i] -= wl.PerfQi_lbmol(p, i) * dt;
448 for (
OCP_USI n = 0; n < nb; n++) {
452 Vpp = bk.
v[n] * bk.
poroP[n];
456 ls.
AddRhs(n, (Vpp - vfP) * P + dt * (vf - Vp));
461 OCP_DBL valupi, valdowni, valup, rhsup, valdown, rhsdown;
475 for (
USI j = 0; j < np; j++) {
476 uId_np_j = conn.
upblock[c * np + j] * np + j;
482 for (
USI i = 0; i < nc; i++) {
483 valupi += bk.
vfi[bId * nc + i] * bk.
xij[uId_np_j * nc + i];
484 valdowni += bk.
vfi[eId * nc + i] * bk.
xij[uId_np_j * nc + i];
488 valup += tmp * valupi;
489 valdown += tmp * valdowni;
491 (bk.
Pc[bId * np + j] - bk.
Pc[eId * np + j]);
492 rhsup += tmp * valupi;
493 rhsdown -= tmp * valdowni;
510 switch (wl.WellType()) {
512 AssembleMatInjWells(ls, rs.
bulk, wl, dt);
515 AssembleMatProdWells(ls, rs.
bulk, wl, dt);
544 OCP_DBL Vfi_zi, valb, valw, bb, bw;
548 for (
USI p = 0; p < wl.PerfNum(); p++) {
549 const OCP_USI n = wl.PerfLocation(p);
552 for (
USI i = 0; i < nc; i++) {
553 Vfi_zi += bk.
vfi[n * nc + i] * wl.InjZi(i);
556 valw = dt * wl.PerfXi(p) * wl.PerfTransInj(p);
557 bw = valw * wl.DG(p);
558 valb = valw * Vfi_zi;
559 bb = valb * wl.DG(p);
567 switch (wl.OptMode()) {
586 switch (wl.OptMode()) {
592 ls.
AddRhs(wId, dt * wl.MaxRate());
596 ls.
AddRhs(wId, dt * wl.MaxBHP());
619 for (
USI p = 0; p < wl.PerfNum(); p++) {
620 const OCP_USI n = wl.PerfLocation(p);
627 for (
USI j = 0; j < np; j++) {
633 for (
USI i = 0; i < nc; i++) {
634 tempb += bk.
vfi[n * nc + i] * bk.
xij[n * np * nc + j * nc + i];
635 tempw += wl.ProdWeight(i) * bk.
xij[n * np * nc + j * nc + i];
637 OCP_DBL trans = dt * wl.PerfTransj(p, j) * bk.
xi[n * np + j];
638 valb += tempb * trans;
639 valw += tempw * trans;
641 OCP_DBL dP = wl.DG(p) - bk.
Pc[n * np + j];
642 bb += tempb * trans * dP;
643 bw += tempw * trans * dP;
652 switch (wl.OptMode()) {
671 switch (wl.OptMode()) {
677 ls.
AddRhs(wId, dt * wl.MaxRate());
681 ls.
AddRhs(wId, dt * wl.MinBHP());
689 void IsoT_IMPEC::GetSolution(
Reservoir& rs,
const vector<OCP_DBL>& u)
696 for (
OCP_USI n = 0; n < nb; n++) {
698 for (
USI j = 0; j < np; j++) {
699 bk.
Pj[n * np + j] = bk.
P[n] + bk.
Pc[n * np + j];
782 void IsoT_IMPEC::UpdateLastTimeStep(
Reservoir& rs)
const
820 rs.
allWells.UpdateLastTimeStepBHP();
866 AssembleMatBulks(ls, rs, dt);
870 AssembleMatBulksNew(ls, rs, dt);
871 AssembleMatWellsNew(ls, rs, dt);
891 int status = ls.
Solve();
918 if (!ctrl.Check(rs, {
"BulkNi",
"BulkP"})) {
920 cout <<
"Cut time step size and repeat! current dt = " << fixed
921 << setprecision(3) << dt <<
" days\n";
934 CalRes(rs, dt, OCP_FALSE);
951 (fabs(NRdPmax) <= ctrl.ctrlNR.
NRdPmin &&
952 fabs(NRdSmax) <= ctrl.ctrlNR.
NRdSmin)) {
954 if (!ctrl.Check(rs, {
"WellP"})) {
960 }
else if (ctrl.iterNR >= ctrl.ctrlNR.
maxNRiter) {
961 ctrl.current_dt *= ctrl.ctrlTime.
cutFacNR;
963 cout <<
"### WARNING: NR not fully converged! Cut time step size and repeat! "
965 << fixed << setprecision(3) << ctrl.current_dt <<
" days\n";
977 ctrl.CalNextTimeStep(rs, {
"dP",
"dS",
"iter"});
1001 bk.
Ni.resize(nb * nc);
1006 bk.
Pj.resize(nb * np);
1007 bk.
Pc.resize(nb * np);
1009 bk.
S.resize(nb * np);
1010 bk.
xij.resize(nb * np * nc);
1011 bk.
rho.resize(nb * np);
1012 bk.
xi.resize(nb * np);
1013 bk.
mu.resize(nb * np);
1014 bk.
kr.resize(nb * np);
1018 bk.
lNi.resize(nb * nc);
1022 bk.
lPj.resize(nb * np);
1023 bk.
lPc.resize(nb * np);
1025 bk.
lS.resize(nb * np);
1026 bk.
lxij.resize(nb * np * nc);
1027 bk.
lrho.resize(nb * np);
1028 bk.
lxi.resize(nb * np);
1029 bk.
lmu.resize(nb * np);
1030 bk.
lkr.resize(nb * np);
1034 bk.
vfi.resize(nb * nc);
1035 bk.
rhoP.resize(nb * np);
1036 bk.
rhox.resize(nb * nc * np);
1037 bk.
xiP.resize(nb * np);
1038 bk.
xix.resize(nb * nc * np);
1039 bk.
muP.resize(nb * np);
1040 bk.
mux.resize(nb * nc * np);
1041 bk.
dPcj_dS.resize(nb * np * np);
1042 bk.
dKr_dS.resize(nb * np * np);
1045 bk.
lvfi.resize(nb * nc);
1046 bk.
lrhoP.resize(nb * np);
1047 bk.
lrhox.resize(nb * nc * np);
1048 bk.
lxiP.resize(nb * np);
1049 bk.
lxix.resize(nb * nc * np);
1050 bk.
lmuP.resize(nb * np);
1051 bk.
lmux.resize(nb * nc * np);
1053 bk.
ldKr_dS.resize(nb * np * np);
1073 bk.
dSNR.resize(nb * np);
1074 bk.
dSNRP.resize(nb * np);
1075 bk.
dNNR.resize(nb * nc);
1095 void IsoT_FIM::InitFlash(
Bulk& bk)
const
1108 void IsoT_FIM::CalFlash(
Bulk& bk)
1134 for (
USI j = 0; j < np; j++) {
1139 bk.
S[bIdp + j] = bk.
flashCal[pvtnum]->GetS(j);
1140 bk.
dSNR[bIdp + j] = bk.
S[bIdp + j] - bk.
dSNR[bIdp + j];
1151 bk.
rho[bIdp + j] = bk.
flashCal[pvtnum]->GetRho(j);
1152 bk.
xi[bIdp + j] = bk.
flashCal[pvtnum]->GetXi(j);
1153 bk.
mu[bIdp + j] = bk.
flashCal[pvtnum]->GetMu(j);
1157 bk.
xiP[bIdp + j] = bk.
flashCal[pvtnum]->GetXiP(j);
1158 bk.
muP[bIdp + j] = bk.
flashCal[pvtnum]->GetMuP(j);
1160 for (
USI i = 0; i < nc; i++) {
1161 bk.
xij[bIdp * nc + j * nc + i] = bk.
flashCal[pvtnum]->GetXij(j, i);
1162 bk.
rhox[bIdp * nc + j * nc + i] = bk.
flashCal[pvtnum]->GetRhoX(j, i);
1163 bk.
xix[bIdp * nc + j * nc + i] = bk.
flashCal[pvtnum]->GetXiX(j, i);
1164 bk.
mux[bIdp * nc + j * nc + i] = bk.
flashCal[pvtnum]->GetMuX(j, i);
1175 for (
USI i = 0; i < nc; i++) {
1176 bk.
vfi[n * nc + i] = bk.
flashCal[pvtnum]->GetVfi(i);
1181 &bk.
flashCal[pvtnum]->GetDXsDXp()[0]);
1194 bk.
flow[bk.
SATNUM[n]]->CalKrPcDeriv(&bk.
S[bId], &bk.
kr[bId], &bk.
Pc[bId],
1197 for (
USI j = 0; j < np; j++) bk.
Pj[bId + j] = bk.
P[n] + bk.
Pc[bId + j];
1207 const USI len = nc + 1;
1217 for (
OCP_USI n = 0; n < nb; n++) {
1221 for (
USI i = 0; i < nc; i++) {
1222 Res.
resAbs[bId + 1 + i] = bk.
Ni[bIdb + i] - bk.
lNi[bIdb + i];
1226 OCP_USI bId_np_j, eId_np_j, uId_np_j;
1236 for (
USI j = 0; j < np; j++) {
1237 bId_np_j = bId * np + j;
1238 eId_np_j = eId * np + j;
1243 if ((exbegin) && (exend)) {
1244 rho = (bk.
rho[bId_np_j] + bk.
rho[eId_np_j]) / 2;
1245 }
else if (exbegin && (!exend)) {
1246 rho = bk.
rho[bId_np_j];
1247 }
else if ((!exbegin) && (exend)) {
1248 rho = bk.
rho[eId_np_j];
1250 conn.
upblock[c * np + j] = bId;
1262 conn.
upblock[c * np + j] = uId;
1263 uId_np_j = uId * np + j;
1267 Akd * bk.
kr[uId_np_j] / bk.
mu[uId_np_j] * dP;
1274 dt * Akd * bk.
xi[uId_np_j] * bk.
kr[uId_np_j] / bk.
mu[uId_np_j] * dP;
1276 for (
USI i = 0; i < nc; i++) {
1277 dNi = tmp * bk.
xij[uId_np_j * nc + i];
1278 Res.
resAbs[bId * len + 1 + i] += dNi;
1279 Res.
resAbs[eId * len + 1 + i] -= dNi;
1289 for (
USI p = 0; p < wl.PerfNum(); p++) {
1290 const OCP_USI k = wl.PerfLocation(p);
1291 for (
USI i = 0; i < nc; i++) {
1292 Res.
resAbs[k * len + 1 + i] += wl.PerfQi_lbmol(p, i) * dt;
1298 switch (wl.OptMode()) {
1302 Res.
resAbs[wId] = wl.BHP() - wl.MaxBHP();
1309 Res.
resAbs[wId] = wl.MaxRate();
1310 for (
USI i = 0; i < nc; i++) {
1311 Res.
resAbs[wId] += wl.Qi_lbmol(i);
1325 fabs(Res.
resAbs[wId] / wl.MaxRate()));
1333 switch (wl.OptMode()) {
1337 Res.
resAbs[wId] = wl.BHP() - wl.MinBHP();
1345 Res.
resAbs[wId] = -wl.MaxRate();
1346 for (
USI i = 0; i < nc; i++) {
1347 Res.
resAbs[wId] += wl.Qi_lbmol(i) * wl.ProdWeight(i);
1351 fabs(Res.
resAbs[wId] / wl.MaxRate()));
1364 for (
OCP_USI n = 0; n < nb; n++) {
1366 for (
USI i = 0; i < len; i++) {
1376 for (
USI i = 1; i < len; i++) {
1377 tmp = fabs(Res.
resAbs[n * len + i] / bk.
Nt[n]);
1388 if (resetRes0) Res.SetInitRes();
1400 const USI ncol = nc + 1;
1401 const USI ncol2 = np * nc + np;
1402 const USI bsize = ncol * ncol;
1403 const USI bsize2 = ncol * ncol2;
1407 vector<OCP_DBL> bmat(bsize, 0);
1409 for (
USI i = 1; i < ncol; i++) {
1410 bmat[i * ncol + i] = 1;
1412 for (
OCP_USI n = 0; n < nb; n++) {
1413 bmat[0] = bk.
v[n] * bk.
poroP[n] - bk.
vfP[n];
1414 for (
USI i = 0; i < nc; i++) {
1415 bmat[i + 1] = -bk.
vfi[n * nc + i];
1423 vector<OCP_DBL> dFdXpB(bsize, 0);
1424 vector<OCP_DBL> dFdXpE(bsize, 0);
1425 vector<OCP_DBL> dFdXsB(bsize2, 0);
1426 vector<OCP_DBL> dFdXsE(bsize2, 0);
1433 OCP_USI bId_np_j, eId_np_j, uId_np_j, dId_np_j;
1434 OCP_BOOL phaseExistBj, phaseExistEj, phaseExistDj;
1435 OCP_DBL kr, mu, xi, xij, xiP, muP, rhox, xix, mux;
1442 fill(dFdXpB.begin(), dFdXpB.end(), 0.0);
1443 fill(dFdXpE.begin(), dFdXpE.end(), 0.0);
1444 fill(dFdXsB.begin(), dFdXsB.end(), 0.0);
1445 fill(dFdXsE.begin(), dFdXsE.end(), 0.0);
1452 for (
USI j = 0; j < np; j++) {
1453 uId = conn.
upblock[c * np + j];
1454 uId_np_j = uId * np + j;
1456 bId_np_j = bId * np + j;
1457 eId_np_j = eId * np + j;
1462 dFdXpU = &dFdXpB[0];
1463 dFdXpD = &dFdXpE[0];
1464 dFdXsU = &dFdXsB[0];
1465 dFdXsD = &dFdXsE[0];
1466 phaseExistDj = phaseExistEj;
1467 dId_np_j = eId_np_j;
1469 dFdXpU = &dFdXpE[0];
1470 dFdXpD = &dFdXpB[0];
1471 dFdXsU = &dFdXsE[0];
1472 dFdXsD = &dFdXsB[0];
1473 phaseExistDj = phaseExistBj;
1474 dId_np_j = bId_np_j;
1484 dP = bk.
Pj[bId_np_j] - bk.
Pj[eId_np_j] -
1486 xi = bk.
xi[uId_np_j];
1487 kr = bk.
kr[uId_np_j];
1488 mu = bk.
mu[uId_np_j];
1489 muP = bk.
muP[uId_np_j];
1490 xiP = bk.
xiP[uId_np_j];
1491 transJ = Akd * kr / mu;
1493 for (
USI i = 0; i < nc; i++) {
1494 xij = bk.
xij[uId_np_j * nc + i];
1495 transIJ = xij * xi * transJ;
1498 dFdXpB[(i + 1) * ncol] += transIJ;
1499 dFdXpE[(i + 1) * ncol] -= transIJ;
1501 tmp = transJ * xiP * xij * dP;
1502 tmp += -transIJ * muP / mu * dP;
1503 dFdXpU[(i + 1) * ncol] +=
1504 (tmp - transIJ * rhoWghtU * bk.
rhoP[uId_np_j] * dGamma);
1505 dFdXpD[(i + 1) * ncol] +=
1506 -transIJ * rhoWghtD * bk.
rhoP[dId_np_j] * dGamma;
1509 for (
USI k = 0; k < np; k++) {
1510 dFdXsB[(i + 1) * ncol2 + k] +=
1511 transIJ * bk.
dPcj_dS[bId_np_j * np + k];
1512 dFdXsE[(i + 1) * ncol2 + k] -=
1513 transIJ * bk.
dPcj_dS[eId_np_j * np + k];
1514 dFdXsU[(i + 1) * ncol2 + k] +=
1515 Akd * bk.
dKr_dS[uId_np_j * np + k] / mu * xi * xij * dP;
1518 for (
USI k = 0; k < nc; k++) {
1519 rhox = bk.
rhox[uId_np_j * nc + k];
1520 xix = bk.
xix[uId_np_j * nc + k];
1521 mux = bk.
mux[uId_np_j * nc + k];
1522 tmp = -transIJ * rhoWghtU * rhox * dGamma;
1523 tmp += transJ * xix * xij * dP;
1524 tmp += -transIJ * mux / mu * dP;
1525 dFdXsU[(i + 1) * ncol2 + np + j * nc + k] += tmp;
1526 dFdXsD[(i + 1) * ncol2 + np + j * nc + k] +=
1527 -transIJ * rhoWghtD * bk.
rhox[dId_np_j * nc + k] * dGamma;
1529 dFdXsU[(i + 1) * ncol2 + np + j * nc + i] += transJ * xi * dP;
1535 DaABpbC(ncol, ncol, ncol2, 1, dFdXsB.data(), &bk.
dSec_dPri[bId * bsize2], 1,
1537 Dscalar(bsize, dt, bmat.data());
1541 Dscalar(bsize, -1, bmat.data());
1545 if (!
CheckNan(bmat.size(), &bmat[0])) {
1552 DaABpbC(ncol, ncol, ncol2, 1, dFdXsE.data(), &bk.
dSec_dPri[eId * bsize2], 1,
1554 Dscalar(bsize, dt, bmat.data());
1558 Dscalar(bsize, -1, bmat.data());
1562 if (!
CheckNan(bmat.size(), &bmat[0])) {
1578 const USI ncol = nc + 1;
1579 const USI ncol2 = np * nc + np;
1580 const USI bsize = ncol * ncol;
1581 const USI bsize2 = ncol * ncol2;
1586 vector<OCP_DBL> bmat(bsize, 0);
1588 for (
USI i = 1; i < ncol; i++) {
1589 bmat[i * ncol + i] = 1;
1591 for (
OCP_USI n = 0; n < nb; n++) {
1592 bmat[0] = bk.
v[n] * bk.
poroP[n] - bk.
vfP[n];
1593 for (
USI i = 0; i < nc; i++) {
1594 bmat[i + 1] = -bk.
vfi[n * nc + i];
1602 vector<OCP_DBL> dFdXpB(bsize, 0);
1603 vector<OCP_DBL> dFdXpE(bsize, 0);
1604 vector<OCP_DBL> dFdXsB(bsize2, 0);
1605 vector<OCP_DBL> dFdXsE(bsize2, 0);
1606 vector<OCP_BOOL> phaseExistB(np, OCP_FALSE);
1607 vector<OCP_BOOL> phaseExistE(np, OCP_FALSE);
1609 vector<OCP_BOOL> phasedS_B(np, OCP_FALSE);
1610 vector<OCP_BOOL> phasedS_E(np, OCP_FALSE);
1611 vector<USI> pVnumComB(np, 0);
1612 vector<USI> pVnumComE(np, 0);
1616 OCP_USI bId_np_j, eId_np_j, uId_np_j;
1617 OCP_DBL kr, mu, xi, xij, rhoP, xiP, muP, rhox, xix, mux;
1625 fill(dFdXpB.begin(), dFdXpB.end(), 0.0);
1626 fill(dFdXpE.begin(), dFdXpE.end(), 0.0);
1627 fill(dFdXsB.begin(), dFdXsB.end(), 0.0);
1628 fill(dFdXsE.begin(), dFdXsE.end(), 0.0);
1636 for (
USI j = 0; j < np; j++) {
1637 phaseExistB[j] = bk.
phaseExist[bId * np + j];
1638 phaseExistE[j] = bk.
phaseExist[eId * np + j];
1641 if (phasedS_B[j]) jxB++;
1642 if (phasedS_E[j]) jxE++;
1643 pVnumComB[j] = bk.
pVnumCom[bId * np + j];
1644 pVnumComE[j] = bk.
pVnumCom[eId * np + j];
1645 ncolB += pVnumComB[j];
1646 ncolE += pVnumComE[j];
1651 for (
USI j = 0; j < np; j++) {
1652 uId = conn.
upblock[c * np + j];
1654 phaseExistU = (uId == bId ? phaseExistB[j] : phaseExistE[j]);
1656 jxB += pVnumComB[j];
1657 jxE += pVnumComE[j];
1661 bId_np_j = bId * np + j;
1662 eId_np_j = eId * np + j;
1663 uId_np_j = uId * np + j;
1664 dP = bk.
Pj[bId_np_j] - bk.
Pj[eId_np_j] -
1666 xi = bk.
xi[uId_np_j];
1667 kr = bk.
kr[uId_np_j];
1668 mu = bk.
mu[uId_np_j];
1669 muP = bk.
muP[uId_np_j];
1670 xiP = bk.
xiP[uId_np_j];
1671 rhoP = bk.
rhoP[uId_np_j];
1672 transJ = Akd * kr / mu;
1674 for (
USI i = 0; i < nc; i++) {
1675 xij = bk.
xij[uId_np_j * nc + i];
1676 transIJ = xij * xi * transJ;
1679 dFdXpB[(i + 1) * ncol] += transIJ;
1680 dFdXpE[(i + 1) * ncol] -= transIJ;
1682 tmp = xij * transJ * xiP * dP;
1683 tmp += -transIJ * muP / mu * dP;
1684 if (!phaseExistE[j]) {
1685 tmp += transIJ * (-rhoP * dGamma);
1686 dFdXpB[(i + 1) * ncol] += tmp;
1687 }
else if (!phaseExistB[j]) {
1688 tmp += transIJ * (-rhoP * dGamma);
1689 dFdXpE[(i + 1) * ncol] += tmp;
1691 dFdXpB[(i + 1) * ncol] +=
1692 transIJ * (-bk.
rhoP[bId_np_j] * dGamma) / 2;
1693 dFdXpE[(i + 1) * ncol] +=
1694 transIJ * (-bk.
rhoP[eId_np_j] * dGamma) / 2;
1696 dFdXpB[(i + 1) * ncol] += tmp;
1698 dFdXpE[(i + 1) * ncol] += tmp;
1707 for (
USI j1 = 0; j1 < np; j1++) {
1708 if (phasedS_B[j1]) {
1709 dFdXsB[(i + 1) * ncolB + j1SB] +=
1710 transIJ * bk.
dPcj_dS[bId_np_j * np + j1];
1711 tmp = Akd * xij * xi / mu * bk.
dKr_dS[uId_np_j * np + j1] *
1713 dFdXsB[(i + 1) * ncolB + j1SB] += tmp;
1716 if (phasedS_E[j1]) {
1717 dFdXsE[(i + 1) * ncolE + j1SE] -=
1718 transIJ * bk.
dPcj_dS[eId_np_j * np + j1];
1723 if (!phaseExistE[j]) {
1724 for (
USI k = 0; k < pVnumComB[j]; k++) {
1725 rhox = bk.
rhox[uId_np_j * nc + k];
1726 xix = bk.
xix[uId_np_j * nc + k];
1727 mux = bk.
mux[uId_np_j * nc + k];
1728 tmp = -transIJ * rhox * dGamma;
1729 tmp += xij * transJ * xix * dP;
1730 tmp += -transIJ * mux / mu * dP;
1731 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
1734 if (i < pVnumComB[j])
1735 dFdXsB[(i + 1) * ncolB + jxB + i] += xi * transJ * dP;
1737 for (
USI k = 0; k < pVnumComB[j]; k++) {
1738 rhox = bk.
rhox[bId_np_j * nc + k] / 2;
1739 xix = bk.
xix[uId_np_j * nc + k];
1740 mux = bk.
mux[uId_np_j * nc + k];
1741 tmp = -transIJ * rhox * dGamma;
1742 tmp += xij * transJ * xix * dP;
1743 tmp += -transIJ * mux / mu * dP;
1744 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
1745 dFdXsE[(i + 1) * ncolE + jxE + k] +=
1746 -transIJ * bk.
rhox[eId_np_j * nc + k] / 2 * dGamma;
1749 if (i < pVnumComB[j])
1750 dFdXsB[(i + 1) * ncolB + jxB + i] += xi * transJ * dP;
1754 for (
USI j1 = 0; j1 < np; j1++) {
1755 if (phasedS_B[j1]) {
1756 dFdXsB[(i + 1) * ncolB + j1SB] +=
1757 transIJ * bk.
dPcj_dS[bId_np_j * np + j1];
1760 if (phasedS_E[j1]) {
1761 dFdXsE[(i + 1) * ncolE + j1SE] -=
1762 transIJ * bk.
dPcj_dS[eId_np_j * np + j1];
1763 tmp = Akd * xij * xi / mu * bk.
dKr_dS[uId_np_j * np + j1] *
1765 dFdXsE[(i + 1) * ncolE + j1SE] += tmp;
1770 if (!phaseExistB[j]) {
1771 for (
USI k = 0; k < pVnumComE[j]; k++) {
1772 rhox = bk.
rhox[uId_np_j * nc + k];
1773 xix = bk.
xix[uId_np_j * nc + k];
1774 mux = bk.
mux[uId_np_j * nc + k];
1775 tmp = -transIJ * rhox * dGamma;
1776 tmp += xij * transJ * xix * dP;
1777 tmp += -transIJ * mux / mu * dP;
1778 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
1781 if (i < pVnumComE[j])
1782 dFdXsE[(i + 1) * ncolE + jxE + i] += xi * transJ * dP;
1784 for (
USI k = 0; k < pVnumComE[j]; k++) {
1785 rhox = bk.
rhox[eId_np_j * nc + k] / 2;
1786 xix = bk.
xix[uId_np_j * nc + k];
1787 mux = bk.
mux[uId_np_j * nc + k];
1788 tmp = -transIJ * rhox * dGamma;
1789 tmp += xij * transJ * xix * dP;
1790 tmp += -transIJ * mux / mu * dP;
1791 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
1792 dFdXsB[(i + 1) * ncolB + jxB + k] +=
1793 -transIJ * bk.
rhox[bId_np_j * nc + k] / 2 * dGamma;
1796 if (i < pVnumComE[j])
1797 dFdXsE[(i + 1) * ncolE + jxE + i] += xi * transJ * dP;
1801 jxB += pVnumComB[j];
1802 jxE += pVnumComE[j];
1807 DaABpbC(ncol, ncol, ncolB, 1, dFdXsB.data(), &bk.
dSec_dPri[bId * lendSdP], 1,
1809 Dscalar(bsize, dt, bmat.data());
1813 Dscalar(bsize, -1, bmat.data());
1817 if (!
CheckNan(bmat.size(), &bmat[0])) {
1823 DaABpbC(ncol, ncol, ncolE, 1, dFdXsE.data(), &bk.
dSec_dPri[eId * lendSdP], 1,
1826 Dscalar(bsize, dt, bmat.data());
1830 Dscalar(bsize, -1, bmat.data());
1834 if (!
CheckNan(bmat.size(), &bmat[0])) {
1851 const USI ncol = nc + 1;
1852 const USI ncol2 = np * nc + np;
1853 const USI bsize = ncol * ncol;
1854 const USI bsize2 = ncol * ncol2;
1859 vector<OCP_DBL> bmat(bsize, 0);
1861 for (
USI i = 1; i < ncol; i++) {
1862 bmat[i * ncol + i] = 1;
1864 for (
OCP_USI n = 0; n < nb; n++) {
1865 bmat[0] = bk.
v[n] * bk.
poroP[n] - bk.
vfP[n];
1866 for (
USI i = 0; i < nc; i++) {
1867 bmat[i + 1] = -bk.
vfi[n * nc + i];
1875 vector<OCP_DBL> dFdXpB(bsize, 0);
1876 vector<OCP_DBL> dFdXpE(bsize, 0);
1877 vector<OCP_DBL> dFdXsB(bsize2, 0);
1878 vector<OCP_DBL> dFdXsE(bsize2, 0);
1879 vector<OCP_BOOL> phaseExistB(np, OCP_FALSE);
1880 vector<OCP_BOOL> phaseExistE(np, OCP_FALSE);
1882 vector<USI> pEnumComB(np, 0);
1883 vector<USI> pEnumComE(np, 0);
1887 OCP_USI bId_np_j, eId_np_j, uId_np_j;
1888 OCP_DBL kr, mu, xi, xij, rhoP, xiP, muP, rhox, xix, mux;
1897 fill(dFdXpB.begin(), dFdXpB.end(), 0.0);
1898 fill(dFdXpE.begin(), dFdXpE.end(), 0.0);
1899 fill(dFdXsB.begin(), dFdXsB.end(), 0.0);
1900 fill(dFdXsE.begin(), dFdXsE.end(), 0.0);
1908 for (
USI j = 0; j < np; j++) {
1909 phaseExistB[j] = bk.
phaseExist[bId * np + j];
1910 phaseExistE[j] = bk.
phaseExist[eId * np + j];
1911 pEnumComB[j] = bk.
pVnumCom[bId * np + j];
1912 pEnumComE[j] = bk.
pVnumCom[eId * np + j];
1913 ncolB += pEnumComB[j];
1914 ncolE += pEnumComE[j];
1919 for (
USI j = 0; j < np; j++) {
1920 uId = conn.
upblock[c * np + j];
1922 phaseExistU = (uId == bId ? phaseExistB[j] : phaseExistE[j]);
1924 jxB += pEnumComB[j];
1925 jxE += pEnumComE[j];
1929 bId_np_j = bId * np + j;
1930 eId_np_j = eId * np + j;
1931 uId_np_j = uId * np + j;
1932 dP = bk.
Pj[bId_np_j] - bk.
Pj[eId_np_j] -
1934 xi = bk.
xi[uId_np_j];
1935 kr = bk.
kr[uId_np_j];
1936 mu = bk.
mu[uId_np_j];
1937 muP = bk.
muP[uId_np_j];
1938 xiP = bk.
xiP[uId_np_j];
1939 rhoP = bk.
rhoP[uId_np_j];
1940 transJ = Akd * kr / mu;
1942 for (
USI i = 0; i < nc; i++) {
1943 xij = bk.
xij[uId_np_j * nc + i];
1944 transIJ = xij * xi * transJ;
1947 dFdXpB[(i + 1) * ncol] += transIJ;
1948 dFdXpE[(i + 1) * ncol] -= transIJ;
1950 tmp = xij * transJ * xiP * dP;
1951 tmp += -transIJ * muP / mu * dP;
1952 if (!phaseExistE[j]) {
1953 tmp += transIJ * (-rhoP * dGamma);
1954 dFdXpB[(i + 1) * ncol] += tmp;
1955 }
else if (!phaseExistB[j]) {
1956 tmp += transIJ * (-rhoP * dGamma);
1957 dFdXpE[(i + 1) * ncol] += tmp;
1959 dFdXpB[(i + 1) * ncol] += transIJ * dGamma *
1960 (-bk.
rhoP[bId_np_j] * bk.
S[bId_np_j]) /
1961 (bk.
S[bId_np_j] + bk.
S[eId_np_j]);
1962 dFdXpE[(i + 1) * ncol] += transIJ * dGamma *
1963 (-bk.
rhoP[eId_np_j] * bk.
S[eId_np_j]) /
1964 (bk.
S[bId_np_j] + bk.
S[eId_np_j]);
1966 dFdXpB[(i + 1) * ncol] += tmp;
1968 dFdXpE[(i + 1) * ncol] += tmp;
1977 for (
USI j1 = 0; j1 < np; j1++) {
1981 if (j1 == j && phaseExistE[j]) {
1982 tmp = -dGamma / ((bk.
S[bId_np_j] + bk.
S[eId_np_j]) *
1983 (bk.
S[bId_np_j] + bk.
S[eId_np_j]));
1984 wghtb = tmp * bk.
rho[bId_np_j] * bk.
S[eId_np_j];
1985 wghte = tmp * bk.
rho[eId_np_j] * bk.
S[bId_np_j];
1988 if (phaseExistB[j1]) {
1989 dFdXsB[(i + 1) * ncolB + j1SB] +=
1990 transIJ * (bk.
dPcj_dS[bId_np_j * np + j1] + wghtb);
1991 tmp = Akd * xij * xi / mu * bk.
dKr_dS[uId_np_j * np + j1] *
1993 dFdXsB[(i + 1) * ncolB + j1SB] += tmp;
1996 if (phaseExistE[j1]) {
1997 dFdXsE[(i + 1) * ncolE + j1SE] -=
1998 transIJ * (bk.
dPcj_dS[eId_np_j * np + j1] + wghte);
2003 if (!phaseExistE[j]) {
2004 for (
USI k = 0; k < pEnumComB[j]; k++) {
2005 rhox = bk.
rhox[uId_np_j * nc + k];
2006 xix = bk.
xix[uId_np_j * nc + k];
2007 mux = bk.
mux[uId_np_j * nc + k];
2008 tmp = -transIJ * rhox * dGamma;
2009 tmp += xij * transJ * xix * dP;
2010 tmp += -transIJ * mux / mu * dP;
2011 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
2014 if (i < pEnumComB[j])
2015 dFdXsB[(i + 1) * ncolB + jxB + i] += xi * transJ * dP;
2017 wghtb = bk.
S[bId_np_j] / (bk.
S[bId_np_j] + bk.
S[eId_np_j]);
2018 wghte = bk.
S[eId_np_j] / (bk.
S[bId_np_j] + bk.
S[eId_np_j]);
2019 for (
USI k = 0; k < pEnumComB[j]; k++) {
2020 rhox = bk.
rhox[bId_np_j * nc + k] * wghtb;
2021 xix = bk.
xix[uId_np_j * nc + k];
2022 mux = bk.
mux[uId_np_j * nc + k];
2023 tmp = -transIJ * rhox * dGamma;
2024 tmp += xij * transJ * xix * dP;
2025 tmp += -transIJ * mux / mu * dP;
2026 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
2027 dFdXsE[(i + 1) * ncolE + jxE + k] +=
2028 -transIJ * dGamma * bk.
rhox[eId_np_j * nc + k] * wghte;
2031 if (i < pEnumComB[j])
2032 dFdXsB[(i + 1) * ncolB + jxB + i] += xi * transJ * dP;
2036 for (
USI j1 = 0; j1 < np; j1++) {
2040 if (j1 == j && phaseExistB[j]) {
2041 tmp = -dGamma / ((bk.
S[bId_np_j] + bk.
S[eId_np_j]) *
2042 (bk.
S[bId_np_j] + bk.
S[eId_np_j]));
2043 wghtb = tmp * bk.
rho[bId_np_j] * bk.
S[eId_np_j];
2044 wghte = tmp * bk.
rho[eId_np_j] * bk.
S[bId_np_j];
2047 if (phaseExistB[j1]) {
2048 dFdXsB[(i + 1) * ncolB + j1SB] +=
2049 transIJ * (bk.
dPcj_dS[bId_np_j * np + j1] + wghtb);
2052 if (phaseExistE[j1]) {
2053 dFdXsE[(i + 1) * ncolE + j1SE] -=
2054 transIJ * (bk.
dPcj_dS[eId_np_j * np + j1] + wghte);
2055 tmp = Akd * xij * xi / mu * bk.
dKr_dS[uId_np_j * np + j1] *
2057 dFdXsE[(i + 1) * ncolE + j1SE] += tmp;
2062 if (!phaseExistB[j]) {
2063 for (
USI k = 0; k < pEnumComE[j]; k++) {
2064 rhox = bk.
rhox[uId_np_j * nc + k];
2065 xix = bk.
xix[uId_np_j * nc + k];
2066 mux = bk.
mux[uId_np_j * nc + k];
2067 tmp = -transIJ * rhox * dGamma;
2068 tmp += xij * transJ * xix * dP;
2069 tmp += -transIJ * mux / mu * dP;
2070 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
2073 if (i < pEnumComE[j])
2074 dFdXsE[(i + 1) * ncolE + jxE + i] += xi * transJ * dP;
2076 wghtb = bk.
S[bId_np_j] / (bk.
S[bId_np_j] + bk.
S[eId_np_j]);
2077 wghte = bk.
S[eId_np_j] / (bk.
S[bId_np_j] + bk.
S[eId_np_j]);
2078 for (
USI k = 0; k < pEnumComE[j]; k++) {
2079 rhox = bk.
rhox[eId_np_j * nc + k] * wghte;
2080 xix = bk.
xix[uId_np_j * nc + k];
2081 mux = bk.
mux[uId_np_j * nc + k];
2082 tmp = -transIJ * rhox * dGamma;
2083 tmp += xij * transJ * xix * dP;
2084 tmp += -transIJ * mux / mu * dP;
2085 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
2086 dFdXsB[(i + 1) * ncolB + jxB + k] +=
2087 -transIJ * dGamma * bk.
rhox[bId_np_j * nc + k] * wghtb;
2090 if (i < pEnumComE[j])
2091 dFdXsE[(i + 1) * ncolE + jxE + i] += xi * transJ * dP;
2095 jxB += pEnumComB[j];
2096 jxE += pEnumComE[j];
2101 DaABpbC(ncol, ncol, ncolB, 1, dFdXsB.data(), &bk.
dSec_dPri[bId * lendSdP], 1,
2103 Dscalar(bsize, dt, bmat.data());
2107 Dscalar(bsize, -1, bmat.data());
2111 if (!
CheckNan(bmat.size(), &bmat[0])) {
2118 DaABpbC(ncol, ncol, ncolE, 1, dFdXsE.data(), &bk.
dSec_dPri[eId * lendSdP], 1,
2120 Dscalar(bsize, dt, bmat.data());
2124 Dscalar(bsize, -1, bmat.data());
2128 if (!
CheckNan(bmat.size(), &bmat[0])) {
2144 AssembleMatInjWells(ls, rs.
bulk, wl, dt);
2147 AssembleMatProdWells(ls, rs.
bulk, wl, dt);
2176 const USI ncol = nc + 1;
2177 const USI ncol2 = np * nc + np;
2178 const USI bsize = ncol * ncol;
2179 const USI bsize2 = ncol * ncol2;
2182 vector<OCP_DBL> bmat(bsize, 0);
2183 vector<OCP_DBL> bmat2(bsize, 0);
2184 vector<OCP_DBL> dQdXpB(bsize, 0);
2185 vector<OCP_DBL> dQdXpW(bsize, 0);
2186 vector<OCP_DBL> dQdXsB(bsize2, 0);
2193 for (
USI p = 0; p < wl.PerfNum(); p++) {
2194 const OCP_USI n = wl.PerfLocation(p);
2195 fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
2196 fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
2197 fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
2199 dP = bk.
P[n] - wl.BHP() - wl.DG(p);
2201 for (
USI j = 0; j < np; j++) {
2202 n_np_j = n * np + j;
2206 muP = bk.
muP[n_np_j];
2208 for (
USI i = 0; i < nc; i++) {
2210 transIJ = wl.PerfTransj(p, j) * wl.PerfXi(p) * wl.InjZi(i);
2211 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
2212 dQdXpW[(i + 1) * ncol] += -transIJ;
2215 for (
USI k = 0; k < np; k++) {
2216 dQdXsB[(i + 1) * ncol2 + k] +=
2217 CONV1 * wl.PerfWI(p) * wl.PerfMultiplier(p) * wl.PerfXi(p) *
2218 wl.InjZi(i) * bk.
dKr_dS[n_np_j * np + k] * dP / mu;
2221 for (
USI k = 0; k < nc; k++) {
2222 dQdXsB[(i + 1) * ncol2 + np + j * nc + k] +=
2223 -transIJ * dP / mu * bk.
mux[n_np_j * nc + k];
2232 Dscalar(bsize, dt, bmat.data());
2238 Dscalar(bsize, dt, bmat.data());
2242 switch (wl.OptMode()) {
2249 fill(bmat.begin(), bmat.end(), 0.0);
2250 for (
USI i = 0; i < nc; i++) {
2251 bmat[0] += dQdXpW[(i + 1) * ncol];
2252 bmat[(i + 1) * ncol + i + 1] = 1;
2260 fill(bmat2.begin(), bmat2.end(), 0.0);
2261 for (
USI i = 0; i < nc; i++) {
2262 Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
2269 fill(bmat.begin(), bmat.end(), 0.0);
2270 for (
USI i = 0; i < ncol; i++) {
2271 bmat[i * ncol + i] = 1;
2276 fill(bmat.begin(), bmat.end(), 0.0);
2294 const USI ncol = nc + 1;
2295 const USI ncol2 = np * nc + np;
2296 const USI bsize = ncol * ncol;
2297 const USI bsize2 = ncol * ncol2;
2300 vector<OCP_DBL> bmat(bsize, 0);
2301 vector<OCP_DBL> bmat2(bsize, 0);
2302 vector<OCP_DBL> dQdXpB(bsize, 0);
2303 vector<OCP_DBL> dQdXpW(bsize, 0);
2304 vector<OCP_DBL> dQdXsB(bsize2, 0);
2306 OCP_DBL xij, xi, mu, muP, xiP, dP, transIJ, tmp;
2314 for (
USI p = 0; p < wl.PerfNum(); p++) {
2315 const OCP_USI n = wl.PerfLocation(p);
2316 fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
2317 fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
2318 fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
2320 for (
USI j = 0; j < np; j++) {
2321 n_np_j = n * np + j;
2324 dP = bk.
Pj[n_np_j] - wl.BHP() - wl.DG(p);
2327 muP = bk.
muP[n_np_j];
2328 xiP = bk.
xiP[n_np_j];
2330 for (
USI i = 0; i < nc; i++) {
2331 xij = bk.
xij[n_np_j * nc + i];
2333 transIJ = wl.PerfTransj(p, j) * xi * xij;
2334 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu) +
2335 dP * wl.PerfTransj(p, j) * xij * xiP;
2336 dQdXpW[(i + 1) * ncol] += -transIJ;
2339 for (
USI k = 0; k < np; k++) {
2340 tmp =
CONV1 * wl.PerfWI(p) * wl.PerfMultiplier(p) * dP / mu * xi *
2341 xij * bk.
dKr_dS[n_np_j * np + k];
2343 tmp += transIJ * bk.
dPcj_dS[n_np_j * np + k];
2344 dQdXsB[(i + 1) * ncol2 + k] += tmp;
2347 for (
USI k = 0; k < nc; k++) {
2348 tmp = dP * wl.PerfTransj(p, j) * xij *
2349 (bk.
xix[n_np_j * nc + k] - xi / mu * bk.
mux[n_np_j * nc + k]);
2350 dQdXsB[(i + 1) * ncol2 + np + j * nc + k] += tmp;
2352 dQdXsB[(i + 1) * ncol2 + np + j * nc + i] +=
2353 wl.PerfTransj(p, j) * xi * dP;
2362 Dscalar(bsize, dt, bmat.data());
2367 Dscalar(bsize, dt, bmat.data());
2371 switch (wl.OptMode()) {
2378 fill(bmat.begin(), bmat.end(), 0.0);
2379 for (
USI i = 0; i < nc; i++) {
2380 bmat[0] += dQdXpW[(i + 1) * ncol] * wl.ProdWeight(i);
2381 bmat[(i + 1) * ncol + i + 1] = 1;
2389 fill(bmat2.begin(), bmat2.end(), 0.0);
2390 for (
USI i = 0; i < nc; i++) {
2391 Daxpy(ncol, wl.ProdWeight(i), bmat.data() + (i + 1) * ncol,
2399 fill(bmat.begin(), bmat.end(), 0.0);
2400 for (
USI i = 0; i < ncol; i++) {
2401 bmat[i * ncol + i] = 1;
2406 fill(bmat.begin(), bmat.end(), 0.0);
2426 AssembleMatInjWellsNew(ls, rs.
bulk, wl, dt);
2429 AssembleMatProdWellsNew(ls, rs.
bulk, wl, dt);
2438 void IsoT_FIM::AssembleMatInjWellsNew(
LinearSystem& ls,
2446 const USI ncol = nc + 1;
2447 const USI ncol2 = np * nc + np;
2448 const USI bsize = ncol * ncol;
2449 const USI bsize2 = ncol * ncol2;
2451 vector<OCP_DBL> bmat(bsize, 0);
2452 vector<OCP_DBL> bmat2(bsize, 0);
2453 vector<OCP_DBL> dQdXpB(bsize, 0);
2454 vector<OCP_DBL> dQdXpW(bsize, 0);
2455 vector<OCP_DBL> dQdXsB(bsize2, 0);
2456 vector<OCP_BOOL> phaseExistB(np, OCP_FALSE);
2457 vector<OCP_BOOL> phasedS_B(np, OCP_FALSE);
2458 vector<USI> pVnumComB(np, 0);
2467 for (
USI p = 0; p < wl.PerfNum(); p++) {
2468 const OCP_USI n = wl.PerfLocation(p);
2469 fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
2470 fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
2471 fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
2473 dP = bk.
P[n] - wl.BHP() - wl.DG(p);
2478 for (
USI j = 0; j < np; j++) {
2481 if (phasedS_B[j]) jxB++;
2482 pVnumComB[j] = bk.
pVnumCom[n * np + j];
2483 ncolB += pVnumComB[j];
2487 for (
USI j = 0; j < np; j++) {
2489 if (!phaseExistB[j]) {
2490 jxB += pVnumComB[j];
2494 n_np_j = n * np + j;
2496 muP = bk.
muP[n_np_j];
2498 for (
USI i = 0; i < nc; i++) {
2500 transIJ = wl.PerfTransj(p, j) * wl.PerfXi(p) * wl.InjZi(i);
2501 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
2502 dQdXpW[(i + 1) * ncol] += -transIJ;
2506 for (
USI j1 = 0; j1 < np; j1++) {
2507 if (phasedS_B[j1]) {
2508 dQdXsB[(i + 1) * ncolB + j1B] +=
2509 CONV1 * wl.PerfWI(p) * wl.PerfMultiplier(p) * wl.PerfXi(p) *
2510 wl.InjZi(i) * bk.
dKr_dS[n_np_j * np + j1] * dP / mu;
2516 for (
USI k = 0; k < pVnumComB[j]; k++) {
2517 dQdXsB[(i + 1) * ncolB + jxB + k] +=
2518 -transIJ * dP / mu * bk.
mux[n_np_j * nc + k];
2521 jxB += pVnumComB[j];
2525 DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &bk.
dSec_dPri[n * lendSdP], 1,
2527 Dscalar(bsize, dt, bmat.data());
2533 Dscalar(bsize, dt, bmat.data());
2537 switch (wl.OptMode()) {
2544 fill(bmat.begin(), bmat.end(), 0.0);
2545 for (
USI i = 0; i < nc; i++) {
2546 bmat[0] += dQdXpW[(i + 1) * ncol];
2547 bmat[(i + 1) * ncol + i + 1] = 1;
2555 fill(bmat2.begin(), bmat2.end(), 0.0);
2556 for (
USI i = 0; i < nc; i++) {
2557 Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
2564 fill(bmat.begin(), bmat.end(), 0.0);
2565 for (
USI i = 0; i < ncol; i++) {
2566 bmat[i * ncol + i] = 1;
2571 fill(bmat.begin(), bmat.end(), 0.0);
2582 void IsoT_FIM::AssembleMatProdWellsNew(
LinearSystem& ls,
2590 const USI ncol = nc + 1;
2591 const USI ncol2 = np * nc + np;
2592 const USI bsize = ncol * ncol;
2593 const USI bsize2 = ncol * ncol2;
2595 vector<OCP_DBL> bmat(bsize, 0);
2596 vector<OCP_DBL> bmat2(bsize, 0);
2597 vector<OCP_DBL> dQdXpB(bsize, 0);
2598 vector<OCP_DBL> dQdXpW(bsize, 0);
2599 vector<OCP_DBL> dQdXsB(bsize2, 0);
2600 vector<OCP_BOOL> phaseExistB(np, OCP_FALSE);
2601 vector<OCP_BOOL> phasedS_B(np, OCP_FALSE);
2602 vector<USI> pVnumComB(np, 0);
2606 OCP_DBL xij, xi, mu, muP, xiP, dP, transIJ, tmp;
2614 for (
USI p = 0; p < wl.PerfNum(); p++) {
2615 OCP_USI n = wl.PerfLocation(p);
2616 fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
2617 fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
2618 fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
2622 for (
USI j = 0; j < np; j++) {
2625 if (phasedS_B[j]) jxB++;
2626 pVnumComB[j] = bk.
pVnumCom[n * np + j];
2627 ncolB += pVnumComB[j];
2631 for (
USI j = 0; j < np; j++) {
2633 if (!phaseExistB[j]) {
2634 jxB += pVnumComB[j];
2638 n_np_j = n * np + j;
2639 dP = bk.
Pj[n_np_j] - wl.BHP() - wl.DG(p);
2642 muP = bk.
muP[n_np_j];
2643 xiP = bk.
xiP[n_np_j];
2645 for (
USI i = 0; i < nc; i++) {
2646 xij = bk.
xij[n_np_j * nc + i];
2648 transIJ = wl.PerfTransj(p, j) * xi * xij;
2649 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu) +
2650 dP * wl.PerfTransj(p, j) * xij * xiP;
2651 dQdXpW[(i + 1) * ncol] += -transIJ;
2655 for (
USI j1 = 0; j1 < np; j1++) {
2656 if (phasedS_B[j1]) {
2657 tmp =
CONV1 * wl.PerfWI(p) * wl.PerfMultiplier(p) * dP / mu *
2658 xi * xij * bk.
dKr_dS[n_np_j * np + j1];
2660 tmp += transIJ * bk.
dPcj_dS[n_np_j * np + j1];
2661 dQdXsB[(i + 1) * ncolB + j1B] += tmp;
2666 for (
USI k = 0; k < pVnumComB[j]; k++) {
2667 tmp = dP * wl.PerfTransj(p, j) * xij *
2668 (bk.
xix[n_np_j * nc + k] - xi / mu * bk.
mux[n_np_j * nc + k]);
2669 dQdXsB[(i + 1) * ncolB + jxB + k] += tmp;
2672 if (i < pVnumComB[j])
2673 dQdXsB[(i + 1) * ncolB + jxB + i] += wl.PerfTransj(p, j) * xi * dP;
2675 jxB += pVnumComB[j];
2679 DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &bk.
dSec_dPri[n * lendSdP], 1,
2681 Dscalar(bsize, dt, bmat.data());
2685 Dscalar(bsize, dt, bmat.data());
2689 switch (wl.OptMode()) {
2696 fill(bmat.begin(), bmat.end(), 0.0);
2697 for (
USI i = 0; i < nc; i++) {
2698 bmat[0] += dQdXpW[(i + 1) * ncol] * wl.ProdWeight(i);
2699 bmat[(i + 1) * ncol + i + 1] = 1;
2707 fill(bmat2.begin(), bmat2.end(), 0.0);
2708 for (
USI i = 0; i < nc; i++) {
2709 Daxpy(ncol, wl.ProdWeight(i), bmat.data() + (i + 1) * ncol,
2717 fill(bmat.begin(), bmat.end(), 0.0);
2718 for (
USI i = 0; i < ncol; i++) {
2719 bmat[i * ncol + i] = 1;
2724 fill(bmat.begin(), bmat.end(), 0.0);
2735 void IsoT_FIM::GetSolution(
Reservoir& rs,
2736 const vector<OCP_DBL>& u,
2747 const USI row = np * (nc + 1);
2748 const USI col = nc + 1;
2749 vector<OCP_DBL> dtmp(row, 0);
2758 for (
OCP_USI n = 0; n < nb; n++) {
2763 fill(dtmp.begin(), dtmp.end(), 0.0);
2771 u.data() + n * col, 1, dtmp.data());
2776 for (
USI j = 0; j < np; j++) {
2782 if (fabs(dtmp[js]) > dSmaxlim) {
2783 choptmp = dSmaxlim / fabs(dtmp[js]);
2784 }
else if (bk.
S[n * np + j] + dtmp[js] < 0.0) {
2785 choptmp = 0.9 * bk.
S[n * np + j] / fabs(dtmp[js]);
2792 chopmin = min(chopmin, choptmp);
2798 for (
USI j = 0; j < np; j++) {
2800 bk.
dSNRP[n * np + j] = 0;
2803 bk.
dSNRP[n * np + j] = chopmin * dtmp[js];
2804 bk.
S[n * np + j] += bk.
dSNRP[n * np + j];
2813 for (
USI j = 0; j < 2; j++) {
2814 bId = n * np * nc + j * nc;
2816 bk.
xij[bId + i] += chopmin * dtmp[js];
2836 for (
USI i = 0; i < nc; i++) {
2837 bk.
dNNR[n * nc + i] = u[n * col + 1 + i] * chopmin;
2838 if (fabs(bk.
NRdNmax) < fabs(bk.
dNNR[n * nc + i]) / bk.
Nt[n])
2841 bk.
Ni[n * nc + i] += bk.
dNNR[n * nc + i];
2853 wl.SetBHP(wl.BHP() + u[wId]);
2958 rs.
allWells.UpdateLastTimeStepBHP();
3020 int status = ls.
Solve();
3044 OCP_DBL& dt = ctrl.current_dt;
3047 if (!ctrl.Check(rs, {
"BulkNi",
"BulkP"})) {
3049 cout <<
"Cut time step size and repeat! current dt = " << fixed
3050 << setprecision(3) << dt <<
" days\n";
3062 CalRes(rs, dt, OCP_FALSE);
3080 (fabs(NRdPmax) <= ctrl.ctrlNR.
NRdPmin &&
3081 fabs(NRdSmax) <= ctrl.ctrlNR.
NRdSmin)) {
3083 if (!ctrl.Check(rs, {
"WellP"})) {
3090 }
else if (ctrl.iterNR > ctrl.ctrlNR.
maxNRiter) {
3091 ctrl.current_dt *= ctrl.ctrlTime.
cutFacNR;
3093 cout <<
"### WARNING: NR not fully converged! Cut time step size and repeat! "
3095 << fixed << setprecision(3) << ctrl.current_dt <<
" days\n";
3108 ctrl.CalNextTimeStep(rs, {
"dP",
"dS",
"iter"});
3120 bk.
nj.resize(nb * np);
3121 bk.
res_n.resize(nb * (np + np * nc));
3122 bk.
resPc.resize(nb);
3124 bk.
lnj.resize(nb * np);
3125 bk.
lres_n.resize(nb * (np + np * nc));
3138 for (
OCP_USI n = 0; n < nb; n++) {
3141 bk.
Ni.data() + n * nc, n);
3142 for (
USI i = 0; i < nc; i++) {
3148 OCP_ABORT(
"Not Completed in BLKOIL MODEL!");
3160 vector<USI> flagB(np, 0);
3164 for (
OCP_USI n = 0; n < nb; n++) {
3166 for (
USI j = 0; j < np; j++) flagB[j] = bk.
phaseExist[n * np + j];
3169 bk.
P[n], bk.
T[n], &bk.
Ni[n * nc], &bk.
S[n * np], &bk.
xij[n * np * nc],
3170 &bk.
nj[n * np], &flagB[0], bk.
phaseNum[n], n);
3189 bk.
nj[n * np + j] = bk.
flashCal[pvtnum]->GetNj(j);
3194 &bk.
flashCal[pvtnum]->GetRes()[0]);
3208 const USI ncol = nc + 1;
3209 const USI ncol2 = np * nc + np;
3210 const USI bsize = ncol * ncol;
3211 const USI bsize2 = ncol * ncol2;
3216 vector<OCP_DBL> bmat(bsize, 0);
3217 vector<OCP_DBL> tmpb(ncol, 0);
3220 for (
USI i = 1; i < ncol; i++) {
3221 bmat[i * ncol + i] = 1;
3223 for (
OCP_USI n = 0; n < nb; n++) {
3224 bmat[0] = bk.
v[n] * bk.
poroP[n] - bk.
vfP[n];
3225 for (
USI i = 0; i < nc; i++) {
3226 bmat[i + 1] = -bk.
vfi[n * nc + i];
3236 vector<OCP_DBL> dFdXpB(bsize, 0);
3237 vector<OCP_DBL> dFdXpE(bsize, 0);
3238 vector<OCP_DBL> dFdXsB(bsize2, 0);
3239 vector<OCP_DBL> dFdXsE(bsize2, 0);
3240 vector<OCP_BOOL> phaseExistB(np, OCP_FALSE);
3241 vector<OCP_BOOL> phaseExistE(np, OCP_FALSE);
3243 vector<OCP_BOOL> phasedS_B(np, OCP_FALSE);
3244 vector<OCP_BOOL> phasedS_E(np, OCP_FALSE);
3245 vector<USI> pVnumComB(np, 0);
3246 vector<USI> pVnumComE(np, 0);
3250 OCP_USI bId_np_j, eId_np_j, uId_np_j;
3251 OCP_DBL kr, mu, xi, xij, rhoP, xiP, muP, rhox, xix, mux;
3259 fill(dFdXpB.begin(), dFdXpB.end(), 0.0);
3260 fill(dFdXpE.begin(), dFdXpE.end(), 0.0);
3261 fill(dFdXsB.begin(), dFdXsB.end(), 0.0);
3262 fill(dFdXsE.begin(), dFdXsE.end(), 0.0);
3272 for (
USI j = 0; j < np; j++) {
3273 phaseExistB[j] = bk.
phaseExist[bId * np + j];
3274 phaseExistE[j] = bk.
phaseExist[eId * np + j];
3277 if (phasedS_B[j]) jxB++;
3278 if (phasedS_E[j]) jxE++;
3279 pVnumComB[j] = bk.
pVnumCom[bId * np + j];
3280 pVnumComE[j] = bk.
pVnumCom[eId * np + j];
3281 ncolB += pVnumComB[j];
3282 ncolE += pVnumComE[j];
3287 for (
USI j = 0; j < np; j++) {
3288 uId = conn.
upblock[c * np + j];
3290 phaseExistU = (uId == bId ? phaseExistB[j] : phaseExistE[j]);
3292 jxB += pVnumComB[j];
3293 jxE += pVnumComE[j];
3297 bId_np_j = bId * np + j;
3298 eId_np_j = eId * np + j;
3299 uId_np_j = uId * np + j;
3300 dP = bk.
Pj[bId_np_j] - bk.
Pj[eId_np_j] -
3302 xi = bk.
xi[uId_np_j];
3303 kr = bk.
kr[uId_np_j];
3304 mu = bk.
mu[uId_np_j];
3305 muP = bk.
muP[uId_np_j];
3306 xiP = bk.
xiP[uId_np_j];
3307 rhoP = bk.
rhoP[uId_np_j];
3308 transJ = Akd * kr / mu;
3310 for (
USI i = 0; i < nc; i++) {
3311 xij = bk.
xij[uId_np_j * nc + i];
3312 transIJ = xij * xi * transJ;
3315 dFdXpB[(i + 1) * ncol] += transIJ;
3316 dFdXpE[(i + 1) * ncol] -= transIJ;
3318 tmp = xij * transJ * xiP * dP;
3319 tmp += -transIJ * muP / mu * dP;
3320 if (!phaseExistE[j]) {
3321 tmp += transIJ * (-rhoP * dGamma);
3322 dFdXpB[(i + 1) * ncol] += tmp;
3323 }
else if (!phaseExistB[j]) {
3324 tmp += transIJ * (-rhoP * dGamma);
3325 dFdXpE[(i + 1) * ncol] += tmp;
3327 dFdXpB[(i + 1) * ncol] +=
3328 transIJ * (-bk.
rhoP[bId_np_j] * dGamma) / 2;
3329 dFdXpE[(i + 1) * ncol] +=
3330 transIJ * (-bk.
rhoP[eId_np_j] * dGamma) / 2;
3332 dFdXpB[(i + 1) * ncol] += tmp;
3334 dFdXpE[(i + 1) * ncol] += tmp;
3343 for (
USI j1 = 0; j1 < np; j1++) {
3344 if (phasedS_B[j1]) {
3345 dFdXsB[(i + 1) * ncolB + j1SB] +=
3346 transIJ * bk.
dPcj_dS[bId_np_j * np + j1];
3347 tmp = Akd * xij * xi / mu * bk.
dKr_dS[uId_np_j * np + j1] *
3349 dFdXsB[(i + 1) * ncolB + j1SB] += tmp;
3352 if (phasedS_E[j1]) {
3353 dFdXsE[(i + 1) * ncolE + j1SE] -=
3354 transIJ * bk.
dPcj_dS[eId_np_j * np + j1];
3359 if (!phaseExistE[j]) {
3360 for (
USI k = 0; k < pVnumComB[j]; k++) {
3361 rhox = bk.
rhox[uId_np_j * nc + k];
3362 xix = bk.
xix[uId_np_j * nc + k];
3363 mux = bk.
mux[uId_np_j * nc + k];
3364 tmp = -transIJ * rhox * dGamma;
3365 tmp += xij * transJ * xix * dP;
3366 tmp += -transIJ * mux / mu * dP;
3367 tmp -= transIJ * dP / bk.
nj[uId_np_j];
3368 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
3371 if (i < pVnumComB[j])
3372 dFdXsB[(i + 1) * ncolB + jxB + i] +=
3373 xi * transJ * dP / bk.
nj[uId_np_j];
3375 for (
USI k = 0; k < pVnumComB[j]; k++) {
3376 rhox = bk.
rhox[bId_np_j * nc + k] / 2;
3377 xix = bk.
xix[uId_np_j * nc + k];
3378 mux = bk.
mux[uId_np_j * nc + k];
3379 tmp = -transIJ * rhox * dGamma;
3380 tmp += xij * transJ * xix * dP;
3381 tmp += -transIJ * mux / mu * dP;
3382 tmp -= transIJ * dP / bk.
nj[uId_np_j];
3383 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
3384 dFdXsE[(i + 1) * ncolE + jxE + k] +=
3385 -transIJ * bk.
rhox[eId_np_j * nc + k] / 2 * dGamma;
3388 if (i < pVnumComB[j])
3389 dFdXsB[(i + 1) * ncolB + jxB + i] +=
3390 xi * transJ * dP / bk.
nj[uId_np_j];
3394 for (
USI j1 = 0; j1 < np; j1++) {
3395 if (phasedS_B[j1]) {
3396 dFdXsB[(i + 1) * ncolB + j1SB] +=
3397 transIJ * bk.
dPcj_dS[bId_np_j * np + j1];
3400 if (phasedS_E[j1]) {
3401 dFdXsE[(i + 1) * ncolE + j1SE] -=
3402 transIJ * bk.
dPcj_dS[eId_np_j * np + j1];
3403 tmp = Akd * xij * xi / mu * bk.
dKr_dS[uId_np_j * np + j1] *
3405 dFdXsE[(i + 1) * ncolE + j1SE] += tmp;
3410 if (!phaseExistB[j]) {
3411 for (
USI k = 0; k < pVnumComE[j]; k++) {
3412 rhox = bk.
rhox[uId_np_j * nc + k];
3413 xix = bk.
xix[uId_np_j * nc + k];
3414 mux = bk.
mux[uId_np_j * nc + k];
3415 tmp = -transIJ * rhox * dGamma;
3416 tmp += xij * transJ * xix * dP;
3417 tmp += -transIJ * mux / mu * dP;
3418 tmp -= transIJ * dP / bk.
nj[uId_np_j];
3419 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
3422 if (i < pVnumComE[j])
3423 dFdXsE[(i + 1) * ncolE + jxE + i] +=
3424 xi * transJ * dP / bk.
nj[uId_np_j];
3426 for (
USI k = 0; k < pVnumComE[j]; k++) {
3427 rhox = bk.
rhox[eId_np_j * nc + k] / 2;
3428 xix = bk.
xix[uId_np_j * nc + k];
3429 mux = bk.
mux[uId_np_j * nc + k];
3430 tmp = -transIJ * rhox * dGamma;
3431 tmp += xij * transJ * xix * dP;
3432 tmp += -transIJ * mux / mu * dP;
3433 tmp -= transIJ * dP / bk.
nj[uId_np_j];
3434 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
3435 dFdXsB[(i + 1) * ncolB + jxB + k] +=
3436 -transIJ * bk.
rhox[bId_np_j * nc + k] / 2 * dGamma;
3439 if (i < pVnumComE[j])
3440 dFdXsE[(i + 1) * ncolE + jxE + i] +=
3441 xi * transJ * dP / bk.
nj[uId_np_j];
3445 jxB += pVnumComB[j];
3446 jxE += pVnumComE[j];
3452 fill(tmpb.begin(), tmpb.end(), 0.0);
3453 DaAxpby(ncol, ncolB, -1.0, dFdXsB.data(), &bk.
res_n[bId * ncol2], 1.0,
3460 DaABpbC(ncol, ncol, ncolB, 1, dFdXsB.data(), &bk.
dSec_dPri[bId * lendSdP], 1,
3462 Dscalar(bsize, dt, bmat.data());
3466 Dscalar(bsize, -1, bmat.data());
3470 if (!
CheckNan(bmat.size(), &bmat[0])) {
3478 fill(tmpb.begin(), tmpb.end(), 0.0);
3479 DaAxpby(ncol, ncolE, -1.0, dFdXsE.data(), &bk.
res_n[eId * ncol2], 1.0,
3486 DaABpbC(ncol, ncol, ncolE, 1, dFdXsE.data(), &bk.
dSec_dPri[eId * lendSdP], 1,
3488 Dscalar(bsize, dt, bmat.data());
3492 Dscalar(bsize, -1, bmat.data());
3496 if (!
CheckNan(bmat.size(), &bmat[0])) {
3533 const USI ncol = nc + 1;
3534 const USI ncol2 = np * nc + np;
3535 const USI bsize = ncol * ncol;
3536 const USI bsize2 = ncol * ncol2;
3539 vector<OCP_DBL> tmpb(ncol, 0);
3540 vector<OCP_DBL> bmat(bsize, 0);
3541 vector<OCP_DBL> bmat2(bsize, 0);
3542 vector<OCP_DBL> dQdXpB(bsize, 0);
3543 vector<OCP_DBL> dQdXpW(bsize, 0);
3544 vector<OCP_DBL> dQdXsB(bsize2, 0);
3545 vector<char> phaseExistB(np, OCP_FALSE);
3546 vector<USI> pVnumComB(np, 0);
3547 vector<char> phasedS_B(np, OCP_FALSE);
3555 for (
USI p = 0; p < wl.PerfNum(); p++) {
3556 const OCP_USI n = wl.PerfLocation(p);
3557 fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
3558 fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
3559 fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
3561 dP = bk.
P[n] - wl.BHP() - wl.DG(p);
3566 for (
USI j = 0; j < np; j++) {
3569 if (phasedS_B[j]) jxB++;
3570 pVnumComB[j] = bk.
pVnumCom[n * np + j];
3571 ncolB += pVnumComB[j];
3575 for (
USI j = 0; j < np; j++) {
3577 if (!phaseExistB[j]) {
3578 jxB += pVnumComB[j];
3582 n_np_j = n * np + j;
3584 muP = bk.
muP[n_np_j];
3586 for (
USI i = 0; i < nc; i++) {
3588 transIJ = wl.PerfTransj(p, j) * wl.PerfXi(p) * wl.InjZi(i);
3589 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
3590 dQdXpW[(i + 1) * ncol] += -transIJ;
3594 for (
USI j1 = 0; j1 < np; j1++) {
3595 if (phasedS_B[j1]) {
3596 dQdXsB[(i + 1) * ncolB + j1B] +=
3597 CONV1 * wl.PerfWI(p) * wl.PerfMultiplier(p) * wl.PerfXi(p) *
3598 wl.InjZi(i) * bk.
dKr_dS[n_np_j * np + j1] * dP / mu;
3604 for (
USI k = 0; k < pVnumComB[j]; k++) {
3605 dQdXsB[(i + 1) * ncolB + jxB + k] +=
3606 -transIJ * dP / mu * bk.
mux[n_np_j * nc + k];
3609 jxB += pVnumComB[j];
3615 fill(tmpb.begin(), tmpb.end(), 0.0);
3616 DaAxpby(ncol, ncolB, -1.0, dQdXsB.data(), &bk.
res_n[n * ncol2], 1.0,
3623 DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &bk.
dSec_dPri[n * lendSdP], 1,
3625 Dscalar(bsize, dt, bmat.data());
3630 Dscalar(bsize, dt, bmat.data());
3634 switch (wl.OptMode()) {
3641 fill(bmat.begin(), bmat.end(), 0.0);
3642 for (
USI i = 0; i < nc; i++) {
3643 bmat[0] += dQdXpW[(i + 1) * ncol];
3644 bmat[(i + 1) * ncol + i + 1] = 1;
3652 fill(bmat2.begin(), bmat2.end(), 0.0);
3653 for (
USI i = 0; i < nc; i++) {
3654 Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
3661 fill(bmat.begin(), bmat.end(), 0.0);
3662 for (
USI i = 0; i < ncol; i++) {
3663 bmat[i * ncol + i] = 1;
3668 fill(bmat.begin(), bmat.end(), 0.0);
3687 const USI ncol = nc + 1;
3688 const USI ncol2 = np * nc + np;
3689 const USI bsize = ncol * ncol;
3690 const USI bsize2 = ncol * ncol2;
3693 vector<OCP_DBL> tmpb(ncol, 0);
3694 vector<OCP_DBL> bmat(bsize, 0);
3695 vector<OCP_DBL> bmat2(bsize, 0);
3696 vector<OCP_DBL> dQdXpB(bsize, 0);
3697 vector<OCP_DBL> dQdXpW(bsize, 0);
3698 vector<OCP_DBL> dQdXsB(bsize2, 0);
3699 vector<char> phaseExistB(np, OCP_FALSE);
3700 vector<char> phasedS_B(np, OCP_FALSE);
3701 vector<USI> pVnumComB(np, 0);
3704 OCP_DBL xij, xi, mu, muP, xiP, dP, transIJ, tmp;
3712 for (
USI p = 0; p < wl.PerfNum(); p++) {
3713 OCP_USI n = wl.PerfLocation(p);
3714 fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
3715 fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
3716 fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
3721 for (
USI j = 0; j < np; j++) {
3724 if (phasedS_B[j]) jxB++;
3725 pVnumComB[j] = bk.
pVnumCom[n * np + j];
3726 ncolB += pVnumComB[j];
3730 for (
USI j = 0; j < np; j++) {
3732 if (!phaseExistB[j]) {
3733 jxB += pVnumComB[j];
3737 n_np_j = n * np + j;
3738 dP = bk.
Pj[n_np_j] - wl.BHP() - wl.DG(p);
3741 muP = bk.
muP[n_np_j];
3742 xiP = bk.
xiP[n_np_j];
3744 for (
USI i = 0; i < nc; i++) {
3745 xij = bk.
xij[n_np_j * nc + i];
3747 transIJ = wl.PerfTransj(p, j) * xi * xij;
3748 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu) +
3749 dP * wl.PerfTransj(p, j) * xij * xiP;
3750 dQdXpW[(i + 1) * ncol] += -transIJ;
3754 for (
USI j1 = 0; j1 < np; j1++) {
3755 if (phasedS_B[j1]) {
3756 tmp =
CONV1 * wl.PerfWI(p) * wl.PerfMultiplier(p) * dP / mu *
3757 xi * xij * bk.
dKr_dS[n_np_j * np + j1];
3759 tmp += transIJ * bk.
dPcj_dS[n_np_j * np + j1];
3760 dQdXsB[(i + 1) * ncolB + j1B] += tmp;
3765 for (
USI k = 0; k < pVnumComB[j]; k++) {
3766 tmp = dP * wl.PerfTransj(p, j) * xij *
3767 (bk.
xix[n_np_j * nc + k] - xi / mu * bk.
mux[n_np_j * nc + k]);
3768 tmp -= transIJ * dP / bk.
nj[n_np_j];
3769 dQdXsB[(i + 1) * ncolB + jxB + k] += tmp;
3772 if (i < pVnumComB[j])
3773 dQdXsB[(i + 1) * ncolB + jxB + i] +=
3774 wl.PerfTransj(p, j) * xi * dP / bk.
nj[n_np_j];
3776 jxB += pVnumComB[j];
3782 fill(tmpb.begin(), tmpb.end(), 0.0);
3783 DaAxpby(ncol, ncolB, -1.0, dQdXsB.data(), &bk.
res_n[n * ncol2], 1.0,
3790 DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &bk.
dSec_dPri[n * lendSdP], 1,
3792 Dscalar(bsize, dt, bmat.data());
3796 Dscalar(bsize, dt, bmat.data());
3800 switch (wl.OptMode()) {
3807 fill(bmat.begin(), bmat.end(), 0.0);
3808 for (
USI i = 0; i < nc; i++) {
3809 bmat[0] += dQdXpW[(i + 1) * ncol] * wl.ProdWeight(i);
3810 bmat[(i + 1) * ncol + i + 1] = 1;
3818 fill(bmat2.begin(), bmat2.end(), 0.0);
3819 for (
USI i = 0; i < nc; i++) {
3820 Daxpy(ncol, wl.ProdWeight(i), bmat.data() + (i + 1) * ncol,
3828 fill(bmat.begin(), bmat.end(), 0.0);
3829 for (
USI i = 0; i < ncol; i++) {
3830 bmat[i * ncol + i] = 1;
3835 fill(bmat.begin(), bmat.end(), 0.0);
3848 const vector<OCP_DBL>& u,
3865 const USI row = np * (nc + 1);
3866 const USI col = nc + 1;
3867 vector<OCP_DBL> dtmp(row, 0);
3868 vector<OCP_DBL> tmpNij(np * nc, 0);
3880 for (
OCP_USI n = 0; n < nb; n++) {
3881 const vector<OCP_DBL>& scm = bk.
satcm[bk.
SATNUM[n]];
3902 for (
USI j = 0; j < np; j++) {
3903 n_np_j = n * np + j;
3905 dSmax = max(fabs(dtmp[js]), dSmax);
3911 if (dSmax > dSmaxlim) {
3912 chop = min(chop, dSmaxlim / dSmax);
3916 for (
USI j = 0; j < np; j++) {
3917 n_np_j = n * np + j;
3919 if (fabs(bk.
S[n_np_j] - scm[j]) >
TINY &&
3920 (bk.
S[n_np_j] - scm[j]) / (chop * dtmp[js]) < 0)
3921 chop *= min(1.0, -((bk.
S[n_np_j] - scm[j]) / (chop * dtmp[js])));
3922 if (bk.
S[n_np_j] + chop * dtmp[js] < 0)
3923 chop *= min(1.0, -bk.
S[n_np_j] / (chop * dtmp[js]));
3929 fill(tmpNij.begin(), tmpNij.end(), 0.0);
3934 for (
USI j = 0; j < np; j++) {
3935 n_np_j = n * np + j;
3937 bk.
dSNRP[n_np_j] = chop * dtmp[js];
3945 Daxpy(nc, bk.
nj[n_np_j], &bk.
xij[n_np_j * nc], &tmpNij[j * nc]);
3947 tmpNij[j * nc + i] += chop * dtmp[jx + i];
3950 bk.
nj[n_np_j] =
Dnorm1(nc, &tmpNij[j * nc]);
3951 for (
USI i = 0; i < nc; i++) {
3952 bk.
xij[n_np_j * nc + i] = tmpNij[j * nc + i] / bk.
nj[n_np_j];
3981 for (
USI i = 0; i < nc; i++) {
3982 bk.
dNNR[n * nc + i] = u[n * col + 1 + i] * chop;
3983 if (fabs(bk.
NRdNmax) < fabs(bk.
dNNR[n * nc + i]) / bk.
Nt[n])
3985 bk.
Ni[n * nc + i] += bk.
dNNR[n * nc + i];
3993 wl.SetBHP(wl.BHP() + u[wId]);
4046 CalRes(rs, dt, OCP_TRUE);
4065 IsoT_FIM::AssembleMatWellsNew(ls, rs, dt);
4079 int status = ls.
Solve();
4100 OCP_DBL& dt = ctrl.current_dt;
4103 if (!ctrl.Check(rs, {
"BulkNi",
"BulkP"})) {
4105 cout <<
"Cut time step size and repeat! current dt = " << fixed
4106 << setprecision(3) << dt <<
" days\n";
4119 CalRes(rs, dt, OCP_FALSE);
4140 (fabs(NRdPmax) <= ctrl.ctrlNR.
NRdPmin &&
4141 fabs(NRdSmax) <= ctrl.ctrlNR.
NRdSmin)) {
4143 if (!ctrl.Check(rs, {
"WellP"})) {
4152 }
else if (ctrl.iterNR > ctrl.ctrlNR.
maxNRiter) {
4153 ctrl.current_dt *= ctrl.ctrlTime.
cutFacNR;
4155 cout <<
"### WARNING: NR not fully converged! Cut time step size and repeat! "
4157 << fixed << setprecision(3) << ctrl.current_dt <<
" days\n";
4170 ctrl.CalNextTimeStep(rs, {
"dP",
"dS",
"iter"});
4183 bk.
vj.resize(nb * np);
4184 bk.
lvj.resize(nb * np);
4186 bk.
xijNR.resize(nb * np * nc);
4187 bk.
cfl.resize(nb * np);
4188 bk.bulkTypeAIM.Setup(nb);
4199 bk.bulkTypeAIM.Init();
4204 for (
OCP_USI n = 0; n < nb; n++) {
4209 for (
USI j = 0; j < np; j++) {
4210 if (bk.
cfl[bIdp + j] > 0.8) {
4223 if (!flag && OCP_FALSE) {
4225 if (fabs(bk.
dPNR[n] / bk.
P[n]) > 1E-3) {
4231 if (fabs(bk.
dNNR[bIdc + i] / bk.
Ni[bIdc + i]) > 1E-3) {
4244 bk.bulkTypeAIM.SetBulkType(v, 1);
4252 for (
auto& v1 : conn.
neighbor[v]) bk.bulkTypeAIM.SetBulkType(v1, 1);
4263 for (
OCP_USI n = 0; n < nb; n++) {
4264 if (bk.bulkTypeAIM.IfIMPECbulk(n)) {
4269 &bk.
xijNR[n * np * nc], n);
4282 for (
OCP_USI n = 0; n < nb; n++) {
4283 if (bk.bulkTypeAIM.IfIMPECbulk(n)) {
4302 for (
OCP_USI n = 0; n < nb; n++) {
4303 if (bk.bulkTypeAIM.IfFIMbulk(n)) {
4308 &bk.
xij[n * np * nc], n);
4310 for (
USI j = 0; j < np; j++) {
4311 bk.
vj[n * np + j] = bk.
vf[n] * bk.
S[n * np + j];
4330 for (
USI i = 0; i < nc; i++) {
4331 bk.
vfi[n * nc + i] = bk.
flashCal[pvtnum]->GetVfi(i);
4335 for (
USI j = 0; j < np; j++) {
4336 if (bk.
flashCal[pvtnum]->GetPhaseExist(j)) {
4341 for (
USI i = 0; i < nc; i++) {
4342 bk.
xijNR[bIdp * nc + j * nc + i] = bk.
flashCal[pvtnum]->GetXij(j, i);
4353 for (
OCP_USI n = 0; n < nb; n++) {
4354 if (bk.bulkTypeAIM.IfIMPECbulk(n)) {
4357 bk.
flow[bk.
SATNUM[n]]->CalKrPc(&bk.
S[bId], &bk.
kr[bId], &bk.
Pc[bId], n);
4358 for (
USI j = 0; j < np; j++) bk.
Pj[bId + j] = bk.
P[n] + bk.
Pc[bId + j];
4368 for (
OCP_USI n = 0; n < nb; n++) {
4369 if (bk.bulkTypeAIM.IfFIMbulk(n)) {
4372 bk.
flow[bk.
SATNUM[n]]->CalKrPcDeriv(&bk.
S[bId], &bk.
kr[bId], &bk.
Pc[bId],
4375 for (
USI j = 0; j < np; j++) bk.
Pj[bId + j] = bk.
P[n] + bk.
Pc[bId + j];
4389 const USI ncol = nc + 1;
4390 const USI ncol2 = np * nc + np;
4391 const USI bsize = ncol * ncol;
4392 const USI bsize2 = ncol * ncol2;
4397 vector<OCP_DBL> bmat(bsize, 0);
4399 for (
USI i = 1; i < nc + 1; i++) {
4400 bmat[i * ncol + i] = 1;
4402 for (
OCP_USI n = 0; n < nb; n++) {
4403 bmat[0] = bk.
v[n] * bk.
poroP[n] - bk.
vfP[n];
4404 for (
USI i = 0; i < nc; i++) {
4405 bmat[i + 1] = -bk.
vfi[n * nc + i];
4413 vector<OCP_DBL> dFdXpB(bsize, 0);
4414 vector<OCP_DBL> dFdXpE(bsize, 0);
4415 vector<OCP_DBL> dFdXsB(bsize2, 0);
4416 vector<OCP_DBL> dFdXsE(bsize2, 0);
4419 vector<OCP_BOOL> phaseExistB(np, OCP_FALSE);
4420 vector<OCP_BOOL> phaseExistE(np, OCP_FALSE);
4421 vector<OCP_BOOL> phaseExistI(np, OCP_FALSE);
4423 vector<OCP_BOOL> phasedS_B(np, OCP_FALSE);
4424 vector<OCP_BOOL> phasedS_E(np, OCP_FALSE);
4425 vector<OCP_BOOL> phasedS_I(np, OCP_FALSE);
4426 vector<USI> pVnumComB(np, 0);
4427 vector<USI> pVnumComE(np, 0);
4428 vector<USI> pVnumComI(np, 0);
4432 OCP_USI bId_np_j, eId_np_j, uId_np_j, ibId_np_j;
4433 OCP_DBL kr, mu, xi, xij, rhoP, xiP, muP, rhox, xix, mux;
4443 bIdFIM = eIdFIM = OCP_FALSE;
4444 if (bk.bulkTypeAIM.IfFIMbulk(bId)) bIdFIM = OCP_TRUE;
4445 if (bk.bulkTypeAIM.IfFIMbulk(eId)) eIdFIM = OCP_TRUE;
4447 if (!bIdFIM && !eIdFIM) {
4449 fill(dFdXpB.begin(), dFdXpB.end(), 0.0);
4450 fill(dFdXpE.begin(), dFdXpE.end(), 0.0);
4451 for (
USI j = 0; j < np; j++) {
4452 phaseExistB[j] = bk.
phaseExist[bId * np + j];
4453 phaseExistE[j] = bk.
phaseExist[eId * np + j];
4454 uId = conn.
upblock[c * np + j];
4455 phaseExistU = (uId == bId ? phaseExistB[j] : phaseExistE[j]);
4459 bId_np_j = bId * np + j;
4460 eId_np_j = eId * np + j;
4461 uId_np_j = uId * np + j;
4462 xi = bk.
xi[uId_np_j];
4463 kr = bk.
kr[uId_np_j];
4464 mu = bk.
mu[uId_np_j];
4465 transJ = Akd * xi * kr / mu;
4466 for (
USI i = 0; i < nc; i++) {
4467 xij = bk.
xij[uId_np_j * nc + i];
4468 transIJ = xij * transJ;
4470 dFdXpB[(i + 1) * ncol] += transIJ;
4471 dFdXpE[(i + 1) * ncol] -= transIJ;
4474 }
else if ((bIdFIM && !eIdFIM) || (!bIdFIM && eIdFIM)) {
4477 fill(dFdXpB.begin(), dFdXpB.end(), 0.0);
4478 fill(dFdXpE.begin(), dFdXpE.end(), 0.0);
4479 fill(dFdXsB.begin(), dFdXsB.end(), 0.0);
4480 fill(dFdXsE.begin(), dFdXsE.end(), 0.0);
4485 for (
USI j = 0; j < np; j++) {
4486 phaseExistI[j] = bk.
phaseExist[bId * np + j];
4488 if (phasedS_I[j]) jxI++;
4489 pVnumComI[j] = bk.
pVnumCom[bId * np + j];
4490 ncolI += pVnumComI[j];
4492 dFdXpI = &dFdXpB[0];
4493 dFdXsI = &dFdXsB[0];
4495 for (
USI j = 0; j < np; j++) {
4496 phaseExistI[j] = bk.
phaseExist[eId * np + j];
4498 if (phasedS_I[j]) jxI++;
4499 pVnumComI[j] = bk.
pVnumCom[eId * np + j];
4500 ncolI += pVnumComI[j];
4502 dFdXpI = &dFdXpE[0];
4503 dFdXsI = &dFdXsE[0];
4507 for (
USI j = 0; j < np; j++) {
4508 phaseExistB[j] = bk.
phaseExist[bId * np + j];
4509 phaseExistE[j] = bk.
phaseExist[eId * np + j];
4510 uId = conn.
upblock[c * np + j];
4511 phaseExistU = (uId == bId ? phaseExistB[j] : phaseExistE[j]);
4516 bId_np_j = bId * np + j;
4517 eId_np_j = eId * np + j;
4518 uId_np_j = uId * np + j;
4519 dP = bk.
Pj[bId_np_j] - bk.
Pj[eId_np_j] -
4521 xi = bk.
xi[uId_np_j];
4522 kr = bk.
kr[uId_np_j];
4523 mu = bk.
mu[uId_np_j];
4524 transJ = Akd * kr / mu;
4525 uIdFIM = (uId == bId ? bIdFIM : eIdFIM);
4528 ibId_np_j = bId_np_j;
4530 ibId_np_j = eId_np_j;
4535 if (phaseExistB[j] && phaseExistE[j]) rhoWgt = 0.5;
4537 muP = bk.
muP[ibId_np_j];
4538 xiP = bk.
xiP[ibId_np_j];
4539 rhoP = bk.
rhoP[ibId_np_j];
4540 for (
USI i = 0; i < nc; i++) {
4541 xij = bk.
xij[ibId_np_j * nc + i];
4542 transIJ = xij * xi * transJ;
4545 dFdXpB[(i + 1) * ncol] += transIJ;
4546 dFdXpE[(i + 1) * ncol] -= transIJ;
4548 tmp = transIJ * (-rhoP * dGamma) * rhoWgt;
4549 tmp += xij * transJ * xiP * dP;
4550 tmp += -transIJ * muP / mu * dP;
4551 dFdXpI[(i + 1) * ncol] += tmp;
4555 for (
USI j1 = 0; j1 < np; j1++) {
4556 if (phasedS_I[j1]) {
4557 dFdXsI[(i + 1) * ncolI + j1S] +=
4558 transIJ * bk.
dPcj_dS[ibId_np_j * np + j1];
4559 tmp = Akd * xij * xi / mu *
4560 bk.
dKr_dS[ibId_np_j * np + j1] * dP;
4561 dFdXsI[(i + 1) * ncolI + j1S] += tmp;
4566 for (
USI k = 0; k < pVnumComI[j]; k++) {
4567 rhox = bk.
rhox[ibId_np_j * nc + k] * rhoWgt;
4568 xix = bk.
xix[ibId_np_j * nc + k];
4569 mux = bk.
mux[ibId_np_j * nc + k];
4570 tmp = -transIJ * rhox * dGamma;
4571 tmp += xij * transJ * xix * dP;
4572 tmp += -transIJ * mux / mu * dP;
4573 dFdXsI[(i + 1) * ncolI + jxI + k] += tmp;
4576 if (i < pVnumComI[j])
4577 dFdXsI[(i + 1) * ncolI + jxI + i] += xi * transJ * dP;
4579 jxI += pVnumComI[j];
4583 if (phaseExistB[j] && phaseExistE[j]) rhoWgt = 0.5;
4584 rhoP = bk.
rhoP[ibId_np_j];
4586 for (
USI i = 0; i < nc; i++) {
4587 xij = bk.
xij[uId_np_j * nc + i];
4588 transIJ = xij * xi * transJ;
4591 dFdXpB[(i + 1) * ncol] += transIJ;
4592 dFdXpE[(i + 1) * ncol] -= transIJ;
4594 tmp = transIJ * (-rhoP * dGamma) * rhoWgt;
4595 dFdXpI[(i + 1) * ncol] += tmp;
4599 for (
USI j1 = 0; j1 < np; j1++) {
4600 if (phasedS_I[j1]) {
4601 dFdXsI[(i + 1) * ncolI + j1S] +=
4602 transIJ * bk.
dPcj_dS[ibId_np_j * np + j1];
4607 for (
USI k = 0; k < pVnumComI[j]; k++) {
4608 rhox = bk.
rhox[ibId_np_j * nc + k] * rhoWgt;
4609 tmp = -transIJ * rhox * dGamma;
4610 dFdXsI[(i + 1) * ncolI + jxI + k] += tmp;
4613 jxI += pVnumComI[j];
4618 fill(dFdXpB.begin(), dFdXpB.end(), 0.0);
4619 fill(dFdXpE.begin(), dFdXpE.end(), 0.0);
4620 fill(dFdXsB.begin(), dFdXsB.end(), 0.0);
4621 fill(dFdXsE.begin(), dFdXsE.end(), 0.0);
4628 for (
USI j = 0; j < np; j++) {
4629 phaseExistB[j] = bk.
phaseExist[bId * np + j];
4630 phaseExistE[j] = bk.
phaseExist[eId * np + j];
4633 if (phasedS_B[j]) jxB++;
4634 if (phasedS_E[j]) jxE++;
4635 pVnumComB[j] = bk.
pVnumCom[bId * np + j];
4636 pVnumComE[j] = bk.
pVnumCom[eId * np + j];
4637 ncolB += pVnumComB[j];
4638 ncolE += pVnumComE[j];
4643 for (
USI j = 0; j < np; j++) {
4644 uId = conn.
upblock[c * np + j];
4646 phaseExistU = (uId == bId ? phaseExistB[j] : phaseExistE[j]);
4648 jxB += pVnumComB[j];
4649 jxE += pVnumComE[j];
4653 bId_np_j = bId * np + j;
4654 eId_np_j = eId * np + j;
4655 uId_np_j = uId * np + j;
4656 dP = bk.
Pj[bId_np_j] - bk.
Pj[eId_np_j] -
4658 xi = bk.
xi[uId_np_j];
4659 kr = bk.
kr[uId_np_j];
4660 mu = bk.
mu[uId_np_j];
4661 muP = bk.
muP[uId_np_j];
4662 xiP = bk.
xiP[uId_np_j];
4663 rhoP = bk.
rhoP[uId_np_j];
4664 transJ = Akd * kr / mu;
4666 for (
USI i = 0; i < nc; i++) {
4667 xij = bk.
xij[uId_np_j * nc + i];
4668 transIJ = xij * xi * transJ;
4671 dFdXpB[(i + 1) * ncol] += transIJ;
4672 dFdXpE[(i + 1) * ncol] -= transIJ;
4674 tmp = xij * transJ * xiP * dP;
4675 tmp += -transIJ * muP / mu * dP;
4676 if (!phaseExistE[j]) {
4677 tmp += transIJ * (-rhoP * dGamma);
4678 dFdXpB[(i + 1) * ncol] += tmp;
4679 }
else if (!phaseExistB[j]) {
4680 tmp += transIJ * (-rhoP * dGamma);
4681 dFdXpE[(i + 1) * ncol] += tmp;
4683 dFdXpB[(i + 1) * ncol] +=
4684 transIJ * (-bk.
rhoP[bId_np_j] * dGamma) / 2;
4685 dFdXpE[(i + 1) * ncol] +=
4686 transIJ * (-bk.
rhoP[eId_np_j] * dGamma) / 2;
4688 dFdXpB[(i + 1) * ncol] += tmp;
4690 dFdXpE[(i + 1) * ncol] += tmp;
4699 for (
USI j1 = 0; j1 < np; j1++) {
4700 if (phasedS_B[j1]) {
4701 dFdXsB[(i + 1) * ncolB + j1SB] +=
4702 transIJ * bk.
dPcj_dS[bId_np_j * np + j1];
4703 tmp = Akd * xij * xi / mu *
4704 bk.
dKr_dS[uId_np_j * np + j1] * dP;
4705 dFdXsB[(i + 1) * ncolB + j1SB] += tmp;
4708 if (phasedS_E[j1]) {
4709 dFdXsE[(i + 1) * ncolE + j1SE] -=
4710 transIJ * bk.
dPcj_dS[eId_np_j * np + j1];
4715 if (!phaseExistE[j]) {
4716 for (
USI k = 0; k < pVnumComB[j]; k++) {
4717 rhox = bk.
rhox[uId_np_j * nc + k];
4718 xix = bk.
xix[uId_np_j * nc + k];
4719 mux = bk.
mux[uId_np_j * nc + k];
4720 tmp = -transIJ * rhox * dGamma;
4721 tmp += xij * transJ * xix * dP;
4722 tmp += -transIJ * mux / mu * dP;
4723 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
4726 if (i < pVnumComB[j])
4727 dFdXsB[(i + 1) * ncolB + jxB + i] += xi * transJ * dP;
4729 for (
USI k = 0; k < pVnumComB[j]; k++) {
4730 rhox = bk.
rhox[bId_np_j * nc + k] / 2;
4731 xix = bk.
xix[uId_np_j * nc + k];
4732 mux = bk.
mux[uId_np_j * nc + k];
4733 tmp = -transIJ * rhox * dGamma;
4734 tmp += xij * transJ * xix * dP;
4735 tmp += -transIJ * mux / mu * dP;
4736 dFdXsB[(i + 1) * ncolB + jxB + k] += tmp;
4737 dFdXsE[(i + 1) * ncolE + jxE + k] +=
4738 -transIJ * bk.
rhox[eId_np_j * nc + k] / 2 * dGamma;
4741 if (i < pVnumComB[j])
4742 dFdXsB[(i + 1) * ncolB + jxB + i] += xi * transJ * dP;
4746 for (
USI j1 = 0; j1 < np; j1++) {
4747 if (phasedS_B[j1]) {
4748 dFdXsB[(i + 1) * ncolB + j1SB] +=
4749 transIJ * bk.
dPcj_dS[bId_np_j * np + j1];
4752 if (phasedS_E[j1]) {
4753 dFdXsE[(i + 1) * ncolE + j1SE] -=
4754 transIJ * bk.
dPcj_dS[eId_np_j * np + j1];
4755 tmp = Akd * xij * xi / mu *
4756 bk.
dKr_dS[uId_np_j * np + j1] * dP;
4757 dFdXsE[(i + 1) * ncolE + j1SE] += tmp;
4762 if (!phaseExistB[j]) {
4763 for (
USI k = 0; k < pVnumComE[j]; k++) {
4764 rhox = bk.
rhox[uId_np_j * nc + k];
4765 xix = bk.
xix[uId_np_j * nc + k];
4766 mux = bk.
mux[uId_np_j * nc + k];
4767 tmp = -transIJ * rhox * dGamma;
4768 tmp += xij * transJ * xix * dP;
4769 tmp += -transIJ * mux / mu * dP;
4770 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
4773 if (i < pVnumComE[j])
4774 dFdXsE[(i + 1) * ncolE + jxE + i] += xi * transJ * dP;
4776 for (
USI k = 0; k < pVnumComE[j]; k++) {
4777 rhox = bk.
rhox[eId_np_j * nc + k] / 2;
4778 xix = bk.
xix[uId_np_j * nc + k];
4779 mux = bk.
mux[uId_np_j * nc + k];
4780 tmp = -transIJ * rhox * dGamma;
4781 tmp += xij * transJ * xix * dP;
4782 tmp += -transIJ * mux / mu * dP;
4783 dFdXsE[(i + 1) * ncolE + jxE + k] += tmp;
4784 dFdXsB[(i + 1) * ncolB + jxB + k] +=
4785 -transIJ * bk.
rhox[bId_np_j * nc + k] / 2 * dGamma;
4788 if (i < pVnumComE[j])
4789 dFdXsE[(i + 1) * ncolE + jxE + i] += xi * transJ * dP;
4793 jxB += pVnumComB[j];
4794 jxE += pVnumComE[j];
4798 if (bIdFIM && !eIdFIM)
4800 else if (!bIdFIM && eIdFIM)
4809 Dscalar(bsize, dt, bmat.data());
4813 Dscalar(bsize, -1, bmat.data());
4817 if (!
CheckNan(bmat.size(), &bmat[0])) {
4828 Dscalar(bsize, dt, bmat.data());
4832 Dscalar(bsize, -1, bmat.data());
4836 if (!
CheckNan(bmat.size(), &bmat[0])) {
4844 const vector<OCP_DBL>& u,
4855 const USI row = np * (nc + 1);
4856 const USI col = nc + 1;
4857 vector<OCP_DBL> dtmp(row, 0);
4867 for (
OCP_USI n = 0; n < nb; n++) {
4868 if (bk.bulkTypeAIM.IfIMPECbulk(n)) {
4877 for (
USI i = 0; i < nc; i++) {
4878 bk.
dNNR[n * nc + i] = u[n * col + 1 + i];
4879 bk.
Ni[n * nc + i] += bk.
dNNR[n * nc + i];
4886 for (
USI j = 0; j < np; j++) {
4887 bk.
Pj[n * np + j] = bk.
P[n] + bk.
Pc[n * np + j];
4894 fill(dtmp.begin(), dtmp.end(), 0.0);
4896 u.data() + n * col, 1, dtmp.data());
4899 for (
USI j = 0; j < np; j++) {
4903 n_np_j = n * np + j;
4906 if (fabs(dtmp[js]) > dSmaxlim) {
4907 choptmp = dSmaxlim / fabs(dtmp[js]);
4908 }
else if (bk.
S[n_np_j] + dtmp[js] < 0.0) {
4909 choptmp = 0.9 * bk.
S[n_np_j] / fabs(dtmp[js]);
4916 chopmin = min(chopmin, choptmp);
4922 for (
USI j = 0; j < np; j++) {
4924 bk.
dSNRP[n * np + j] = 0;
4927 bk.
dSNRP[n * np + j] = chopmin * dtmp[js];
4935 for (
USI j = 0; j < 2; j++) {
4936 bId = n * np * nc + j * nc;
4938 bk.
xij[bId + i] += chopmin * dtmp[js];
4953 for (
USI i = 0; i < nc; i++) {
4954 bk.
dNNR[n * nc + i] = u[n * col + 1 + i] * chopmin;
4955 if (fabs(bk.
NRdNmax) < fabs(bk.
dNNR[n * nc + i]) / bk.
Nt[n])
4958 bk.
Ni[n * nc + i] += bk.
dNNR[n * nc + i];
4970 wl.SetBHP(wl.BHP() + u[wId]);
void DaABpbC(const int &m, const int &n, const int &k, const double &alpha, const double *A, const double *B, const double &beta, double *C)
Computes C' = alpha B'A' + beta C', all matrices are column-major.
void Dscalar(const int &n, const double &alpha, double *x)
Scales a vector by a constant.
void DaAxpby(const int &m, const int &n, const double &a, const double *A, const double *x, const double &b, double *y)
Computes y = a A x + b y.
bool CheckNan(const int &N, const T *x)
check NaN
void Daxpy(const int &n, const double &alpha, const double *x, double *y)
Constant times a vector plus a vector.
double Dnorm1(const int &N, double *x)
Computes the L1-norm of a vector.
void Dcopy(const int &N, double *dst, const double *src)
Calculate the minimal eigenvalue for symmetric matrix with mkl lapack.
const USI VECTORFASP
Use vector linear solver in Fasp.
const OCP_DBL TINY
Small constant.
unsigned int USI
Generic unsigned integer.
double OCP_DBL
Double precision.
const OCP_DBL CONV1
1 bbl = CONV1 ft3
const OCP_DBL GRAVITY_FACTOR
0.00694444 ft2 psi / lb
const USI LRATE_MODE
Well option = fixed fluid rate???
const USI WRATE_MODE
Well option = fixed water rate.
const USI ORATE_MODE
Well option = fixed oil rate.
const USI RATE_MODE
Well option = fixed total rate???
unsigned int OCP_USI
Long unsigned integer.
const USI PROD
Well type = producer.
const USI SCALARFASP
Use scalar linear solver in Fasp.
const USI INJ
Well type = injector.
const USI BHP_MODE
Well option = fixed bottom-hole-pressure.
unsigned int OCP_BOOL
OCP_BOOL in OCP.
const USI GRATE_MODE
Well option = fixed gas rate.
const OCP_DBL CONV2
Darcy constant in field unit.
Declaration of solution methods for fluid part in OpenCAEPoro.
#define OCP_FUNCNAME
Print Function Name.
#define OCP_ABORT(msg)
Abort if critical error happens.
void CalFlux(const Bulk &myBulk)
Calculate volume flow rate and moles flow rate of each perforation.
vector< Well > wells
well set.
void CalTrans(const Bulk &myBulk)
Calculate Transmissibility of Wells.
void CaldG(const Bulk &myBulk)
Calculate dG.
void SetupWellBulk(Bulk &myBulk) const
Setup bulks which are penetrated by wells at current stage.
void InitBHP(const Bulk &myBulk)
Set the initial well pressure.
void PrepareWell(const Bulk &myBulk)
Calculate well properties at the beginning of each time step.
Properties and operations on connections between bulks (active grids).
OCP_USI numConn
Number of connections between bulks.
vector< OCP_USI > upblock
Index of upwinding bulk of connections : numConn * numPhase.
vector< OCP_DBL > upblock_Rho
Mass density of phase from upblock: numConn * numPhase.
vector< OCP_DBL > lupblock_Velocity
last upblock_Velocity
vector< OCP_DBL > upblock_Trans
Transmissibility of phase from upblock: numConn * numPhase.
vector< OCP_DBL > lupblock_Rho
last upblock_Rho
vector< OCP_DBL > upblock_Velocity
vector< vector< OCP_USI > > neighbor
Neighboring information of each bulk: activeGridNum.
vector< OCP_DBL > lupblock_Trans
last upblock_Trans
vector< BulkPair > iteratorConn
All connections (pair of indices) between bulks: numConn.
vector< OCP_USI > lupblock
last upblock
Physical information of each active reservoir bulk.
vector< OCP_DBL > mu
Viscosity of phase: numPhase*numBulk.
vector< USI > pVnumCom
num of variable components in the phase
vector< OCP_DBL > dNNR
Ni change between NR steps.
vector< OCP_DBL > lP
last P
vector< OCP_DBL > lS
last S
vector< OCP_DBL > NRstep
NRstep for FIM.
vector< Rock * > rock
rock model
vector< OCP_DBL > Pc
Capillary pressure of phase: numPhase*numBulk.
vector< FlowUnit * > flow
Vector for capillary pressure, relative perm.
vector< OCP_DBL > ldPcj_dS
last Pcj_dS
vector< OCP_DBL > lNt
last Nt
USI numPhase
Number of phase.
vector< OCP_DBL > lvf
last vf
vector< OCP_DBL > T
Temperature: numBulk.
vector< OCP_DBL > S
Saturation of phase: numPhase*numBulk.
vector< OCP_DBL > rho
Mass density of phase: numPhase*numBulk.
OCP_BOOL ifComps
If OCP_TRUE, compositional model will be used.
OCPRes res
Residual for all equations.
vector< OCP_DBL > dSec_dPri
d Secondary variable / d Primary variable.
vector< OCP_DBL > lxij
last xij
vector< OCP_DBL > rhoP
d Rho / d P: numPhase*numBulk.
vector< OCP_DBL > ntg
net to gross of bulk.
vector< OCP_DBL > lrho
last rho
vector< USI > PVTNUM
Identify PVT region in black-oil model: numBulk.
vector< USI > lphaseNum
last phaseNum
vector< OCP_DBL > vfi
d vf / d Ni: numCom*numBulk.
vector< USI > lpVnumCom
last pVnumCom
vector< OCP_DBL > poro
rock porosity * ntg.
vector< OCP_DBL > xij
Nij / Nj: numPhase*numCom*numBulk.
vector< OCP_DBL > lrockVp
Pore volume: numBulk.
vector< OCP_DBL > kr
Relative permeability of phase: numPhase*numBulk.
vector< USI > SATNUM
Identify SAT region: numBulk.
vector< OCP_DBL > depth
Depth of center of grid cells: activeGridNum.
vector< OCP_DBL > rockVp
pore volume = Vgrid * ntg * poro.
vector< OCP_DBL > Ni
Moles of component: numCom*numBulk.
OCP_DBL NRdPmax
Max pressure difference in an NR step.
vector< OCP_DBL > Pj
Pressure of phase: numPhase*numBulk.
vector< OCP_DBL > mux
d Muj / d xij: numPhase*numCom*numBulk.
vector< OCP_DBL > rhox
d Rhoj / d xij: numPhase*numCom*numBulk.
vector< OCP_DBL > lporoP
last poroP.
OCP_USI index_maxNRdSSP
index of grid which has maxNRdSSP
vector< OCP_DBL > lkr
last kr
vector< OCP_DBL > dSNR
saturation change between NR steps
vector< OCP_DBL > lvfi
last vfi
vector< OCP_DBL > lporo
last poro.
OCP_DBL maxNRdSSP
max difference between dSNR and dSNRP
vector< OCP_DBL > lvj
last vj
vector< OCP_DBL > Nt
Total moles of components in bulks: numBulk.
vector< OCP_DBL > muP
d Mu / d P: numPhase*numBulk.
vector< OCP_DBL > dKr_dS
d Krj / d Sk: numPhase * numPhase * bulk.
vector< OCP_DBL > lT
last T
vector< Mixture * > flashCal
Flash calculation class.
vector< OCP_BOOL > phaseExist
Existence of phase: numPhase*numBulk.
vector< OCP_DBL > lPj
last Pj
vector< OCP_DBL > xiP
d xi / d P: numPhase*numBulk.
vector< OCP_DBL > poroP
d poro / d P.
vector< vector< OCP_DBL > > satcm
critical saturation when phase becomes mobile / immobile.
vector< OCP_DBL > ldKr_dS
last dKr_dS
vector< OCP_DBL > lrhoP
last rhoP
vector< OCP_DBL > xi
Moles density of phase: numPhase*numBulk.
vector< OCP_DBL > lxi
last xi
vector< OCP_DBL > lmux
last mux
vector< OCP_DBL > vf
Total fluid volume: numBulk.
vector< USI > phaseNum
Num of hydrocarbon phase in each bulk.
vector< USI > bRowSizedSdP
length of dSec_dPri in each bulk
vector< OCP_DBL > vfP
d vf / d P: numBulk.
OCP_DBL NRdNmax
Max Ni difference in an NR step.
vector< OCP_DBL > lres_n
last res_n
vector< OCP_DBL > lxix
last xix
vector< OCP_DBL > lresPc
last lresPc;
OCP_BOOL IfUseEoS() const
Return ifUseEoS.
vector< OCP_DBL > dPNR
P change between NR steps.
vector< OCP_USI > wellBulkId
vector< OCP_DBL > vj
Volume of phase: numPhase*numBulk.
vector< OCP_DBL > lmuP
last muP
vector< OCP_DBL > lvfP
last vfP
vector< OCP_DBL > Pb
Bubble point pressure: numBulk.
vector< OCP_DBL > lrhox
last rhox
vector< OCP_BOOL > lphaseExist
last phaseExist
vector< OCP_DBL > v
Volume of grids: activeGridNum.
USI numComH
Number of HydroCarbon.
vector< OCP_DBL > dSNRP
predicted saturation change between NR steps
void InitPTSw(const USI &tabrow)
Calculate initial equilibrium – hydrostatic equilibration.
vector< OCP_DBL > lxiP
last xiP
vector< OCP_BOOL > lpSderExist
last pSderExist
vector< OCP_DBL > resPc
a precalculated value
vector< OCP_DBL > lmu
last mu
vector< OCP_BOOL > pSderExist
Existence of derivative of phase saturation.
OCP_USI numBulk
Number of bulks (active grids).
vector< USI > NRphaseNum
phaseNum in NR step
vector< OCP_DBL > poroInit
initial rock porosity * ntg.
vector< OCP_DBL > ldSec_dPri
last dSec_dPri
vector< OCP_DBL > xix
d Xi_j / d xij: numPhase*numCom*numBulk.
vector< USI > ROCKNUM
index of Rock table for each bulk
vector< OCP_DBL > nj
moles number of phase: numPhase*numBulk.
vector< OCP_DBL > dPcj_dS
d Pcj / d Sk: numPhase * numPhase * bulk.
vector< OCP_DBL > res_n
residual for FIM_n
vector< USI > lbRowSizedSdP
last bRowSizedSdP
vector< OCP_DBL > xijNR
store the current NR step's xij in AIM
vector< OCP_DBL > P
Pressure: numBulk.
vector< OCP_DBL > lNi
last Ni
vector< OCP_DBL > lnj
last nj
vector< OCP_DBL > cfl
CFL number for each bulk.
vector< OCP_DBL > lPc
last Pc
USI maxLendSdP
length of dSec_dPri.
USI numCom
Number of component.
OCP_DBL NRtol
Maximum non-linear convergence error.
OCP_DBL NRdSmin
Minimum Saturation change in a Newton iteration.
USI maxNRiter
Maximum number of Newton iterations in a time step.
OCP_DBL NRdSmax
Maximum Saturation change in a Newton iteration.
OCP_DBL NRdPmin
Minimum Pressure change in a Newton iteration.
OCP_DBL cutFacNR
Factor by which time step is cut after convergence failure.
Get elapsed wall-time in millisecond.
__inline__ double Stop() const
Stop the timer and return duration from start() in ms.
__inline__ void Start()
Start the timer.
void GetSolution(Reservoir &rs, const vector< OCP_DBL > &u, const OCPControl &ctrl) const
Update P, Ni, BHP after linear system is solved.
void AssembleMatBulks(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble linear system for bulks.
void CalFlashEa(Bulk &bk)
Perform flash calculation with Ni for Explicit bulk – Update all properties.
void SolveLinearSystem(LinearSystem &ls, Reservoir &rs, OCPControl &ctrl)
Solve the linear system.
void CalFlashEp(Bulk &bk)
Perform flash calculation with Ni for Explicit bulk – Update partial properties.
void CalKrPcI(Bulk &bk)
Calculate relative permeability and capillary pressure for Implicit bulk.
void Setup(Reservoir &rs, LinearSystem &ls, const OCPControl &ctrl)
Setup AIMc.
void AssembleMat(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble Matrix.
OCP_BOOL FinishNR(Reservoir &rs, OCPControl &ctrl)
Finish a Newton-Raphson iteration.
void CalFlashI(Bulk &bk)
Perform flash calculation with Ni for Implicit bulk.
void SetFIMBulk(Reservoir &rs)
Determine which bulk are treated Implicit.
OCP_BOOL UpdateProperty(Reservoir &rs, OCPControl &ctrl)
Update properties of fluids.
void UpdateLastTimeStep(Reservoir &rs) const
Update values of last step for AIMc.
void PassFlashValueEp(Bulk &bk, const OCP_USI &n)
Pass flash value needed for Explicit bulk – Update partial properties.
void CalKrPcE(Bulk &bk)
Calculate relative permeability and capillary pressure for Explicit bulk.
void ResetToLastTimeStep(Reservoir &rs, OCPControl &ctrl)
Reset variables to last time step.
void Prepare(Reservoir &rs, const OCP_DBL &dt)
Prepare for Assembling matrix.
void InitReservoir(Reservoir &rs) const
Init.
void FinishStep(Reservoir &rs, OCPControl &ctrl) const
Finish a time step.
void AllocateReservoir(Reservoir &rs)
Allocate memory for reservoir.
void Setup(Reservoir &rs, LinearSystem &ls, const OCPControl &ctrl)
Setup FIM.
void AssembleMat(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble Matrix.
void UpdateLastTimeStep(Reservoir &rs) const
Update values of last step for FIM.
void InitReservoir(Reservoir &rs) const
Init.
OCP_BOOL FinishNR(Reservoir &rs, OCPControl &ctrl)
Finish a Newton-Raphson iteration.
void AllocateLinearSystem(LinearSystem &ls, const Reservoir &rs, const OCPControl &ctrl)
Allocate memory for linear system.
void Prepare(Reservoir &rs, const OCP_DBL &dt)
Prepare for Assembling matrix.
void FinishStep(Reservoir &rs, OCPControl &ctrl)
Finish a time step.
void PassFlashValue(Bulk &bk, const OCP_USI &n) const
Pass value needed for FIM from flash to bulk.
void SolveLinearSystem(LinearSystem &ls, Reservoir &rs, OCPControl &ctrl) const
Solve the linear system.
OCP_BOOL UpdateProperty(Reservoir &rs, OCPControl &ctrl)
Update properties of fluids.
void CalRes(Reservoir &rs, const OCP_DBL &dt, const OCP_BOOL &resetRes0) const
Calculate residual.
void CalKrPc(Bulk &bk) const
Calculate relative permeability and capillary pressure needed for FIM.
void ResetToLastTimeStep(Reservoir &rs, OCPControl &ctrl)
Reset variables to last time step.
void AllocateReservoir(Reservoir &rs)
Allocate memory for reservoir.
void AssembleMatWells(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble linear system for wells.
void AssembleMatBulksNew(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble linear system for bulks.
void FinishStep(Reservoir &rs, OCPControl &ctrl) const
Finish a time step.
void Prepare(Reservoir &rs, const OCP_DBL &dt)
Prepare for Assembling matrix.
void AssembleMatProdWellsNew(LinearSystem &ls, const Bulk &bk, const Well &wl, const OCP_DBL &dt) const
Assemble linear system for production wells.
void GetSolution(Reservoir &rs, const vector< OCP_DBL > &u, const OCPControl &ctrl) const
Update P, Ni, BHP after linear system is solved.
void AllocateReservoir(Reservoir &rs)
Allocate memory for reservoir.
void ResetToLastTimeStep(Reservoir &rs, OCPControl &ctrl)
Reset variables to last time step.
OCP_BOOL UpdateProperty(Reservoir &rs, OCPControl &ctrl)
Update properties of fluids.
void AssembleMatInjWellsNew(LinearSystem &ls, const Bulk &bk, const Well &wl, const OCP_DBL &dt) const
Assemble linear system for injection wells.
void AssembleMatWellsNew(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble linear system for wells.
void InitFlash(Bulk &bk) const
Perform Flash with Sj and calculate values needed for FIMn.
void PassFlashValue(Bulk &bk, const OCP_USI &n) const
Pass value needed for FIMn from flash to bulk.
void AssembleMat(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble Matrix.
void Setup(Reservoir &rs, LinearSystem &ls, const OCPControl &ctrl)
Setup FIM.
void InitReservoir(Reservoir &rs) const
Init.
void CalFlash(Bulk &bk)
Perform Flash with Ni and calculate values needed for FIMn.
void SolveLinearSystem(LinearSystem &ls, Reservoir &rs, OCPControl &ctrl) const
Solve the linear system.
OCP_BOOL FinishNR(Reservoir &rs, OCPControl &ctrl)
Finish a Newton-Raphson iteration.
void UpdateLastTimeStep(Reservoir &rs) const
Update values of last step for FIMn.
void Prepare(Reservoir &rs, OCPControl &ctrl)
Prepare for Assembling matrix.
void SolveLinearSystem(LinearSystem &ls, Reservoir &rs, OCPControl &ctrl)
Solve the linear system.
void AssembleMat(LinearSystem &ls, const Reservoir &rs, const OCP_DBL &dt) const
Assemble Matrix.
void InitFlash(Bulk &bk) const
Perform Flash with Sj and calculate values needed for FIM.
void Setup(Reservoir &rs, LinearSystem &ls, const OCPControl &ctrl)
Setup IMPEC.
OCP_BOOL UpdateProperty(Reservoir &rs, OCPControl &ctrl)
Update properties of fluids.
void PassFlashValue(Bulk &bk, const OCP_USI &n) const
Pass value needed for FIM from flash to bulk.
void CalKrPc(Bulk &bk) const
Calculate relative permeability and capillary pressure needed for FIM.
OCP_BOOL FinishNR(const Reservoir &rs)
Determine if NR iteration finishes.
void InitReservoir(Reservoir &rs) const
Init.
Linear solvers for discrete systems.
USI GetNumIters()
Return the number of iterations.
void AssembleMatLinearSolver()
Assemble Mat for Linear Solver.
void AllocateColMem(const vector< USI > &bulk2bulk, const vector< vector< OCP_USI >> well2bulk)
Allocate memory for linear system with max possible number of columns.
void AddDiag(const OCP_USI &n, const OCP_DBL &v)
Add a value at diagonal value.
void AssembleRhsCopy(const vector< OCP_DBL > &rhs)
Assign Rhs by Copying.
void AssembleRhsAccumulate(const vector< OCP_DBL > &rhs)
Assign Rhs by Accumulating.
void AllocateRowMem(const OCP_USI &dimMax, const USI &nb)
Allocate memory for linear system with max possible number of rows.
void NewDiag(const OCP_USI &n, const OCP_DBL &v)
Push back a diagonal val, which is always at the first location.
void AssignGuess(const OCP_USI &n, const OCP_DBL &v)
Assign an initial value at u[n].
void AddRhs(const OCP_USI &n, const OCP_DBL &v)
Add a value at b[n].
void ClearData()
Clear the internal matrix data for scalar-value problems.
void NewOffDiag(const OCP_USI &bId, const OCP_USI &eId, const OCP_DBL &v)
Push back a off-diagonal value.
OCP_INT Solve()
Solve the Linear System.
OCP_USI AddDim(const OCP_USI &n)
Setup dimensions.
void CheckEquation() const
Check whether NAN or INF occurs in equations, used in debug mode.
vector< OCP_DBL > & GetSolution()
Return the solution.
void SetupLinearSolver(const USI &i, const string &dir, const string &file)
Setup LinearSolver.
void CheckSolution() const
Check whether NAN or INF occurs in solutions, used in debug mode.
All control parameters except for well controllers.
string GetWorkDir() const
Return work dir name.
OCP_DBL GetCurDt() const
Return current time step size.
void UpdateIterNR()
Update the number of Newton iterations.
void ResetIterNRLS()
Reset the number of iterations.
string GetLsFile() const
Return linear solver file name.
void UpdateIterLS(const USI &num)
Update the number of linear iterations.
void RecordTimeLS(const OCP_DBL &t)
Record time used for linear solver.
OCP_DBL maxWellRelRes_mol
maximum relative residual wrt. total moles for each well
OCP_INT maxId_N
index of bulk who has maxRelRes_N
OCP_INT maxId_V
index of bulk who has maxRelRes_V
vector< OCP_DBL > resRelN
vector< OCP_DBL > resRelV
vector< OCP_DBL > resAbs
residual for all equations for each bulk
OCP_DBL maxRelRes_N
maximum relative residual wrt. total moles for each bulk
BulkConn conn
Bulk's connection info.
OCP_DBL GetNRdSmax(OCP_USI &index)
Return NRdSmax.
OptionalFeatures optFeatures
optional features.
OCP_DBL CalCFL(const OCP_DBL &dt) const
Calculate the CFL number, including bulks and wells for IMPEC.
USI GetWellNum() const
Return the num of Well.
OCP_DBL GetNRdPmax()
Return NRdPmax.
void CalMaxChange()
Calculate Maximum Change of some reference variables for IMPEC.
USI GetComNum() const
Return the num of Components.
Bulk bulk
Active grid info.
AllWells allWells
Wells class info.
void CalIPRT(const OCP_DBL &dt)
Calculate num of Injection, Production.
OCP_USI GetBulkNum() const
Return the num of Bulk.
void CalPerfP()
Update pressure in Perforation after well pressure updates.
OCP_BOOL IsOpen() const
Return the state of the well, Open or Close.
USI WellType() const
Return the type of well, Inj or Prod.
void CalProdWeight(const Bulk &myBulk) const
Calculate the production weight.