17     if (Optparam.
type == 
"INJ") {
 
   19     } 
else if (Optparam.
type == 
"PROD") {
 
   27         if (fluidType == 
"WAT" || fluidType == 
"WATER") {
 
   32     if (Optparam.
state == 
"OPEN") {
 
   34     } 
else if (Optparam.
state == 
"CLOSE") {
 
   40     if (Optparam.
optMode == 
"RATE") {
 
   42     } 
else if (Optparam.
optMode == 
"ORAT") {
 
   44     } 
else if (Optparam.
optMode == 
"GRAT") {
 
   46     } 
else if (Optparam.
optMode == 
"WRAT") {
 
   48     } 
else if (Optparam.
optMode == 
"LRAT") {
 
   50     } 
else if (Optparam.
optMode == 
"BHP") {
 
   56     initOptMode = optMode;
 
   65     if (this->type != Opt.type)                 
return true;
 
   66     if (this->state != Opt.state)               
return true;
 
   67     if (this->optMode != Opt.optMode)           
return true;
 
   68     if (this->initOptMode != Opt.initOptMode)   
return true;
 
   69     if (this->maxRate != Opt.maxRate)           
return true;
 
   70     if (this->maxBHP != Opt.maxBHP)             
return true;
 
   71     if (this->minBHP != Opt.minBHP)             
return true;
 
   72     for (
USI i = 0; i < zi.size(); i++) {
 
   73         if (fabs(zi[i] - Opt.zi[i]) > 
TINY)     
return true;
 
   83     numPerf = well.
I_perf.size();
 
   85     for (
USI p = 0; p < numPerf; p++) {
 
   86         perf[p].I          = well.
I_perf[p] - 1;
 
   87         perf[p].J          = well.
J_perf[p] - 1;
 
   88         perf[p].K          = well.
K_perf[p] - 1;
 
   89         perf[p].WI         = well.
WI[p];
 
   90         perf[p].radius     = well.
diameter[p] / 2.0;
 
   91         perf[p].kh         = well.kh[p];
 
  100             OCP_ABORT(
"Wrong direction of perforations!");
 
  108     qi_lbmol.resize(myBulk.numCom);
 
  109     prodWeight.resize(myBulk.numCom);
 
  111     Mtype = myBulk.flashCal[0]->GetType();
 
  113     if (myBulk.blackOil) {
 
  114         for (
auto& opt : optSet) {
 
  116             if (!opt.state) 
continue;
 
  118             opt.zi.resize(myBulk.numCom, 0);
 
  119             if (opt.type == 
INJ) {
 
  121                 switch (myBulk.PVTmode) {
 
  128                         if (opt.fluidType == 
"GAS")
 
  138                 switch (myBulk.PVTmode) {
 
  157                             opt.zi[2] = opt.zi[0] = 1;
 
  164     } 
else if (myBulk.comps) {
 
  166         USI len = sols.size();
 
  168         for (
auto& opt : optSet) {
 
  170             if (!opt.state) 
continue;
 
  172             if (opt.type == 
INJ) {
 
  174                 if (opt.fluidType == 
"WAT") {
 
  175                     opt.zi.resize(myBulk.numCom, 0);
 
  178                     for (
USI i = 0; i < len; i++) {
 
  179                         if (opt.fluidType == sols[i].name) {
 
  180                             opt.zi = sols[i].data;
 
  181                             opt.zi.resize(myBulk.numCom);
 
  184                             opt.xiINJ = myBulk.flashCal[0]->XiPhase(
 
  207     for (
USI p = 0; p < numPerf; p++) {
 
  209             perf[p].K * myGrid.nx * myGrid.ny + perf[p].J * myGrid.nx + perf[p].I;
 
  210         if (myGrid.activeMap_G2B[Idg].IsAct()) {
 
  213             perf[pp].state      = 
OPEN;
 
  214             perf[pp].location   = myGrid.activeMap_G2B[Idg].GetId();
 
  215             perf[pp].depth      = myBulk.depth[perf[pp].location];
 
  216             perf[pp].multiplier = 1;
 
  217             perf[pp].qi_lbmol.resize(myBulk.numCom);
 
  218             perf[pp].transj.resize(myBulk.numPhase);
 
  219             perf[pp].qj_ft3.resize(myBulk.numPhase);
 
  226     perf.resize(numPerf);
 
  228     dG.resize(numPerf, 0);
 
  231     if (depth < 0) depth = perf[0].depth;
 
  247     for (
USI p = 0; p < numPerf; p++) {
 
  248         if (perf[p].WI > 0) {
 
  251             OCP_USI Idb = perf[p].location;
 
  254             OCP_DBL dz  = myBulk.dz[Idb] * myBulk.ntg[Idb];
 
  256             switch (perf[p].direction) {
 
  258                     OCP_DBL kykz  = myBulk.rockKy[Idb] * myBulk.rockKz[Idb];
 
  259                     OCP_DBL ky_kz = myBulk.rockKy[Idb] / myBulk.rockKz[Idb];
 
  263                         pow((dy * dy * pow(1 / ky_kz, 0.5) + dz * dz * pow(ky_kz, 0.5)),
 
  265                     ro /= (pow(ky_kz, 0.25) + pow(1 / ky_kz, 0.25));
 
  267                     if (perf[p].kh < 0) {
 
  268                         perf[p].kh = (dx * pow(kykz, 0.5));
 
  273                     OCP_DBL kzkx  = myBulk.rockKz[Idb] * myBulk.rockKx[Idb];
 
  274                     OCP_DBL kz_kx = myBulk.rockKz[Idb] / myBulk.rockKx[Idb];
 
  278                         pow((dz * dz * pow(1 / kz_kx, 0.5) + dx * dx * pow(kz_kx, 0.5)),
 
  280                     ro /= (pow(kz_kx, 0.25) + pow(1 / kz_kx, 0.25));
 
  282                     if (perf[p].kh < 0) {
 
  283                         perf[p].kh = (dy * pow(kzkx, 0.5));
 
  288                     OCP_DBL kxky  = myBulk.rockKx[Idb] * myBulk.rockKy[Idb];
 
  289                     OCP_DBL kx_ky = myBulk.rockKx[Idb] / myBulk.rockKy[Idb];
 
  293                         pow((dx * dx * pow(1 / kx_ky, 0.5) + dy * dy * pow(kx_ky, 0.5)),
 
  295                     ro /= (pow(kx_ky, 0.25) + pow(1 / kx_ky, 0.25));
 
  297                     if (perf[p].kh < 0) {
 
  298                         perf[p].kh = (dz * pow(kxky, 0.5));
 
  303                     OCP_ABORT(
"Wrong direction of perforations!");
 
  305             perf[p].WI = 
CONV2 * (2 * 
PI) * perf[p].kh /
 
  306                          (log(ro / perf[p].radius) + perf[p].skinFactor);
 
  315     const USI np = myBulk.numPhase;
 
  317     if (opt.type == 
INJ) {
 
  318         for (
USI p = 0; p < numPerf; p++) {
 
  319             perf[p].transINJ = 0;
 
  324             for (
USI j = 0; j < np; j++) {
 
  325                 perf[p].transj[j] = 0;
 
  327                 if (myBulk.phaseExist[
id]) {
 
  328                     perf[p].transj[j] = temp * myBulk.kr[id] / myBulk.mu[id];
 
  329                     perf[p].transINJ += perf[p].transj[j];
 
  334         for (
USI p = 0; p < numPerf; p++) {
 
  339             for (
USI j = 0; j < np; j++) {
 
  340                 perf[p].transj[j] = 0;
 
  342                 if (myBulk.phaseExist[
id]) {
 
  343                     perf[p].transj[j] = temp * myBulk.kr[id] / myBulk.mu[id];
 
  379     const USI np = myBulk.numPhase;
 
  380     const USI nc = myBulk.numCom;
 
  381     fill(qi_lbmol.begin(), qi_lbmol.end(), 0.0);
 
  383     if (opt.type == 
INJ) {
 
  385         for (
USI p = 0; p < numPerf; p++) {
 
  386             perf[p].P  = BHP + dG[p];
 
  388             OCP_DBL dP = perf[p].P - myBulk.P[k];
 
  391             perf[p].qt_ft3 = perf[p].transINJ * dP;
 
  394                 USI pvtnum = myBulk.PVTNUM[k];
 
  396                     myBulk.flashCal[pvtnum]->XiPhase(myBulk.P[k], myBulk.T, &opt.zi[0]);
 
  400             for (
USI i = 0; i < nc; i++) {
 
  401                 perf[p].qi_lbmol[i] = perf[p].qt_ft3 * xi * opt.zi[i];
 
  402                 qi_lbmol[i] += perf[p].qi_lbmol[i];
 
  407         for (
USI p = 0; p < numPerf; p++) {
 
  408             perf[p].P      = BHP + dG[p];
 
  411             fill(perf[p].qi_lbmol.begin(), perf[p].qi_lbmol.end(), 0.0);
 
  412             fill(perf[p].qj_ft3.begin(), perf[p].qj_ft3.end(), 0.0);
 
  414             for (
USI j = 0; j < np; j++) {
 
  416                 if (myBulk.phaseExist[
id]) {
 
  417                     OCP_DBL dP = myBulk.Pj[id] - perf[p].P;
 
  419                     perf[p].qj_ft3[j] = perf[p].transj[j] * dP;
 
  420                     perf[p].qt_ft3 += perf[p].qj_ft3[j];
 
  426                     for (
USI i = 0; i < nc; i++) {
 
  427                         xij = myBulk.xij[
id * nc + i];
 
  428                         perf[p].qi_lbmol[i] += perf[p].qj_ft3[j] * xi * xij;
 
  445             for (
USI i = 0; i < nc; i++) qi_lbmol[i] += perf[p].qi_lbmol[i];
 
  465     OCP_DBL Pwell = maxBHP ? opt.maxBHP : BHP;
 
  467     for (
USI p = 0; p < numPerf; p++) {
 
  472         OCP_DBL dP = Pperf - myBulk.P[k];
 
  473         qj += perf[p].transINJ * perf[p].xi * dP;
 
  485     const USI np = myBulk.numPhase;
 
  486     const USI nc = myBulk.numCom;
 
  488     OCP_DBL Pwell = minBHP ? opt.minBHP : BHP;
 
  490     for (
USI p = 0; p < numPerf; p++) {
 
  495         for (
USI j = 0; j < np; j++) {
 
  497             if (myBulk.phaseExist[
id]) {
 
  499                 for (
USI i = 0; i < nc; i++) {
 
  500                     temp += prodWeight[i] * myBulk.xij[
id * nc + i];
 
  503                 OCP_DBL dP = myBulk.Pj[id] - Pperf;
 
  504                 qj += perf[p].transj[j] * xi * dP * temp;
 
  515     const USI nc = myBulk.numCom;
 
  518     for (
USI i = 0; i < nc; i++) {
 
  521     if (opt.fluidType == 
"WAT") {
 
  529             WGIR = -qj / (opt.xiINJ * 1000); 
 
  550     USI     nc = myBulk.numCom;
 
  552     WOPR       = qt * factor[0];
 
  553     WGPR       = qt * factor[1];
 
  554     WWPR       = qi_lbmol[nc - 1];
 
  561     const USI nc = myBulk.numCom;
 
  563     for (
USI i = 0; i < nc; i++) {
 
  564         if (myBulk.index2Phase[i] == 
OIL) {
 
  566         } 
else if (myBulk.index2Phase[i] == 
GAS) {
 
  568         } 
else if (myBulk.index2Phase[i] == 
WATER) {
 
  615     vector<OCP_DBL> dGperf(numPerf, 0);
 
  617     if (depth <= perf.front().depth) {
 
  619         for (
OCP_INT p = numPerf - 1; p >= 0; p--) {
 
  621                 seg_num = ceil(fabs((perf[0].depth - depth) / maxlen));
 
  622                 if (seg_num == 0) 
continue;
 
  623                 seg_len = (perf[0].depth - depth) / seg_num;
 
  625                 seg_num = ceil(fabs((perf[p].depth - perf[p - 1].depth) / maxlen));
 
  626                 if (seg_num == 0) 
continue;
 
  627                 seg_len = (perf[p].depth - perf[p - 1].depth) / seg_num;
 
  630             perf[p].P     = BHP + dG[p];
 
  634             USI pvtnum = myBulk.PVTNUM[n];
 
  635             for (
USI i = 0; i < seg_num; i++) {
 
  637                     myBulk.flashCal[pvtnum]->RhoPhase(Ptmp, myBulk.T, opt.zi.data()) *
 
  640             dGperf[p] = Pperf - Ptmp;
 
  643         for (
USI p = 1; p < numPerf; p++) {
 
  644             dG[p] = dG[p - 1] + dGperf[p];
 
  646     } 
else if (depth >= perf[numPerf - 1].depth) {
 
  648         for (
USI p = 0; p < numPerf; p++) {
 
  649             if (p == numPerf - 1) {
 
  650                 seg_num = ceil(fabs((depth - perf[numPerf - 1].depth) / maxlen));
 
  651                 if (seg_num == 0) 
continue;
 
  652                 seg_len = (depth - perf[numPerf - 1].depth) / seg_num;
 
  654                 seg_num = ceil(fabs((perf[p + 1].depth - perf[p].depth) / maxlen));
 
  655                 if (seg_num == 0) 
continue;
 
  656                 seg_len = (perf[p + 1].depth - perf[p].depth) / seg_num;
 
  659             perf[p].P     = BHP + dG[p];
 
  663             USI pvtnum = myBulk.PVTNUM[n];
 
  664             for (
USI i = 0; i < seg_num; i++) {
 
  666                     myBulk.flashCal[pvtnum]->RhoPhase(Ptmp, myBulk.T, opt.zi.data()) *
 
  669             dGperf[p] = Ptmp - Pperf;
 
  671         dG[numPerf - 1] = dGperf[numPerf - 1];
 
  672         for (
OCP_INT p = numPerf - 2; p >= 0; p--) {
 
  673             dG[p] = dG[p + 1] + dGperf[p];
 
  682     const USI       np      = myBulk.numPhase;
 
  683     const USI       nc      = myBulk.numCom;
 
  687     vector<OCP_DBL> tmpNi(nc, 0);
 
  688     vector<OCP_DBL> dGperf(numPerf, 0);
 
  693     if (depth <= perf.front().depth) {
 
  697         if (perf[numPerf - 1].state == 
CLOSE) {
 
  698             for (
OCP_INT p = numPerf - 2; p >= 0; p--) {
 
  699                 if (perf[p].state == 
OPEN) {
 
  700                     for (
USI i = 0; i < nc; i++) {
 
  701                         perf[numPerf - 1].qi_lbmol[i] = perf[p].qi_lbmol[i];
 
  708         for (
OCP_INT p = numPerf - 1; p >= 0; p--) {
 
  711                 seg_num = ceil(fabs((perf[0].depth - depth) / maxlen));
 
  712                 if (seg_num == 0) 
continue;
 
  713                 seg_len = (perf[0].depth - depth) / seg_num;
 
  715                 seg_num = ceil(fabs((perf[p].depth - perf[p - 1].depth) / maxlen));
 
  716                 if (seg_num == 0) 
continue;
 
  717                 seg_len = (perf[p].depth - perf[p - 1].depth) / seg_num;
 
  721             perf[p].P     = BHP + dG[p];
 
  725             USI pvtnum = myBulk.PVTNUM[n];
 
  733             for (
USI i = 0; i < nc; i++) {
 
  734                 tmpNi[i] += perf[p].qi_lbmol[i];
 
  738             for (
auto& v : tmpNi) {
 
  742             for (
USI k = 0; k < seg_num; k++) {
 
  743                 myBulk.flashCal[pvtnum]->Flash(Ptmp, myBulk.T, tmpNi.data(), 0, 0, 0);
 
  744                 for (
USI j = 0; j < myBulk.numPhase; j++) {
 
  745                     if (myBulk.flashCal[pvtnum]->phaseExist[j]) {
 
  746                         rhotmp = myBulk.flashCal[pvtnum]->rho[j];
 
  747                         qtacc += myBulk.flashCal[pvtnum]->v[j] / seg_num;
 
  748                         rhoacc += myBulk.flashCal[pvtnum]->v[j] * rhotmp *
 
  751                         if (rhotmp <= 0 || !isfinite(rhotmp)) {
 
  752                             OCP_ABORT(
"Wrong rho " + to_string(rhotmp));
 
  757                 Ptmp -= rhoacc / qtacc * seg_len;
 
  759             dGperf[p] = Pperf - Ptmp;
 
  762         for (
USI p = 1; p < numPerf; p++) {
 
  763             dG[p] = dG[p - 1] + dGperf[p];
 
  765     } 
else if (depth >= perf.back().depth) {
 
  769         if (perf[0].state == 
CLOSE) {
 
  770             for (
USI p = 1; p <= numPerf; p++) {
 
  771                 if (perf[p].state == 
OPEN) {
 
  772                     for (
USI i = 0; i < nc; i++) {
 
  773                         perf[numPerf - 1].qi_lbmol[i] = perf[p].qi_lbmol[i];
 
  780         for (
USI p = 0; p < numPerf; p++) {
 
  781             if (p == numPerf - 1) {
 
  782                 seg_num = ceil(fabs((depth - perf[numPerf - 1].depth) / maxlen));
 
  783                 if (seg_num == 0) 
continue;
 
  784                 seg_len = (depth - perf[numPerf - 1].depth) / seg_num;
 
  786                 seg_num = ceil(fabs((perf[p + 1].depth - perf[p].depth) / maxlen));
 
  787                 if (seg_num == 0) 
continue;
 
  788                 seg_len = (perf[p + 1].depth - perf[p].depth) / seg_num;
 
  792             perf[p].P     = BHP + dG[p];
 
  796             USI pvtnum = myBulk.PVTNUM[n];
 
  797             fill(tmpNi.begin(), tmpNi.end(), 0.0);
 
  798             for (
OCP_INT p1 = numPerf - 1; p1 - p >= 0; p1--) {
 
  799                 for (
USI i = 0; i < nc; i++) {
 
  800                     tmpNi[i] += perf[p1].qi_lbmol[i];
 
  805             for (
auto& v : tmpNi) {
 
  809             for (
USI k = 0; k < seg_num; k++) {
 
  810                 myBulk.flashCal[pvtnum]->Flash(Ptmp, myBulk.T, tmpNi.data(), 0, 0, 0);
 
  811                 for (
USI j = 0; j < np; j++) {
 
  812                     if (myBulk.flashCal[pvtnum]->phaseExist[j]) {
 
  813                         rhotmp = myBulk.flashCal[pvtnum]->rho[j];
 
  814                         qtacc += myBulk.flashCal[pvtnum]->v[j] / seg_num;
 
  815                         rhoacc += myBulk.flashCal[pvtnum]->v[j] * rhotmp *
 
  819                 Ptmp += rhoacc / qtacc * seg_len;
 
  821             dGperf[p] = Ptmp - Pperf;
 
  823         dG[numPerf - 1] = dGperf[numPerf - 1];
 
  824         for (
OCP_INT p = numPerf - 2; p >= 0; p--) {
 
  825             dG[p] = dG[p + 1] + dGperf[p];
 
  835     if (opt.type == 
PROD) {
 
  849             for (
USI i = 0; i < myBulk.numCom; i++) {
 
  852             if (fabs(qt) > 
TINY && qt > 0) {
 
  862                 USI             np = myBulk.numPhase;
 
  863                 USI             nc = myBulk.numCom;
 
  864                 vector<OCP_DBL> tmpNi(nc, 0);
 
  865                 for (
USI p = 0; p < numPerf; p++) {
 
  868                     for (
USI j = 0; j < np; j++) {
 
  870                         if (!myBulk.phaseExist[
id]) 
continue;
 
  871                         for (
USI k = 0; k < nc; k++) {
 
  872                             tmpNi[k] += perf[p].transj[j] * myBulk.xi[id] *
 
  873                                         myBulk.xij[
id * nc + k];
 
  877                 qt = 
Dnorm1(nc, &tmpNi[0]);
 
  900             fill(factor.begin(), factor.end(), 0);
 
  901             if (myBulk.flashCal[0]->phaseExist[0]) { 
 
  902                 OCP_DBL nuo = myBulk.flashCal[0]->xi[0] * myBulk.flashCal[0]->v[0] /
 
  904                 factor[0] = nuo / (myBulk.flashCal[0]->xi[0] *
 
  907             if (myBulk.flashCal[0]->phaseExist[1]) {
 
  908                 OCP_DBL nug = myBulk.flashCal[0]->xi[1] * myBulk.flashCal[0]->v[1] /
 
  910                 factor[1] = nug / (myBulk.flashCal[0]->xi[1] *
 
  913             factor[2] = factor[0];
 
  914             if (myBulk.flashCal[0]->phaseExist[2]) {
 
  915                 OCP_DBL nuw = myBulk.flashCal[0]->xi[2] * myBulk.flashCal[0]->v[2] /
 
  920             if (factor[pid] < 1E-12 || !isfinite(factor[pid])) {
 
  923             fill(prodWeight.begin(), prodWeight.end(), factor[pid]);
 
  934     USI np = myBulk.numPhase;
 
  935     USI nc = myBulk.numCom;
 
  936     for (
USI p = 0; p < numPerf; p++) {
 
  939         for (
USI j = 0; j < np; j++) {
 
  941             if (!myBulk.phaseExist[
id]) 
continue;
 
  942             for (
USI k = 0; k < nc; k++) {
 
  943                 myZi[k] += perf[p].transj[j] * myBulk.xi[id] * myBulk.xij[
id * nc + k];
 
  953     } 
else if (opt.type == 
INJ && opt.optMode == 
BHP_MODE) {
 
  963     for (
USI p = 0; p < numPerf; p++) {
 
  964         dG[p] = (ldG[p] + dG[p]) / 2; 
 
  975         if (opt.type == 
INJ) {
 
  980                 if (opt.injPhase == 
GAS)
 
  982                 else if (opt.injPhase == 
WATER)
 
 1012         if (opt.type == 
INJ) {
 
 1015             OCP_DBL tarRate = opt.maxRate;
 
 1017                 if (opt.injPhase == 
GAS)
 
 1019                 else if (opt.injPhase == 
WATER)
 
 1024                 opt.optMode = opt.initOptMode;
 
 1034             if (q > opt.maxRate) {
 
 1035                 opt.optMode = opt.initOptMode;
 
 1054         cout << 
"### WARNING: Negative BHP " << BHP << endl;
 
 1057     for (
USI p = 0; p < numPerf; p++) {
 
 1058         if (perf[p].state == 
OPEN && perf[p].P < 0) {
 
 1060             cout << 
"### WARNING: Well " << name << 
" Perf[" << p << 
"].P = " << perf[p].P
 
 1063             cout << 
"### WARNING: Negative perforation P " << perf[p].P << endl;
 
 1068     if (opt.type == 
INJ) {
 
 1069         if (opt.optMode != 
BHP_MODE && BHP > opt.maxBHP) {
 
 1071             cout << 
"### WARNING: Well " << name << 
" switch to BHPMode" << endl;
 
 1078         if (opt.optMode != 
BHP_MODE && BHP < opt.minBHP) {
 
 1080             cout << 
"### WARNING: Well " << name << 
" switch to BHPMode" << endl;
 
 1098     if (opt.type == 
PROD) {
 
 1099         for (
USI p = 0; p < numPerf; p++) {
 
 1100             k            = perf[p].location;
 
 1102             if (perf[p].state == 
OPEN && minP < perf[p].P) {
 
 1103                 cout << std::left << std::setw(12) << name << 
"  " 
 1104                      << 
"Well P = " << perf[p].P << 
", " 
 1105                      << 
"Bulk P = " << minP << endl;
 
 1106                 perf[p].state      = 
CLOSE;
 
 1107                 perf[p].multiplier = 0;
 
 1110             } 
else if (perf[p].state == 
CLOSE && minP > perf[p].P) {
 
 1111                 perf[p].state      = 
OPEN;
 
 1112                 perf[p].multiplier = 1;
 
 1116         for (
USI p = 0; p < numPerf; p++) {
 
 1117             k = perf[p].location;
 
 1118             if (perf[p].state == 
OPEN && myBulk.P[k] > perf[p].P) {
 
 1119                 cout << std::left << std::setw(12) << name << 
"  " 
 1120                      << 
"Well P = " << perf[p].P << 
", " 
 1121                      << 
"Bulk P = " << myBulk.P[k] << endl;
 
 1122                 perf[p].state      = 
CLOSE;
 
 1123                 perf[p].multiplier = 0;
 
 1126             } 
else if (perf[p].state == 
CLOSE && myBulk.P[k] < perf[p].P) {
 
 1127                 perf[p].state      = 
OPEN;
 
 1128                 perf[p].multiplier = 1;
 
 1135     for (
USI p = 0; p < numPerf; p++) {
 
 1136         if (perf[p].state == 
OPEN) {
 
 1144         perf.back().state      = 
OPEN;
 
 1145         perf.back().multiplier = 1;
 
 1146         cout << 
"### WARNING: All perfs of " << name
 
 1147              << 
" are closed! Open the last perf!\n";
 
 1171     for (
USI p = 0; p < numPerf; p++) {
 
 1172         myLS.rowCapacity[perf[p].location]++;
 
 1179     for (
USI p = 0; p < numPerf; p++) {
 
 1180         myBulk.wellBulkId.push_back(perf[p].location);
 
 1189     cout << 
"----------------------------" << endl;
 
 1190     cout << name << 
":    " << opt.optMode << 
"   " << setprecision(3) << BHP << endl;
 
 1191     for (
USI p = 0; p < numPerf; p++) {
 
 1192         vector<OCP_DBL> Qitmp(perf[p].qi_lbmol);
 
 1195         cout << setw(3) << p << 
"   " << perf[p].state << 
"   " << setw(6)
 
 1196             << perf[p].location << 
"  " << setw(2) << perf[p].I + 1 << 
"  " << setw(2)
 
 1197             << perf[p].J + 1 << 
"  " << setw(2) << perf[p].K + 1 << 
"  " << setw(10)
 
 1198             << setprecision(6) << perf[p].WI << 
"  "                
 1199             << setprecision(3) << perf[p].radius << 
"  "                
 1200             << setw(8) << setprecision(4) << perf[p].kh << 
"  "     
 1201             << setw(8) << setprecision(2) << perf[p].depth << 
"  "  
 1202             << setprecision(3) << perf[p].P << 
"  "                 
 1203             << setw(10) << setprecision(3) << myBulk.P[n] << 
"   "  
 1204             << setw(6) << setprecision(3) << dG[p] << 
"   "         
 1205             << setw(8) << perf[p].qi_lbmol[myBulk.numCom - 1] << 
"   " << setw(6) << setprecision(6)
 
 1206             << myBulk.S[n * myBulk.numPhase + 0] << 
"   " << setw(6) << setprecision(6)
 
 1207             << myBulk.S[n * myBulk.numPhase + 1] << 
"   " << setw(6) << setprecision(6)
 
 1208             << myBulk.S[n * myBulk.numPhase + 2] << endl;
 
 1221     if (opt.type == 
PROD) {
 
 1222         const USI np = myBulk.numPhase;
 
 1223         for (
USI p = 0; p < numPerf; p++) {
 
 1224             if (perf[p].state == 
OPEN) {
 
 1227                 for (
USI j = 0; j < np; j++) {
 
 1228                     myBulk.cfl[k * np + j] += fabs(perf[p].qj_ft3[j]) * dt;
 
 1239     const USI nc = myBulk.numCom;
 
 1241     for (
USI p = 0; p < numPerf; p++) {
 
 1243         for (
USI i = 0; i < nc; i++) {
 
 1244             myBulk.Ni[k * nc + i] -= perf[p].qi_lbmol[i] * dt;
 
 1254     const USI     nc  = myBulk.numCom;
 
 1259     for (
USI p = 0; p < numPerf; p++) {
 
 1263         for (
USI i = 0; i < nc; i++) {
 
 1264             Vfi_zi += myBulk.vfi[k * nc + i] * opt.zi[i];
 
 1267         OCP_DBL valw = dt * perf[p].xi * perf[p].transINJ;
 
 1275         USI ptr = myLS.diagPtr[k];
 
 1276         myLS.val[k][ptr] += valb;
 
 1278         myLS.colId[k].push_back(wId);
 
 1279         myLS.val[k].push_back(-valb);
 
 1284         switch (opt.optMode) {
 
 1291                 myLS.diagVal[wId] += valw;
 
 1293                 myLS.colId[wId].push_back(k);
 
 1294                 myLS.val[wId].push_back(-valw);
 
 1299                 myLS.colId[wId].push_back(k);
 
 1300                 myLS.val[wId].push_back(0);
 
 1308     assert(myLS.val[wId].size() == numPerf);
 
 1310     switch (opt.optMode) {
 
 1317             myLS.colId[wId].push_back(wId);
 
 1318             myLS.diagPtr[wId] = numPerf;
 
 1319             myLS.val[wId].push_back(myLS.diagVal[wId]);
 
 1321             myLS.b[wId] += dt * opt.maxRate;
 
 1325             myLS.colId[wId].push_back(wId);
 
 1326             myLS.diagPtr[wId] = numPerf;
 
 1327             myLS.val[wId].push_back(dt);
 
 1329             myLS.b[wId] += dt * opt.maxBHP;
 
 1331             myLS.u[wId] = opt.maxBHP;
 
 1343     const USI     np  = myBulk.numPhase;
 
 1344     const USI     nc  = myBulk.numCom;
 
 1352     for (
USI p = 0; p < numPerf; p++) {
 
 1360         for (
USI j = 0; j < np; j++) {
 
 1361             if (!myBulk.phaseExist[n * np + j]) 
continue;
 
 1366             for (
USI i = 0; i < nc; i++) {
 
 1367                 tempb += myBulk.vfi[n * nc + i] * myBulk.xij[n * np * nc + j * nc + i];
 
 1368                 tempw += prodWeight[i] * myBulk.xij[n * np * nc + j * nc + i];
 
 1370             OCP_DBL trans = dt * perf[p].transj[j] * myBulk.xi[n * np + j];
 
 1371             valb += tempb * trans;
 
 1372             valw += tempw * trans;
 
 1374             OCP_DBL dP = dG[p] - myBulk.Pc[n * np + j];
 
 1375             bb += tempb * trans * dP;
 
 1376             bw += tempw * trans * dP;
 
 1381         USI ptr = myLS.diagPtr[n];
 
 1382         myLS.val[n][ptr] += valb;
 
 1384         myLS.colId[n].push_back(wId);
 
 1385         myLS.val[n].push_back(-valb);
 
 1390         switch (opt.optMode) {
 
 1397                 myLS.diagVal[wId] -= valw;
 
 1399                 myLS.colId[wId].push_back(n);
 
 1400                 myLS.val[wId].push_back(valw);
 
 1406                 myLS.colId[wId].push_back(n);
 
 1407                 myLS.val[wId].push_back(0);
 
 1415     assert(myLS.val[wId].size() == numPerf);
 
 1417     switch (opt.optMode) {
 
 1424             myLS.colId[wId].push_back(wId);
 
 1425             myLS.diagPtr[wId] = numPerf;
 
 1426             myLS.val[wId].push_back(myLS.diagVal[wId]);
 
 1428             myLS.b[wId] += dt * opt.maxRate;
 
 1432             myLS.colId[wId].push_back(wId);
 
 1433             myLS.diagPtr[wId] = numPerf;
 
 1434             myLS.val[wId].push_back(dt);
 
 1436             myLS.b[wId] += dt * opt.minBHP;
 
 1438             myLS.u[wId] = opt.minBHP;
 
 1446                                         const OCP_DBL& dt, 
const vector<Well>& allWell,
 
 1447                                         const vector<USI>& injId)
 const 
 1450     vector<OCP_USI> tarId;
 
 1451     for (
USI w = 0; w < injId.size(); w++) {
 
 1453             tarId.push_back(allWell[w].wEId + myBulk.numBulk);
 
 1456     USI tlen = tarId.size();
 
 1458         const OCP_DBL factor = allWell[injId[0]].opt.factor * dt;
 
 1460         const OCP_USI prodId = wEId + myBulk.numBulk;
 
 1461         USI           np     = myBulk.numPhase;
 
 1468         for (
USI p = 0; p < numPerf; p++) {
 
 1469             n    = perf[p].location;
 
 1472             for (
USI j = 0; j < np; j++) {
 
 1474                 if (myBulk.phaseExist[bId]) {
 
 1475                     tmp = perf[p].transj[j] * myBulk.xi[bId];
 
 1477                     rhsw += tmp * (myBulk.Pc[bId] - dG[p]);
 
 1482             for (
USI t = 0; t < tlen; t++) {
 
 1484                 tarsize = myLS.colId[tar].size();
 
 1486                 for (i = 0; i < tarsize; i++) {
 
 1487                     if (n < myLS.colId[tar][i]) {
 
 1490                         myLS.colId[tar].insert(myLS.colId[tar].begin() + i, n);
 
 1491                         myLS.val[tar].insert(myLS.val[tar].begin() + i, -valb);
 
 1492                         myLS.diagPtr[tar]++;
 
 1501         for (
USI t = 0; t < tlen; t++) {
 
 1503             tarsize = myLS.colId[tar].size();
 
 1504             myLS.b[tar] += rhsw; 
 
 1506             for (i = 0; i < tarsize; i++) {
 
 1507                 if (prodId < myLS.colId[tar][i]) {
 
 1509                     myLS.colId[tar].insert(myLS.colId[tar].begin() + i, prodId);
 
 1510                     myLS.val[tar].insert(myLS.val[tar].begin() + i, valw);
 
 1511                     if (i <= myLS.diagPtr[tar]) myLS.diagPtr[tar]++;
 
 1517                 myLS.colId[tar].push_back(prodId);
 
 1518                 myLS.val[tar].push_back(valw);
 
 1537     const USI np     = myBulk.numPhase;
 
 1538     const USI nc     = myBulk.numCom;
 
 1539     const USI ncol   = nc + 1;
 
 1540     const USI ncol2  = np * nc + np;
 
 1541     const USI bsize  = ncol * ncol;
 
 1542     const USI bsize2 = ncol * ncol2;
 
 1550     vector<OCP_DBL> bmat(bsize, 0);
 
 1551     vector<OCP_DBL> bmat2(bsize, 0);
 
 1552     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 1553     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 1554     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 1556     for (
USI p = 0; p < numPerf; p++) {
 
 1557         const OCP_USI n = perf[p].location;
 
 1558         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 1559         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 1560         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 1562         dP = myBulk.P[n] - BHP - dG[p];
 
 1564         for (
USI j = 0; j < np; j++) {
 
 1565             n_np_j = n * np + j;
 
 1566             if (!myBulk.phaseExist[n_np_j]) 
continue;
 
 1568             mu  = myBulk.mu[n_np_j];
 
 1569             muP = myBulk.muP[n_np_j];
 
 1571             for (
USI i = 0; i < nc; i++) {
 
 1573                 transIJ = perf[p].transj[j] * perf[p].xi * opt.zi[i];
 
 1574                 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
 
 1575                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 1578                 for (
USI k = 0; k < np; k++) {
 
 1579                     dQdXsB[(i + 1) * ncol2 + k] +=
 
 1580                         CONV1 * perf[p].WI * perf[p].multiplier * perf[p].xi *
 
 1581                         opt.zi[i] * myBulk.dKr_dS[n_np_j * np + k] * dP / mu;
 
 1584                 for (
USI k = 0; k < nc; k++) {
 
 1585                     dQdXsB[(i + 1) * ncol2 + np + j * nc + k] +=
 
 1586                         -transIJ * dP / mu * myBulk.mux[n_np_j * nc + k];
 
 1595         DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(), &myBulk.dSec_dPri[n * bsize2], 1,
 
 1597         Dscalar(bsize, dt, bmat.data());
 
 1599         USI ptr = myLS.diagPtr[n];
 
 1600         for (
USI i = 0; i < bsize; i++) {
 
 1601             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 1605         Dscalar(bsize, dt, bmat.data());
 
 1606         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 1607         myLS.colId[n].push_back(wId);
 
 1610         switch (opt.optMode) {
 
 1617                 fill(bmat.begin(), bmat.end(), 0.0);
 
 1618                 for (
USI i = 0; i < nc; i++) {
 
 1619                     bmat[0] += dQdXpW[(i + 1) * ncol];
 
 1620                     bmat[(i + 1) * ncol + i + 1] = 1;
 
 1622                 for (
USI i = 0; i < bsize; i++) {
 
 1623                     myLS.diagVal[wId * bsize + i] += bmat[i];
 
 1631                 DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(),
 
 1632                         &myBulk.dSec_dPri[n * bsize2], 1, bmat.data());
 
 1633                 fill(bmat2.begin(), bmat2.end(), 0.0);
 
 1634                 for (
USI i = 0; i < nc; i++) {
 
 1635                     Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
 
 1637                 myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 1638                 myLS.colId[wId].push_back(n);
 
 1643                 fill(bmat.begin(), bmat.end(), 0.0);
 
 1644                 for (
USI i = 0; i < nc + 1; i++) {
 
 1645                     bmat[i * ncol + i] = 1;
 
 1648                 for (
USI i = 0; i < bsize; i++) {
 
 1649                     myLS.diagVal[wId * bsize + i] += bmat[i];
 
 1652                 fill(bmat.begin(), bmat.end(), 0.0);
 
 1654                 myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 1655                 myLS.colId[wId].push_back(n);
 
 1665     assert(myLS.val[wId].size() == numPerf * bsize);
 
 1667     myLS.colId[wId].push_back(wId);
 
 1668     myLS.diagPtr[wId] = numPerf;
 
 1669     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 1670                          myLS.diagVal.data() + wId * bsize + bsize);
 
 1682     const USI np     = myBulk.numPhase;
 
 1683     const USI nc     = myBulk.numCom;
 
 1684     const USI ncol   = nc + 1;
 
 1685     const USI ncol2  = np * nc + np;
 
 1686     const USI bsize  = ncol * ncol;
 
 1687     const USI bsize2 = ncol * ncol2;
 
 1689     OCP_DBL xij, xi, mu, muP, xiP;
 
 1696     vector<OCP_DBL> bmat(bsize, 0);
 
 1697     vector<OCP_DBL> bmat2(bsize, 0);
 
 1698     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 1699     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 1700     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 1706     for (
USI p = 0; p < numPerf; p++) {
 
 1707         const OCP_USI n = perf[p].location;
 
 1708         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 1709         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 1710         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 1712         for (
USI j = 0; j < np; j++) {
 
 1713             n_np_j = n * np + j;
 
 1714             if (!myBulk.phaseExist[n_np_j]) 
continue;
 
 1716             dP  = myBulk.Pj[n_np_j] - BHP - dG[p];
 
 1717             xi  = myBulk.xi[n_np_j];
 
 1718             mu  = myBulk.mu[n_np_j];
 
 1719             muP = myBulk.muP[n_np_j];
 
 1720             xiP = myBulk.xiP[n_np_j];
 
 1722             for (
USI i = 0; i < nc; i++) {
 
 1723                 xij = myBulk.xij[n_np_j * nc + i];
 
 1725                 transIJ = perf[p].transj[j] * xi * xij;
 
 1726                 dQdXpB[(i + 1) * ncol] +=
 
 1727                     transIJ * (1 - dP * muP / mu) + dP * perf[p].transj[j] * xij * xiP;
 
 1728                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 1735                 for (
USI k = 0; k < np; k++) {
 
 1736                     tmp = 
CONV1 * perf[p].WI * perf[p].multiplier * dP / mu * xi * xij *
 
 1737                           myBulk.dKr_dS[n_np_j * np + k];
 
 1739                     tmp += transIJ * myBulk.dPcj_dS[n_np_j * np + k];
 
 1740                     dQdXsB[(i + 1) * ncol2 + k] += tmp;
 
 1743                 for (
USI k = 0; k < nc; k++) {
 
 1744                     tmp = dP * perf[p].transj[j] * xij *
 
 1745                           (myBulk.xix[n_np_j * nc + k] -
 
 1746                            xi / mu * myBulk.mux[n_np_j * nc + k]);
 
 1747                     dQdXsB[(i + 1) * ncol2 + np + j * nc + k] += tmp;
 
 1749                 dQdXsB[(i + 1) * ncol2 + np + j * nc + i] += perf[p].transj[j] * xi * dP;
 
 1757         DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(), &myBulk.dSec_dPri[n * bsize2], 1,
 
 1760         Dscalar(bsize, dt, bmat.data());
 
 1762         USI ptr = myLS.diagPtr[n];
 
 1763         for (
USI i = 0; i < bsize; i++) {
 
 1764             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 1768         Dscalar(bsize, dt, bmat.data());
 
 1769         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 1770         myLS.colId[n].push_back(wId);
 
 1773         switch (opt.optMode) {
 
 1780                 fill(bmat.begin(), bmat.end(), 0.0);
 
 1781                 for (
USI i = 0; i < nc; i++) {
 
 1782                     bmat[0] += dQdXpW[(i + 1) * ncol] * prodWeight[i];
 
 1783                     bmat[(i + 1) * ncol + i + 1] = 1;
 
 1785                 for (
USI i = 0; i < bsize; i++) {
 
 1786                     myLS.diagVal[wId * bsize + i] += bmat[i];
 
 1794                 DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(),
 
 1795                         &myBulk.dSec_dPri[n * bsize2], 1, bmat.data());
 
 1796                 fill(bmat2.begin(), bmat2.end(), 0.0);
 
 1797                 for (
USI i = 0; i < nc; i++) {
 
 1798                     Daxpy(ncol, prodWeight[i], bmat.data() + (i + 1) * ncol,
 
 1801                 myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 1802                 myLS.colId[wId].push_back(n);
 
 1807                 fill(bmat.begin(), bmat.end(), 0.0);
 
 1808                 for (
USI i = 0; i < nc + 1; i++) {
 
 1809                     bmat[i * ncol + i] = 1;
 
 1812                 for (
USI i = 0; i < bsize; i++) {
 
 1813                     myLS.diagVal[wId * bsize + i] += bmat[i];
 
 1816                 fill(bmat.begin(), bmat.end(), 0.0);
 
 1818                 myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 1819                 myLS.colId[wId].push_back(n);
 
 1829     assert(myLS.val[wId].size() == numPerf * bsize);
 
 1831     myLS.colId[wId].push_back(wId);
 
 1832     myLS.diagPtr[wId] = numPerf;
 
 1833     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 1834                          myLS.diagVal.data() + wId * bsize + bsize);
 
 1843                                       const OCP_DBL& dt, 
const vector<Well>& allWell,
 
 1844                                       const vector<USI>& injId)
 const 
 1847     vector<OCP_USI> tarId;
 
 1848     for (
USI w = 0; w < injId.size(); w++) {
 
 1850             tarId.push_back(allWell[w].wEId + myBulk.numBulk);
 
 1853     USI tlen = tarId.size();
 
 1857         const OCP_DBL factor = allWell[injId[0]].opt.factor;
 
 1858         const OCP_USI prodId = wEId + myBulk.numBulk;
 
 1862         const USI np     = myBulk.numPhase;
 
 1863         const USI nc     = myBulk.numCom;
 
 1864         const USI ncol   = nc + 1;
 
 1865         const USI ncol2  = np * nc + np;
 
 1866         const USI bsize  = ncol * ncol;
 
 1867         const USI bsize2 = ncol * ncol2;
 
 1869         OCP_DBL xij, xi, mu, muP, xiP, dP, transIJ, tmp;
 
 1872         vector<OCP_DBL> bmat(bsize, 0);
 
 1873         vector<OCP_DBL> bmat2(bsize, 0);
 
 1874         vector<OCP_DBL> tmpMat(bsize, 0);
 
 1875         vector<OCP_DBL> dQdXpB(bsize, 0);
 
 1876         vector<OCP_DBL> dQdXpW(bsize, 0);
 
 1877         vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 1879         for (
USI p = 0; p < numPerf; p++) {
 
 1881             fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 1882             fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 1883             fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 1885             for (
USI j = 0; j < np; j++) {
 
 1886                 n_np_j = n * np + j;
 
 1887                 if (!myBulk.phaseExist[n_np_j]) 
continue;
 
 1889                 dP  = myBulk.Pj[n_np_j] - BHP - dG[p];
 
 1890                 xi  = myBulk.xi[n_np_j];
 
 1891                 mu  = myBulk.mu[n_np_j];
 
 1892                 muP = myBulk.muP[n_np_j];
 
 1893                 xiP = myBulk.xiP[n_np_j];
 
 1895                 for (
USI i = 0; i < nc; i++) {
 
 1896                     xij = myBulk.xij[n_np_j * nc + i];
 
 1898                     transIJ = perf[p].transj[j] * xi * xij;
 
 1899                     dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu) +
 
 1900                                               dP * perf[p].transj[j] * xij * xiP;
 
 1901                     dQdXpW[(i + 1) * ncol] += -transIJ;
 
 1904                     for (
USI k = 0; k < np; k++) {
 
 1905                         tmp = 
CONV1 * perf[p].WI * perf[p].multiplier * dP / mu * xi *
 
 1906                               xij * myBulk.dKr_dS[n * np * np + j * np + k];
 
 1908                         tmp += transIJ * myBulk.dPcj_dS[n * np * np + j * np + k];
 
 1909                         dQdXsB[(i + 1) * ncol2 + k] += tmp;
 
 1912                     for (
USI k = 0; k < nc; k++) {
 
 1913                         tmp = dP * perf[p].transj[j] * xij *
 
 1914                               (myBulk.xix[n_np_j * nc + k] -
 
 1915                                xi / mu * myBulk.mux[n_np_j * nc + k]);
 
 1917                             tmp += perf[p].transj[j] * xi * dP;
 
 1919                         dQdXsB[(i + 1) * ncol2 + np + j * nc + k] += tmp;
 
 1925             for (
USI i = 0; i < nc; i++) {
 
 1927                 tmpMat[0] += dQdXpW[(i + 1) * ncol] * factor;
 
 1932             DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(), &myBulk.dSec_dPri[n * bsize2],
 
 1934             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 1935             for (
USI i = 0; i < nc; i++) {
 
 1938                 Daxpy(ncol, factor, bmat.data() + (i + 1) * ncol, bmat2.data());
 
 1942             for (
USI t = 0; t < tlen; t++) {
 
 1944                 tarsize = myLS.colId[tar].size();
 
 1946                 for (i = 0; i < tarsize; i++) {
 
 1947                     if (n < myLS.colId[tar][i]) {
 
 1950                         myLS.colId[tar].insert(myLS.colId[tar].begin() + i, n);
 
 1951                         myLS.val[tar].insert(myLS.val[tar].begin() + i * bsize,
 
 1952                                              bmat.begin(), bmat.end());
 
 1953                         myLS.diagPtr[tar]++;
 
 1960         for (
USI t = 0; t < tlen; t++) {
 
 1962             tarsize = myLS.colId[tar].size();
 
 1964             for (i = 0; i < tarsize; i++) {
 
 1965                 if (prodId < myLS.colId[tar][i]) {
 
 1967                     myLS.colId[tar].insert(myLS.colId[tar].begin() + i, prodId);
 
 1968                     myLS.val[tar].insert(myLS.val[tar].begin() + i * bsize,
 
 1969                                          tmpMat.begin(), tmpMat.end());
 
 1970                     if (i <= myLS.diagPtr[tar]) myLS.diagPtr[tar]++;
 
 1976                 myLS.colId[tar].push_back(prodId);
 
 1977                 myLS.val[tar].insert(myLS.val[tar].end(), tmpMat.begin(), tmpMat.end());
 
 1984                      const OCP_USI& wId, 
const vector<Well>& allWell)
 const 
 1989     const USI nc  = myBulk.numCom;
 
 1990     const USI len = nc + 1;
 
 1993     for (
USI p = 0; p < numPerf; p++) {
 
 1994         k = perf[p].location;
 
 1995         for (
USI i = 0; i < nc; i++) {
 
 1996             resFIM.res[k * len + 1 + i] += perf[p].qi_lbmol[i] * dt;
 
 2001     OCP_USI bId = (myBulk.numBulk + wId) * len;   
 
 2002     if (opt.type == 
INJ) {
 
 2004         switch (opt.optMode) {
 
 2007                 resFIM.res[bId] = BHP - opt.maxBHP;
 
 2014                 resFIM.res[bId] = opt.maxRate;
 
 2015                 for (
USI i = 0; i < nc; i++) {
 
 2016                     resFIM.res[bId] += qi_lbmol[i];
 
 2019                     for (
auto& w : opt.connWell) {
 
 2021                         for (
USI i = 0; i < nc; i++) {
 
 2022                             tmp += allWell[w].qi_lbmol[i];
 
 2027                         resFIM.res[bId] += tmp;
 
 2034                 resFIM.maxWellRelRes_mol =
 
 2035                     max(resFIM.maxWellRelRes_mol, fabs(resFIM.res[bId] / opt.maxRate));
 
 2043         switch (opt.optMode) {
 
 2046                 resFIM.res[bId] = BHP - opt.minBHP;
 
 2053                 resFIM.res[bId] = -opt.maxRate;
 
 2054                 for (
USI i = 0; i < nc; i++) {
 
 2055                     resFIM.res[bId] += qi_lbmol[i] * prodWeight[i];
 
 2060                 resFIM.maxWellRelRes_mol =
 
 2061                     max(resFIM.maxWellRelRes_mol, fabs(resFIM.res[bId] / opt.maxRate));
 
 2070 void Well::ShowRes(
const OCP_USI& wId, 
const vector<OCP_DBL>& res, 
const Bulk& myBulk)
 const 
 2073     const USI nc = myBulk.numCom;
 
 2074     const USI len = nc + 1;
 
 2076     OCP_USI bId = (myBulk.numBulk + wId) * len;
 
 2077     cout << name << 
"   " << res[bId] << 
"   ";
 
 2079     if (opt.type == 
INJ) {
 
 2081         switch (opt.optMode) {
 
 2083             cout << 
"BHPMode" << endl;
 
 2090             cout << opt.maxRate << 
"   " << fabs(res[bId] / opt.maxRate) << endl;
 
 2099         switch (opt.optMode) {
 
 2101             cout << 
"BHPMode" << endl;
 
 2108             cout << opt.maxRate << 
"   " << fabs(res[bId] / opt.maxRate) << endl;
 
 2132     const USI np = myBulk.numPhase;
 
 2133     const USI nc = myBulk.numCom;
 
 2134     const USI nch = nc - 1;
 
 2135     const USI ncol = nc + 1;
 
 2136     const USI ncol2 = np * nc + np;
 
 2137     const USI bsize = ncol * ncol;
 
 2138     const USI bsize2 = ncol * ncol2;
 
 2146     vector<OCP_DBL> bmat(bsize, 0);
 
 2147     vector<OCP_DBL> bmat2(bsize, 0);
 
 2148     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 2149     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 2150     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 2151     vector<bool>    phaseExistB(np, 
false);
 
 2152     vector<USI>     pEnumComB(np, 0);
 
 2156     for (
USI p = 0; p < numPerf; p++) {
 
 2157         const OCP_USI n = perf[p].location;
 
 2158         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 2159         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 2160         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 2162         dP = myBulk.P[n] - BHP - dG[p];
 
 2164         const USI npB = myBulk.phaseNum[n] + 1;  ncolB = npB;
 
 2165         for (
USI j = 0; j < np; j++) {
 
 2166             phaseExistB[j] = myBulk.phaseExist[n * np + j];
 
 2167             pEnumComB[j] = myBulk.pEnumCom[n * np + j];
 
 2168             ncolB += pEnumComB[j];
 
 2173         for (
USI j = 0; j < np; j++) {
 
 2175             if (!phaseExistB[j]) {
 
 2176                 jxB += pEnumComB[j];
 
 2180             n_np_j = n * np + j;
 
 2181             mu = myBulk.mu[n_np_j];
 
 2182             muP = myBulk.muP[n_np_j];
 
 2184             for (
USI i = 0; i < nc; i++) {
 
 2186                 transIJ = perf[p].transj[j] * perf[p].xi * opt.zi[i];
 
 2187                 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
 
 2188                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 2192                 for (
USI j1 = 0; j1 < np; j1++) {
 
 2193                     if (phaseExistB[j1]) {
 
 2194                         dQdXsB[(i + 1) * ncolB + j1B] +=
 
 2195                             CONV1 * perf[p].WI * perf[p].multiplier * perf[p].xi *
 
 2196                             opt.zi[i] * myBulk.dKr_dS[n_np_j * np + j1] * dP / mu;
 
 2202                 for (
USI k = 0; k < pEnumComB[j]; k++) {
 
 2203                     dQdXsB[(i + 1) * ncolB + jxB + k] +=
 
 2204                         -transIJ * dP / mu * myBulk.mux[n_np_j * nc + k];
 
 2207             jxB += pEnumComB[j];
 
 2213         DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1,
 
 2215         Dscalar(bsize, dt, bmat.data());
 
 2217         USI ptr = myLS.diagPtr[n];
 
 2218         for (
USI i = 0; i < bsize; i++) {
 
 2219             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 2223         Dscalar(bsize, dt, bmat.data());
 
 2224         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 2225         myLS.colId[n].push_back(wId);
 
 2228         switch (opt.optMode) {
 
 2235             fill(bmat.begin(), bmat.end(), 0.0);
 
 2236             for (
USI i = 0; i < nc; i++) {
 
 2237                 bmat[0] += dQdXpW[(i + 1) * ncol];
 
 2238                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 2240             for (
USI i = 0; i < bsize; i++) {
 
 2241                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2248             DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(),
 
 2249                 &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1, bmat.data());
 
 2250             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 2251             for (
USI i = 0; i < nc; i++) {
 
 2252                 Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
 
 2254             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 2255             myLS.colId[wId].push_back(n);
 
 2260             fill(bmat.begin(), bmat.end(), 0.0);
 
 2261             for (
USI i = 0; i < nc + 1; i++) {
 
 2262                 bmat[i * ncol + i] = 1;
 
 2265             for (
USI i = 0; i < bsize; i++) {
 
 2266                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2269             fill(bmat.begin(), bmat.end(), 0.0);
 
 2271             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 2272             myLS.colId[wId].push_back(n);
 
 2282     assert(myLS.val[wId].size() == numPerf * bsize);
 
 2284     myLS.colId[wId].push_back(wId);
 
 2285     myLS.diagPtr[wId] = numPerf;
 
 2286     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 2287         myLS.diagVal.data() + wId * bsize + bsize);
 
 2300     const USI np = myBulk.numPhase;
 
 2301     const USI nc = myBulk.numCom;
 
 2302     const USI nch = nc - 1;
 
 2303     const USI ncol = nc + 1;
 
 2304     const USI ncol2 = np * nc + np;
 
 2305     const USI bsize = ncol * ncol;
 
 2306     const USI bsize2 = ncol * ncol2;
 
 2308     OCP_DBL xij, xi, mu, muP, xiP;
 
 2315     vector<OCP_DBL> bmat(bsize, 0);
 
 2316     vector<OCP_DBL> bmat2(bsize, 0);
 
 2317     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 2318     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 2319     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 2320     vector<bool>    phaseExistB(np, 
false);
 
 2321     vector<USI>     pEnumComB(np, 0);
 
 2328     for (
USI p = 0; p < numPerf; p++) {
 
 2330         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 2331         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 2332         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 2334         const USI npB = myBulk.phaseNum[n] + 1;    ncolB = npB;
 
 2335         for (
USI j = 0; j < np; j++) {
 
 2336             phaseExistB[j] = myBulk.phaseExist[n * np + j];
 
 2337             pEnumComB[j] = myBulk.pEnumCom[n * np + j];
 
 2338             ncolB += pEnumComB[j];
 
 2343         for (
USI j = 0; j < np; j++) {
 
 2345             if (!phaseExistB[j]) {
 
 2346                 jxB += pEnumComB[j];
 
 2350             n_np_j = n * np + j;
 
 2351             dP = myBulk.Pj[n_np_j] - BHP - dG[p];
 
 2352             xi = myBulk.xi[n_np_j];
 
 2353             mu = myBulk.mu[n_np_j];
 
 2354             muP = myBulk.muP[n_np_j];
 
 2355             xiP = myBulk.xiP[n_np_j];
 
 2358             for (
USI i = 0; i < nc; i++) {
 
 2359                 xij = myBulk.xij[n_np_j * nc + i];
 
 2361                 transIJ = perf[p].transj[j] * xi * xij;
 
 2362                 dQdXpB[(i + 1) * ncol] +=
 
 2363                     transIJ * (1 - dP * muP / mu) + dP * perf[p].transj[j] * xij * xiP;
 
 2364                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 2368                 for (
USI j1 = 0; j1 < np; j1++) {
 
 2369                     if (phaseExistB[j1]) {
 
 2370                         tmp = 
CONV1 * perf[p].WI * perf[p].multiplier * dP / mu * xi * xij *
 
 2371                             myBulk.dKr_dS[n_np_j * np + j1];
 
 2373                         tmp += transIJ * myBulk.dPcj_dS[n_np_j * np + j1];
 
 2374                         dQdXsB[(i + 1) * ncolB + j1B] += tmp;
 
 2379                 for (
USI k = 0; k < pEnumComB[j]; k++) {
 
 2380                     tmp = dP * perf[p].transj[j] * xij *
 
 2381                         (myBulk.xix[n_np_j * nc + k] -
 
 2382                             xi / mu * myBulk.mux[n_np_j * nc + k]);
 
 2383                     dQdXsB[(i + 1) * ncolB + jxB + k] += tmp;
 
 2386                 if (i < pEnumComB[j])
 
 2387                     dQdXsB[(i + 1) * ncolB + jxB + i] += perf[p].transj[j] * xi * dP;;
 
 2389             jxB += pEnumComB[j];
 
 2395         DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1,
 
 2398         Dscalar(bsize, dt, bmat.data());
 
 2400         USI ptr = myLS.diagPtr[n];
 
 2401         for (
USI i = 0; i < bsize; i++) {
 
 2402             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 2406         Dscalar(bsize, dt, bmat.data());
 
 2407         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 2408         myLS.colId[n].push_back(wId);
 
 2411         switch (opt.optMode) {
 
 2418             fill(bmat.begin(), bmat.end(), 0.0);
 
 2419             for (
USI i = 0; i < nc; i++) {
 
 2420                 bmat[0] += dQdXpW[(i + 1) * ncol] * prodWeight[i];
 
 2421                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 2423             for (
USI i = 0; i < bsize; i++) {
 
 2424                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2431             DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(),
 
 2432                 &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1, bmat.data());
 
 2433             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 2434             for (
USI i = 0; i < nc; i++) {
 
 2435                 Daxpy(ncol, prodWeight[i], bmat.data() + (i + 1) * ncol,
 
 2438             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 2439             myLS.colId[wId].push_back(n);
 
 2444             fill(bmat.begin(), bmat.end(), 0.0);
 
 2445             for (
USI i = 0; i < nc + 1; i++) {
 
 2446                 bmat[i * ncol + i] = 1;
 
 2449             for (
USI i = 0; i < bsize; i++) {
 
 2450                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2453             fill(bmat.begin(), bmat.end(), 0.0);
 
 2455             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 2456             myLS.colId[wId].push_back(n);
 
 2466     assert(myLS.val[wId].size() == numPerf * bsize);
 
 2468     myLS.colId[wId].push_back(wId);
 
 2469     myLS.diagPtr[wId] = numPerf;
 
 2470     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 2471         myLS.diagVal.data() + wId * bsize + bsize);
 
 2475 void Well::AssembleMatINJ_FIM_new_n(
const Bulk& myBulk, 
LinearSystem& myLS,
 
 2484     const USI np = myBulk.numPhase;
 
 2485     const USI nc = myBulk.numCom;
 
 2486     const USI nch = nc - 1;
 
 2487     const USI ncol = nc + 1;
 
 2488     const USI ncol2 = np * nc + np;
 
 2489     const USI bsize = ncol * ncol;
 
 2490     const USI bsize2 = ncol * ncol2;
 
 2498     vector<OCP_DBL> bmat(bsize, 0);
 
 2499     vector<OCP_DBL> bmat2(bsize, 0);
 
 2500     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 2501     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 2502     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 2503     vector<bool>    phaseExistB(np, 
false);
 
 2504     vector<USI>     pEnumComB(np, 0);
 
 2508     for (
USI p = 0; p < numPerf; p++) {
 
 2509         const OCP_USI n = perf[p].location;
 
 2510         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 2511         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 2512         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 2514         dP = myBulk.P[n] - BHP - dG[p];
 
 2516         const USI npB = myBulk.phaseNum[n] + 1;  ncolB = npB;
 
 2517         for (
USI j = 0; j < np; j++) {
 
 2518             phaseExistB[j] = myBulk.phaseExist[n * np + j];
 
 2519             pEnumComB[j] = myBulk.pEnumCom[n * np + j];
 
 2520             ncolB += pEnumComB[j];
 
 2525         for (
USI j = 0; j < np; j++) {
 
 2527             if (!phaseExistB[j]) {
 
 2528                 jxB += pEnumComB[j];
 
 2532             n_np_j = n * np + j;
 
 2533             mu = myBulk.mu[n_np_j];
 
 2534             muP = myBulk.muP[n_np_j];
 
 2536             for (
USI i = 0; i < nc; i++) {
 
 2538                 transIJ = perf[p].transj[j] * perf[p].xi * opt.zi[i];
 
 2539                 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
 
 2540                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 2544                 for (
USI j1 = 0; j1 < np; j1++) {
 
 2545                     if (phaseExistB[j1]) {
 
 2546                         dQdXsB[(i + 1) * ncolB + j1B] +=
 
 2547                             CONV1 * perf[p].WI * perf[p].multiplier * perf[p].xi *
 
 2548                             opt.zi[i] * myBulk.dKr_dS[n_np_j * np + j1] * dP / mu;
 
 2554                 for (
USI k = 0; k < pEnumComB[j]; k++) {
 
 2555                     dQdXsB[(i + 1) * ncolB + jxB + k] +=
 
 2556                         -transIJ * dP / mu * myBulk.mux[n_np_j * nc + k];
 
 2559             jxB += pEnumComB[j];
 
 2565             DaAxpby(ncol, ncolB, -1.0, dQdXsB.data(),
 
 2566                 &myBulk.res_n[myBulk.resIndex[n]], 1.0, &myLS.b[n * ncol]);
 
 2574         DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1,
 
 2576         Dscalar(bsize, dt, bmat.data());
 
 2578         USI ptr = myLS.diagPtr[n];
 
 2579         for (
USI i = 0; i < bsize; i++) {
 
 2580             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 2584         Dscalar(bsize, dt, bmat.data());
 
 2585         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 2586         myLS.colId[n].push_back(wId);
 
 2589         switch (opt.optMode) {
 
 2596             fill(bmat.begin(), bmat.end(), 0.0);
 
 2597             for (
USI i = 0; i < nc; i++) {
 
 2598                 bmat[0] += dQdXpW[(i + 1) * ncol];
 
 2599                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 2601             for (
USI i = 0; i < bsize; i++) {
 
 2602                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2609             DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(),
 
 2610                 &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1, bmat.data());
 
 2611             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 2612             for (
USI i = 0; i < nc; i++) {
 
 2613                 Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
 
 2615             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 2616             myLS.colId[wId].push_back(n);
 
 2621             fill(bmat.begin(), bmat.end(), 0.0);
 
 2622             for (
USI i = 0; i < nc + 1; i++) {
 
 2623                 bmat[i * ncol + i] = 1;
 
 2626             for (
USI i = 0; i < bsize; i++) {
 
 2627                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2630             fill(bmat.begin(), bmat.end(), 0.0);
 
 2632             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 2633             myLS.colId[wId].push_back(n);
 
 2643     assert(myLS.val[wId].size() == numPerf * bsize);
 
 2645     myLS.colId[wId].push_back(wId);
 
 2646     myLS.diagPtr[wId] = numPerf;
 
 2647     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 2648         myLS.diagVal.data() + wId * bsize + bsize);
 
 2652 void Well::AssembleMatPROD_FIM_new_n(
const Bulk& myBulk, 
LinearSystem& myLS,
 
 2661     const USI np = myBulk.numPhase;
 
 2662     const USI nc = myBulk.numCom;
 
 2663     const USI nch = nc - 1;
 
 2664     const USI ncol = nc + 1;
 
 2665     const USI ncol2 = np * nc + np;
 
 2666     const USI bsize = ncol * ncol;
 
 2667     const USI bsize2 = ncol * ncol2;
 
 2669     OCP_DBL xij, xi, mu, muP, xiP;
 
 2676     vector<OCP_DBL> bmat(bsize, 0);
 
 2677     vector<OCP_DBL> bmat2(bsize, 0);
 
 2678     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 2679     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 2680     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 2681     vector<bool>    phaseExistB(np, 
false);
 
 2682     vector<USI>     pEnumComB(np, 0);
 
 2689     for (
USI p = 0; p < numPerf; p++) {
 
 2691         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 2692         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 2693         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 2695         const USI npB = myBulk.phaseNum[n] + 1;    ncolB = npB;
 
 2696         for (
USI j = 0; j < np; j++) {
 
 2697             phaseExistB[j] = myBulk.phaseExist[n * np + j];
 
 2698             pEnumComB[j] = myBulk.pEnumCom[n * np + j];
 
 2699             ncolB += pEnumComB[j];
 
 2704         for (
USI j = 0; j < np; j++) {
 
 2706             if (!phaseExistB[j]) {
 
 2707                 jxB += pEnumComB[j];
 
 2711             n_np_j = n * np + j;
 
 2712             dP = myBulk.Pj[n_np_j] - BHP - dG[p];
 
 2713             xi = myBulk.xi[n_np_j];
 
 2714             mu = myBulk.mu[n_np_j];
 
 2715             muP = myBulk.muP[n_np_j];
 
 2716             xiP = myBulk.xiP[n_np_j];
 
 2719             for (
USI i = 0; i < nc; i++) {
 
 2720                 xij = myBulk.xij[n_np_j * nc + i];
 
 2722                 transIJ = perf[p].transj[j] * xi * xij;
 
 2723                 dQdXpB[(i + 1) * ncol] +=
 
 2724                     transIJ * (1 - dP * muP / mu) + dP * perf[p].transj[j] * xij * xiP;
 
 2725                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 2729                 for (
USI j1 = 0; j1 < np; j1++) {
 
 2730                     if (phaseExistB[j1]) {
 
 2731                         tmp = 
CONV1 * perf[p].WI * perf[p].multiplier * dP / mu * xi * xij *
 
 2732                             myBulk.dKr_dS[n_np_j * np + j1];
 
 2734                         tmp += transIJ * myBulk.dPcj_dS[n_np_j * np + j1];
 
 2735                         dQdXsB[(i + 1) * ncolB + j1B] += tmp;
 
 2740                 for (
USI k = 0; k < pEnumComB[j]; k++) {
 
 2741                     tmp = dP * perf[p].transj[j] * xij *
 
 2742                         (myBulk.xix[n_np_j * nc + k] -
 
 2743                             xi / mu * myBulk.mux[n_np_j * nc + k]);
 
 2744                     tmp -= transIJ * dP / myBulk.nj[n_np_j];
 
 2745                     dQdXsB[(i + 1) * ncolB + jxB + k] += tmp;
 
 2748                 if (i < pEnumComB[j])
 
 2749                     dQdXsB[(i + 1) * ncolB + jxB + i] += perf[p].transj[j] * xi * dP / myBulk.nj[n_np_j];
 
 2751             jxB += pEnumComB[j];
 
 2757             DaAxpby(ncol, ncolB, -1.0, dQdXsB.data(),
 
 2758                 &myBulk.res_n[myBulk.resIndex[n]], 1.0, &myLS.b[n * ncol]);
 
 2766         DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(), &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1,
 
 2769         Dscalar(bsize, dt, bmat.data());
 
 2771         USI ptr = myLS.diagPtr[n];
 
 2772         for (
USI i = 0; i < bsize; i++) {
 
 2773             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 2777         Dscalar(bsize, dt, bmat.data());
 
 2778         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 2779         myLS.colId[n].push_back(wId);
 
 2782         switch (opt.optMode) {
 
 2789             fill(bmat.begin(), bmat.end(), 0.0);
 
 2790             for (
USI i = 0; i < nc; i++) {
 
 2791                 bmat[0] += dQdXpW[(i + 1) * ncol] * prodWeight[i];
 
 2792                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 2794             for (
USI i = 0; i < bsize; i++) {
 
 2795                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2802             DaABpbC(ncol, ncol, ncolB, 1, dQdXsB.data(),
 
 2803                 &myBulk.dSec_dPri[myBulk.dSdPindex[n]], 1, bmat.data());
 
 2804             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 2805             for (
USI i = 0; i < nc; i++) {
 
 2806                 Daxpy(ncol, prodWeight[i], bmat.data() + (i + 1) * ncol,
 
 2809             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 2810             myLS.colId[wId].push_back(n);
 
 2815             fill(bmat.begin(), bmat.end(), 0.0);
 
 2816             for (
USI i = 0; i < nc + 1; i++) {
 
 2817                 bmat[i * ncol + i] = 1;
 
 2820             for (
USI i = 0; i < bsize; i++) {
 
 2821                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2824             fill(bmat.begin(), bmat.end(), 0.0);
 
 2826             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 2827             myLS.colId[wId].push_back(n);
 
 2837     assert(myLS.val[wId].size() == numPerf * bsize);
 
 2839     myLS.colId[wId].push_back(wId);
 
 2840     myLS.diagPtr[wId] = numPerf;
 
 2841     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 2842         myLS.diagVal.data() + wId * bsize + bsize);
 
 2855     const USI np = myBulk.numPhase;
 
 2856     const USI nc = myBulk.numCom;
 
 2857     const USI ncol = nc + 1;
 
 2858     const USI ncol2 = np * nc + np;
 
 2859     const USI bsize = ncol * ncol;
 
 2860     const USI bsize2 = ncol * ncol2;
 
 2869     vector<OCP_DBL> bmat(bsize, 0);
 
 2870     vector<OCP_DBL> bmat2(bsize, 0);
 
 2871     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 2872     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 2873     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 2875     for (
USI p = 0; p < numPerf; p++) {
 
 2877         pIde = myBulk.map_Bulk2FIM[n];
 
 2879         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 2880         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 2881         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 2883         dP = myBulk.P[n] - BHP - dG[p];
 
 2885         for (
USI j = 0; j < np; j++) {
 
 2886             n_np_j = n * np + j;
 
 2887             if (!myBulk.phaseExist[n_np_j]) 
continue;
 
 2889             pIde_np_j = pIde * np + j;
 
 2890             mu = myBulk.mu[n_np_j];
 
 2891             muP = myBulk.muP[pIde_np_j];
 
 2893             for (
USI i = 0; i < nc; i++) {
 
 2895                 transIJ = perf[p].transj[j] * perf[p].xi * opt.zi[i];
 
 2896                 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
 
 2897                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 2900                 for (
USI k = 0; k < np; k++) {
 
 2901                     dQdXsB[(i + 1) * ncol2 + k] +=
 
 2902                         CONV1 * perf[p].WI * perf[p].multiplier * perf[p].xi *
 
 2903                         opt.zi[i] * myBulk.dKr_dS[pIde * np * np + j * np + k] * dP / mu;
 
 2906                 for (
USI k = 0; k < nc; k++) {
 
 2907                     dQdXsB[(i + 1) * ncol2 + np + j * nc + k] +=
 
 2908                         -transIJ * dP / mu * myBulk.mux[pIde_np_j * nc + k];
 
 2914         DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(), &myBulk.dSec_dPri[pIde * bsize2], 1,
 
 2916         Dscalar(bsize, dt, bmat.data());
 
 2918         USI ptr = myLS.diagPtr[pIde];
 
 2919         for (
USI i = 0; i < bsize; i++) {
 
 2920             myLS.val[pIde][ptr * bsize + i] += bmat[i];
 
 2924         Dscalar(bsize, dt, bmat.data());
 
 2925         myLS.val[pIde].insert(myLS.val[pIde].end(), bmat.begin(), bmat.end());
 
 2926         myLS.colId[pIde].push_back(wId);
 
 2929         switch (opt.optMode) {
 
 2936             fill(bmat.begin(), bmat.end(), 0.0);
 
 2937             for (
USI i = 0; i < nc; i++) {
 
 2938                 bmat[0] += dQdXpW[(i + 1) * ncol];
 
 2939                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 2941             for (
USI i = 0; i < bsize; i++) {
 
 2942                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2947             DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(),
 
 2948                 &myBulk.dSec_dPri[pIde * bsize2], 1, bmat.data());
 
 2949             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 2950             for (
USI i = 0; i < nc; i++) {
 
 2951                 Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
 
 2953             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 2954             myLS.colId[wId].push_back(pIde);
 
 2959             fill(bmat.begin(), bmat.end(), 0.0);
 
 2960             for (
USI i = 0; i < nc + 1; i++) {
 
 2961                 bmat[i * ncol + i] = 1;
 
 2964             for (
USI i = 0; i < bsize; i++) {
 
 2965                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 2968             fill(bmat.begin(), bmat.end(), 0.0);
 
 2970             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 2971             myLS.colId[wId].push_back(pIde);
 
 2981     assert(myLS.val[wId].size() == numPerf * bsize);
 
 2983     myLS.colId[wId].push_back(wId);
 
 2984     myLS.diagPtr[wId] = numPerf;
 
 2985     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 2986         myLS.diagVal.data() + wId * bsize + bsize);
 
 2999     const USI np = myBulk.numPhase;
 
 3000     const USI nc = myBulk.numCom;
 
 3001     const USI ncol = nc + 1;
 
 3002     const USI ncol2 = np * nc + np;
 
 3003     const USI bsize = ncol * ncol;
 
 3004     const USI bsize2 = ncol * ncol2;
 
 3006     OCP_DBL xij, xi, mu, muP, xiP;
 
 3014     vector<OCP_DBL> bmat(bsize, 0);
 
 3015     vector<OCP_DBL> bmat2(bsize, 0);
 
 3016     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 3017     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 3018     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 3023     for (
USI p = 0; p < numPerf; p++) {
 
 3025         pIde = myBulk.map_Bulk2FIM[n];
 
 3026         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 3027         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 3028         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 3030         for (
USI j = 0; j < np; j++) {
 
 3031             n_np_j = n * np + j;
 
 3032             if (!myBulk.phaseExist[n_np_j]) 
continue;
 
 3034             pIde_np_j = pIde * np + j;
 
 3035             dP = myBulk.Pj[n_np_j] - BHP - dG[p];
 
 3036             xi = myBulk.xi[n_np_j];
 
 3037             mu = myBulk.mu[n_np_j];
 
 3038             muP = myBulk.muP[pIde_np_j];
 
 3039             xiP = myBulk.xiP[pIde_np_j];
 
 3041             for (
USI i = 0; i < nc; i++) {
 
 3042                 xij = myBulk.xij[n_np_j * nc + i];
 
 3044                 transIJ = perf[p].transj[j] * xi * xij;
 
 3045                 dQdXpB[(i + 1) * ncol] +=
 
 3046                     transIJ * (1 - dP * muP / mu) + dP * perf[p].transj[j] * xij * xiP;
 
 3047                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 3050                 for (
USI k = 0; k < np; k++) {
 
 3051                     tmp = 
CONV1 * perf[p].WI * perf[p].multiplier * dP / mu * xi * xij *
 
 3052                         myBulk.dKr_dS[pIde * np * np + j * np + k];
 
 3054                     tmp += transIJ * myBulk.dPcj_dS[pIde * np * np + j * np + k];
 
 3055                     dQdXsB[(i + 1) * ncol2 + k] += tmp;
 
 3058                 for (
USI k = 0; k < nc; k++) {
 
 3059                     tmp = dP * perf[p].transj[j] * xij *
 
 3060                         (myBulk.xix[pIde_np_j * nc + k] -
 
 3061                             xi / mu * myBulk.mux[pIde_np_j * nc + k]);
 
 3063                         tmp += perf[p].transj[j] * xi * dP;
 
 3065                     dQdXsB[(i + 1) * ncol2 + np + j * nc + k] += tmp;
 
 3071         DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(), &myBulk.dSec_dPri[pIde * bsize2], 1,
 
 3078         Dscalar(bsize, dt, bmat.data());
 
 3080         USI ptr = myLS.diagPtr[pIde];
 
 3081         for (
USI i = 0; i < bsize; i++) {
 
 3082             myLS.val[pIde][ptr * bsize + i] += bmat[i];
 
 3086         Dscalar(bsize, dt, bmat.data());
 
 3087         myLS.val[pIde].insert(myLS.val[pIde].end(), bmat.begin(), bmat.end());
 
 3088         myLS.colId[pIde].push_back(wId);
 
 3091         switch (opt.optMode) {
 
 3098             fill(bmat.begin(), bmat.end(), 0.0);
 
 3099             for (
USI i = 0; i < nc; i++) {
 
 3100                 bmat[0] += dQdXpW[(i + 1) * ncol] * prodWeight[i];
 
 3101                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 3103             for (
USI i = 0; i < bsize; i++) {
 
 3104                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 3109             DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(),
 
 3110                 &myBulk.dSec_dPri[pIde * bsize2], 1, bmat.data());
 
 3111             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 3112             for (
USI i = 0; i < nc; i++) {
 
 3113                 Daxpy(ncol, prodWeight[i], bmat.data() + (i + 1) * ncol,
 
 3116             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 3117             myLS.colId[wId].push_back(pIde);
 
 3122             fill(bmat.begin(), bmat.end(), 0.0);
 
 3123             for (
USI i = 0; i < nc + 1; i++) {
 
 3124                 bmat[i * ncol + i] = 1;
 
 3127             for (
USI i = 0; i < bsize; i++) {
 
 3128                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 3131             fill(bmat.begin(), bmat.end(), 0.0);
 
 3133             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 3134             myLS.colId[wId].push_back(pIde);
 
 3144     assert(myLS.val[wId].size() == numPerf * bsize);
 
 3146     myLS.colId[wId].push_back(wId);
 
 3147     myLS.diagPtr[wId] = numPerf;
 
 3148     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 3149         myLS.diagVal.data() + wId * bsize + bsize);
 
 3158     const OCP_USI& wId, 
const vector<Well>& allWell)
 const 
 3163     const USI nc = myBulk.numCom;
 
 3164     const USI len = nc + 1;
 
 3167     for (
USI p = 0; p < numPerf; p++) {
 
 3168         k = perf[p].location;
 
 3169         bIde = myBulk.map_Bulk2FIM[k];
 
 3170         for (
USI i = 0; i < nc; i++) {
 
 3171             resFIM.res[bIde * len + 1 + i] += perf[p].qi_lbmol[i] * dt;
 
 3175     OCP_USI bId = (myBulk.numFIMBulk + wId) * len;
 
 3177     if (opt.type == 
INJ) {
 
 3179         switch (opt.optMode) {
 
 3182             resFIM.res[bId] = BHP - opt.maxBHP;
 
 3189             resFIM.res[bId] = opt.maxRate;
 
 3190             for (
USI i = 0; i < nc; i++) {
 
 3191                 resFIM.res[bId] += qi_lbmol[i];
 
 3194                 for (
auto& w : opt.connWell) {
 
 3196                     for (
USI i = 0; i < nc; i++) {
 
 3197                         tmp += allWell[w].qi_lbmol[i];
 
 3202                     resFIM.res[bId] += tmp;
 
 3209             resFIM.maxRelRes_v =
 
 3210                 max(resFIM.maxRelRes_v, fabs(resFIM.res[bId] / opt.maxRate));
 
 3219         switch (opt.optMode) {
 
 3222             resFIM.res[bId] = BHP - opt.minBHP;
 
 3229             resFIM.res[bId] = -opt.maxRate;
 
 3230             for (
USI i = 0; i < nc; i++) {
 
 3231                 resFIM.res[bId] += qi_lbmol[i] * prodWeight[i];
 
 3236             resFIM.maxRelRes_v =
 
 3237                 max(resFIM.maxRelRes_v, fabs(resFIM.res[bId] / opt.maxRate));
 
 3256     const USI np = myBulk.numPhase;
 
 3257     const USI nc = myBulk.numCom;
 
 3258     const USI ncol = nc + 1;
 
 3259     const USI ncol2 = np * nc + np;
 
 3260     const USI bsize = ncol * ncol;
 
 3261     const USI bsize2 = ncol * ncol2;
 
 3269     vector<OCP_DBL> bmat(bsize, 0);
 
 3270     vector<OCP_DBL> bmat2(bsize, 0);
 
 3271     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 3272     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 3273     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 3275     for (
USI p = 0; p < numPerf; p++) {
 
 3277         OCP_USI pId = myBulk.map_Bulk2FIM[n];
 
 3278         OCP_ASSERT(pId < myBulk.numFIMBulk, 
"wrong FIM Bulk");
 
 3280         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 3281         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 3282         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 3284         dP = myBulk.P[n] - BHP - dG[p];
 
 3286         for (
USI j = 0; j < np; j++) {
 
 3287             n_np_j = n * np + j;
 
 3288             if (!myBulk.phaseExist[n_np_j]) 
continue;
 
 3290             mu = myBulk.mu[n_np_j];
 
 3291             muP = myBulk.muP[n_np_j];
 
 3293             for (
USI i = 0; i < nc; i++) {
 
 3295                 transIJ = perf[p].transj[j] * perf[p].xi * opt.zi[i];
 
 3296                 dQdXpB[(i + 1) * ncol] += transIJ * (1 - dP * muP / mu);
 
 3297                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 3300                 for (
USI k = 0; k < np; k++) {
 
 3301                     dQdXsB[(i + 1) * ncol2 + k] +=
 
 3302                         CONV1 * perf[p].WI * perf[p].multiplier * perf[p].xi *
 
 3303                         opt.zi[i] * myBulk.dKr_dS[pId * np * np + j * np + k] * dP / mu;
 
 3306                 for (
USI k = 0; k < nc; k++) {
 
 3307                     dQdXsB[(i + 1) * ncol2 + np + j * nc + k] +=
 
 3308                         -transIJ * dP / mu * myBulk.mux[n_np_j * nc + k];
 
 3314         DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(), &myBulk.dSec_dPri[pId * bsize2], 1,
 
 3316         Dscalar(bsize, dt, bmat.data());
 
 3318         USI ptr = myLS.diagPtr[n];
 
 3319         for (
USI i = 0; i < bsize; i++) {
 
 3320             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 3324         Dscalar(bsize, dt, bmat.data());
 
 3325         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 3326         myLS.colId[n].push_back(wId);
 
 3329         switch (opt.optMode) {
 
 3336             fill(bmat.begin(), bmat.end(), 0.0);
 
 3337             for (
USI i = 0; i < nc; i++) {
 
 3338                 bmat[0] += dQdXpW[(i + 1) * ncol];
 
 3339                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 3341             for (
USI i = 0; i < bsize; i++) {
 
 3342                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 3347             DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(),
 
 3348                 &myBulk.dSec_dPri[pId * bsize2], 1, bmat.data());
 
 3349             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 3350             for (
USI i = 0; i < nc; i++) {
 
 3351                 Daxpy(ncol, 1.0, bmat.data() + (i + 1) * ncol, bmat2.data());
 
 3353             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 3354             myLS.colId[wId].push_back(n);
 
 3359             fill(bmat.begin(), bmat.end(), 0.0);
 
 3360             for (
USI i = 0; i < nc + 1; i++) {
 
 3361                 bmat[i * ncol + i] = 1;
 
 3364             for (
USI i = 0; i < bsize; i++) {
 
 3365                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 3368             fill(bmat.begin(), bmat.end(), 0.0);
 
 3370             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 3371             myLS.colId[wId].push_back(n);
 
 3381     assert(myLS.val[wId].size() == numPerf * bsize);
 
 3383     myLS.colId[wId].push_back(wId);
 
 3384     myLS.diagPtr[wId] = numPerf;
 
 3385     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 3386         myLS.diagVal.data() + wId * bsize + bsize);
 
 3399     const USI np = myBulk.numPhase;
 
 3400     const USI nc = myBulk.numCom;
 
 3401     const USI ncol = nc + 1;
 
 3402     const USI ncol2 = np * nc + np;
 
 3403     const USI bsize = ncol * ncol;
 
 3404     const USI bsize2 = ncol * ncol2;
 
 3406     OCP_DBL xij, xi, mu, muP, xiP;
 
 3413     vector<OCP_DBL> bmat(bsize, 0);
 
 3414     vector<OCP_DBL> bmat2(bsize, 0);
 
 3415     vector<OCP_DBL> dQdXpB(bsize, 0);
 
 3416     vector<OCP_DBL> dQdXpW(bsize, 0);
 
 3417     vector<OCP_DBL> dQdXsB(bsize2, 0);
 
 3422     for (
USI p = 0; p < numPerf; p++) {
 
 3424         OCP_USI pId = myBulk.map_Bulk2FIM[n];
 
 3425         OCP_ASSERT(pId < myBulk.numFIMBulk, 
"wrong FIM Bulk");
 
 3427         fill(dQdXpB.begin(), dQdXpB.end(), 0.0);
 
 3428         fill(dQdXpW.begin(), dQdXpW.end(), 0.0);
 
 3429         fill(dQdXsB.begin(), dQdXsB.end(), 0.0);
 
 3431         for (
USI j = 0; j < np; j++) {
 
 3432             n_np_j = n * np + j;
 
 3433             if (!myBulk.phaseExist[n_np_j]) 
continue;
 
 3435             dP = myBulk.Pj[n_np_j] - BHP - dG[p];
 
 3436             xi = myBulk.xi[n_np_j];
 
 3437             mu = myBulk.mu[n_np_j];
 
 3438             muP = myBulk.muP[n_np_j];
 
 3439             xiP = myBulk.xiP[n_np_j];
 
 3441             for (
USI i = 0; i < nc; i++) {
 
 3442                 xij = myBulk.xij[n_np_j * nc + i];
 
 3444                 transIJ = perf[p].transj[j] * xi * xij;
 
 3445                 dQdXpB[(i + 1) * ncol] +=
 
 3446                     transIJ * (1 - dP * muP / mu) + dP * perf[p].transj[j] * xij * xiP;
 
 3447                 dQdXpW[(i + 1) * ncol] += -transIJ;
 
 3454                 for (
USI k = 0; k < np; k++) {
 
 3455                     tmp = 
CONV1 * perf[p].WI * perf[p].multiplier * dP / mu * xi * xij *
 
 3456                         myBulk.dKr_dS[pId * np * np + j * np + k];
 
 3458                     tmp += transIJ * myBulk.dPcj_dS[pId * np * np + j * np + k];
 
 3459                     dQdXsB[(i + 1) * ncol2 + k] += tmp;
 
 3462                 for (
USI k = 0; k < nc; k++) {
 
 3463                     tmp = dP * perf[p].transj[j] * xij *
 
 3464                         (myBulk.xix[n_np_j * nc + k] -
 
 3465                             xi / mu * myBulk.mux[n_np_j * nc + k]);
 
 3467                         tmp += perf[p].transj[j] * xi * dP;
 
 3469                     dQdXsB[(i + 1) * ncol2 + np + j * nc + k] += tmp;
 
 3475         DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(), &myBulk.dSec_dPri[pId * bsize2], 1,
 
 3478         Dscalar(bsize, dt, bmat.data());
 
 3480         USI ptr = myLS.diagPtr[n];
 
 3481         for (
USI i = 0; i < bsize; i++) {
 
 3482             myLS.val[n][ptr * bsize + i] += bmat[i];
 
 3486         Dscalar(bsize, dt, bmat.data());
 
 3487         myLS.val[n].insert(myLS.val[n].end(), bmat.begin(), bmat.end());
 
 3488         myLS.colId[n].push_back(wId);
 
 3491         switch (opt.optMode) {
 
 3498             fill(bmat.begin(), bmat.end(), 0.0);
 
 3499             for (
USI i = 0; i < nc; i++) {
 
 3500                 bmat[0] += dQdXpW[(i + 1) * ncol] * prodWeight[i];
 
 3501                 bmat[(i + 1) * ncol + i + 1] = 1;
 
 3503             for (
USI i = 0; i < bsize; i++) {
 
 3504                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 3509             DaABpbC(ncol, ncol, ncol2, 1, dQdXsB.data(),
 
 3510                 &myBulk.dSec_dPri[pId * bsize2], 1, bmat.data());
 
 3511             fill(bmat2.begin(), bmat2.end(), 0.0);
 
 3512             for (
USI i = 0; i < nc; i++) {
 
 3513                 Daxpy(ncol, prodWeight[i], bmat.data() + (i + 1) * ncol,
 
 3516             myLS.val[wId].insert(myLS.val[wId].end(), bmat2.begin(), bmat2.end());
 
 3517             myLS.colId[wId].push_back(n);
 
 3522             fill(bmat.begin(), bmat.end(), 0.0);
 
 3523             for (
USI i = 0; i < nc + 1; i++) {
 
 3524                 bmat[i * ncol + i] = 1;
 
 3527             for (
USI i = 0; i < bsize; i++) {
 
 3528                 myLS.diagVal[wId * bsize + i] += bmat[i];
 
 3531             fill(bmat.begin(), bmat.end(), 0.0);
 
 3533             myLS.val[wId].insert(myLS.val[wId].end(), bmat.begin(), bmat.end());
 
 3534             myLS.colId[wId].push_back(n);
 
 3544     assert(myLS.val[wId].size() == numPerf * bsize);
 
 3546     myLS.colId[wId].push_back(wId);
 
 3547     myLS.diagPtr[wId] = numPerf;
 
 3548     myLS.val[wId].insert(myLS.val[wId].end(), myLS.diagVal.data() + wId * bsize,
 
 3549         myLS.diagVal.data() + wId * bsize + bsize);
 
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.
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.
const USI X_DIRECTION
x-direction
const USI BLKOIL
Mixture model = black-oil.
const OCP_DBL TINY
Small constant.
const USI EOS_PVTW
Mixture model = equation-of-state.
unsigned int USI
Generic unsigned integer.
const USI GAS
Fluid type = gas.
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 WATER
Fluid type = water.
const USI PHASE_ODGW
Phase type = oil-dry gas-water.
const USI Y_DIRECTION
y-direction
const USI ORATE_MODE
Well option = fixed oil rate.
const USI OIL
Fluid type = oil.
const bool CLOSE
Well type = closed.
const USI PHASE_W
Phase type = water only.
const USI RATE_MODE
Well option = fixed total rate???
unsigned int OCP_USI
Long unsigned integer.
const bool OPEN
Well type = open.
const USI Z_DIRECTION
z-direction
const USI PHASE_OW
Phase type = oil-water.
const USI PROD
Well type = producer.
const OCP_DBL TEMPERATURE_STD
Standard temperature.
const USI PHASE_DOGW
Phase type = dead oil-gas-water.
const USI INJ
Well type = injector.
const USI BHP_MODE
Well option = fixed bottom-hole-pressure.
const USI GRATE_MODE
Well option = fixed gas rate.
const OCP_DBL PRESSURE_STD
14.6959 psia = 1 atm
const OCP_DBL CONV2
Darcy constant in field unit.
#define OCP_FUNCNAME
Print Function Name.
#define OCP_WARNING(msg)
Log warning messages.
#define OCP_ASSERT(cond, msg)
Assert condition and log user messages in DEBUG mode.
#define OCP_ABORT(msg)
Abort if critical error happens.
Physical information of each active reservoir bulk.
Basic information of computational grid, including the rock properties.
Linear solvers for discrete systems.
OCP_DBL maxBHP
Maximum allowable pressure in the injection well.
string type
Type of well, injection or production?
string fluidType
Type of fluid into the injection well. (injection well only)
OCP_DBL maxRate
Maximum allowable flow rate into/out the well.
string optMode
Mode of well, Rate or BHP?
OCP_DBL minBHP
Minimum allowable pressure in the production well.
string state
State of well, open or close?
WellOpt()=default
Default constructor.
bool operator!=(const WellOpt &Opt) const
overload inequality
vector< string > direction
Direction of perforations.
vector< OCP_DBL > diameter
Diameter of perforations.
vector< OCP_DBL > skinFactor
Skin factor.
vector< USI > I_perf
I-index of perforation in grid.
vector< OCP_DBL > WI
Transmissiblity connection factor.
vector< USI > J_perf
J-index of perforation in grid.
vector< USI > K_perf
K-index of perforation in grid.
void AssembleMatPROD_AIMt(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for AIMt, parts related to Production well are included.
void AssembleMatPROD_IMPEC(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for IMPEC, parts related to production well are included.
void AssembleMatReinjection_IMPEC(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt, const vector< Well > &allWell, const vector< USI > &injId) const
void SetBHP()
Set BHP if opt mode is BHPMode.
void Setup(const Grid &myGrid, const Bulk &myBulk, const vector< SolventINJ > &sols)
Setup the well after Grid and Bulk finish setupping.
void CheckOptMode(const Bulk &myBulk)
Check if well operation mode would be changed.
void CalProdQjCOMP(const Bulk &myBulk)
Calculate flow rate of moles of phase for production well in Compositional Model.
void CalWI_Peaceman_Vertical(const Bulk &myBulk)
Calculate Well Index with Peaceman model for vertical well.
OCP_INT CheckP(const Bulk &myBulk)
Check if abnormal Pressure occurs.
void AssembleMatINJ_AIMt(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for AIMt, parts related to Injection well are included.
void CalInjdG(const Bulk &myBulk)
Calculate pressure difference between well and perforations for Injection.
void AssembleMatINJ_FIM(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for FIM, parts related to Injection well are included.
void AssembleMatPROD_FIM_new(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for FIM, parts related to Production well are included.
void CalProdQj(const Bulk &myBulk, const OCP_DBL &dt)
Calculate flow rate of moles of phase for production well.
void AssembleMatINJ_FIM_new(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for FIM, parts related to Injection well are included.
void SetupWellBulk(Bulk &myBulk) const
Setup bulks which are penetrated by wells.
void MassConserveIMPEC(Bulk &myBulk, const OCP_DBL &dt) const
Update moles of components in those bulks who connects to the well.
void CalReInjFluid(const Bulk &myBulk, vector< OCP_DBL > &myZi)
Calculate the contribution of production well to reinjection defaulted.
void InputPerfo(const WellParam &well)
Input the param of perforations.
void AssembleMatPROD_FIM(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for FIM, parts related to Production well are included.
void AssembleMatINJ_AIMs(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for AIMs, parts related to Injection well are included.
void CalProdQiBO(const Bulk &myBulk)
bool WellState() const
Return the state of the well, Open or Close.
void AssembleMatPROD_AIMs(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for AIMs, parts related to Production well are included.
void CalTrans(const Bulk &myBulk)
Calculate transmissibility for each phase in perforations.
void CalFlux(const Bulk &myBulk, const bool flag=false)
Calculate the flux for each perforations.
void CalProddG(const Bulk &myBulk)
Calculate pressure difference between well and perforations for Prodcution.
void AllocateMat(LinearSystem &myLS) const
Allocate memory for matrix.
void CaldG(const Bulk &myBulk)
Calculate pressure difference between well and perforations.
void AssembleMatINJ_IMPEC(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt) const
Assemble matrix for IMPEC, parts related to injection well are included.
OCP_INT CheckCrossFlow(const Bulk &myBulk)
Check if crossflow happens.
void SmoothdG()
Try to smooth the dG by average it with dG at last time step.
void CalResAIMt(ResFIM &resFIM, const Bulk &myBulk, const OCP_DBL &dt, const OCP_USI &wId, const vector< Well > &allWell) const
Calculate Resiual and relative Resiual for local FIM.
void AssembleMatReinjection_FIM(const Bulk &myBulk, LinearSystem &myLS, const OCP_DBL &dt, const vector< Well > &allWell, const vector< USI > &injId) const
void ShowPerfStatus(const Bulk &myBulk) const
Display operation mode of well and state of perforations.
void InitBHP(const Bulk &myBulk)
Initialize the Well BHP.
void CalInjQi(const Bulk &myBulk, const OCP_DBL &dt)
Calculate flow rate of moles of components for injection well.
OCP_DBL CalProdRate(const Bulk &myBulk, const bool &minBHP)
calculate flow rate of moles of components for production well with minBHP
void CalProdWeight(const Bulk &myBulk) const
Calculate the Prodweight.
void CalCFL(const Bulk &myBulk, const OCP_DBL &dt) const
Calculate the CFL number, only parts related to wells are considered.
OCP_DBL CalInjRate(const Bulk &myBulk, const bool &maxBHP)
calculate flow rate of moles of components for injection well with maxBHP
void CalResFIM(ResFIM &resFIM, const Bulk &myBulk, const OCP_DBL &dt, const OCP_USI &wId, const vector< Well > &allWell) const
Calculate Resiual and relative Resiual for FIM.