vcs_MultiPhaseEquil.cpp

Go to the documentation of this file.
00001 /**
00002  *  @file vcs_MultiPhaseEquil.cpp
00003  *    Driver routine for the VCSnonideal equilibrium solver package
00004  */
00005 /*
00006  * $Id: vcs_MultiPhaseEquil.cpp 368 2010-01-04 00:46:26Z hkmoffa $
00007  */
00008 /*
00009  * Copywrite (2006) Sandia Corporation. Under the terms of
00010  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
00011  * U.S. Government retains certain rights in this software.
00012  */
00013 
00014 #include "vcs_MultiPhaseEquil.h"
00015 #include "vcs_prob.h"
00016 #include "vcs_internal.h"
00017 #include "vcs_VolPhase.h"
00018 #include "vcs_species_thermo.h"
00019 #include "vcs_SpeciesProperties.h"
00020 #include "vcs_VolPhase.h"
00021 
00022 #include "vcs_solve.h"
00023 
00024 #include "ct_defs.h"
00025 #include "mix_defs.h"
00026 #include "clockWC.h"
00027 #include "ThermoPhase.h"
00028 #include "speciesThermoTypes.h"
00029 #ifdef WITH_IDEAL_SOLUTIONS
00030 #include "IdealSolidSolnPhase.h"
00031 #endif
00032 #ifdef WITH_ELECTROLYTES
00033 #include "IdealMolalSoln.h"
00034 #endif
00035 #include "ChemEquil.h"
00036 
00037 #include <string>
00038 #include <vector>
00039 
00040 using namespace Cantera;
00041 using namespace std;
00042 //using namespace VCSnonideal;
00043 
00044 namespace VCSnonideal {
00045 
00046 
00047   vcs_MultiPhaseEquil::vcs_MultiPhaseEquil() :
00048     m_vprob(0),
00049     m_mix(0),
00050     m_printLvl(0),
00051     m_vsolvePtr(0)
00052   {
00053   }
00054 
00055   vcs_MultiPhaseEquil::vcs_MultiPhaseEquil(mix_t* mix, int printLvl) :
00056     m_vprob(0),
00057     m_mix(0),
00058     m_printLvl(printLvl),
00059     m_vsolvePtr(0)
00060   {
00061     // Debugging level
00062   
00063     int nsp = mix->nSpecies();
00064     int nel = mix->nElements();
00065     int nph = mix->nPhases();
00066     
00067     /*
00068      * Create a VCS_PROB object that describes the equilibrium problem.
00069      * The constructor just mallocs the necessary objects and sizes them.
00070      */
00071     m_vprob = new VCS_PROB(nsp, nel, nph);
00072     m_mix = mix;
00073     m_vprob->m_printLvl = m_printLvl;
00074     /*
00075      *  Work out the details of the VCS_VPROB construction and
00076      *  Transfer the current problem to VCS_PROB object
00077      */
00078     int res = vcs_Cantera_to_vprob(mix, m_vprob);
00079     if (res != 0) {
00080       plogf("problems\n");
00081    }
00082   }
00083 
00084   vcs_MultiPhaseEquil::~vcs_MultiPhaseEquil() {
00085     delete m_vprob;
00086     m_vprob = 0;
00087     if (m_vsolvePtr) {
00088       delete m_vsolvePtr;
00089       m_vsolvePtr = 0;
00090     }
00091   }
00092 
00093   int vcs_MultiPhaseEquil::equilibrate_TV(int XY, doublereal xtarget,
00094                                           int estimateEquil,
00095                                           int printLvl, doublereal err, 
00096                                           int maxsteps, int loglevel) {
00097 
00098     addLogEntry("problem type","fixed T, V");
00099     //            doublereal dt = 1.0e3;
00100     doublereal Vtarget = m_mix->volume();
00101     doublereal dVdP;
00102     if ((XY != TV) && (XY != HV) && (XY != UV) && (XY != SV)) {
00103       throw CanteraError("vcs_MultiPhaseEquil::equilibrate_TV",
00104                          "Wrong XY flag:" + int2str(XY));
00105     }
00106     int maxiter = 100;
00107     int iSuccess = 0;
00108     int innerXY;
00109     double Pnow;
00110     if (XY == TV) {
00111       m_mix->setTemperature(xtarget);
00112     }
00113     double Pnew;
00114     int strt = estimateEquil;
00115     double P1 = 0.0;
00116     double V1 = 0.0;
00117     double V2 = 0.0;
00118     double P2 = 0.0;
00119     doublereal Tlow = 0.5 * m_mix->minTemp();;
00120     doublereal Thigh = 2.0 * m_mix->maxTemp();
00121     doublereal Vnow, Verr;
00122     int printLvlSub = MAX(0, printLvl - 1);
00123     for (int n = 0; n < maxiter; n++) {
00124       Pnow = m_mix->pressure();
00125   
00126       beginLogGroup("iteration "+int2str(n));
00127       switch(XY) {
00128       case TV:
00129         iSuccess = equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel); 
00130         break;
00131       case HV:
00132         innerXY = HP;
00133         iSuccess = equilibrate_HP(xtarget, innerXY, Tlow, Thigh, strt, 
00134                                   printLvlSub, err, maxsteps, loglevel); 
00135         break;
00136       case UV:
00137         innerXY = UP;
00138         iSuccess = equilibrate_HP(xtarget, innerXY, Tlow, Thigh, strt, 
00139                                   printLvlSub, err, maxsteps, loglevel); 
00140         break;
00141       case SV:
00142         innerXY = SP;
00143         iSuccess = equilibrate_SP(xtarget, Tlow, Thigh, strt, 
00144                                   printLvlSub, err, maxsteps, loglevel); 
00145         break;
00146       default:
00147         break;
00148       }
00149       strt = false;
00150       Vnow = m_mix->volume();
00151       if (n == 0) {
00152         V2 = Vnow;
00153         P2 = Pnow;
00154       } else if (n == 1) {
00155         V1 = Vnow;
00156         P1 = Pnow;
00157       } else {
00158         P2 = P1;
00159         V2 = V1;
00160         P1 = Pnow;
00161         V1 = Vnow;
00162       }
00163       
00164       Verr = fabs((Vtarget - Vnow)/Vtarget);
00165       addLogEntry("P",fp2str(Pnow));
00166       addLogEntry("V rel error",fp2str(Verr));
00167       endLogGroup();
00168                 
00169       if (Verr < err) {
00170         addLogEntry("P iterations",int2str(n));
00171         addLogEntry("Final P",fp2str(Pnow));
00172         addLogEntry("V rel error",fp2str(Verr));
00173         goto done;
00174       }
00175       // find dV/dP
00176       if (n > 1) {
00177         dVdP = (V2 - V1) / (P2 - P1);
00178         if (dVdP == 0.0) {
00179           throw CanteraError("vcs_MultiPhase::equilibrate_TV",
00180                              "dVdP == 0.0");
00181         } else {
00182           Pnew = Pnow + (Vtarget - Vnow) / dVdP; 
00183           if (Pnew < 0.2 * Pnow) {
00184             Pnew = 0.2 * Pnow;
00185           }
00186           if (Pnew > 3.0 * Pnow) {
00187             Pnew = 3.0 * Pnow;
00188           }
00189         }
00190 
00191       } else {
00192         m_mix->setPressure(Pnow*1.01);
00193         dVdP = (m_mix->volume() - Vnow)/(0.01*Pnow);
00194         Pnew = Pnow + 0.5*(Vtarget - Vnow)/dVdP;
00195         if (Pnew < 0.5* Pnow) {
00196           Pnew = 0.5 * Pnow;
00197         }
00198         if (Pnew > 1.7 * Pnow) {
00199           Pnew = 1.7 * Pnow;
00200         }
00201 
00202       }
00203       m_mix->setPressure(Pnew);
00204     }
00205     throw CanteraError("vcs_MultiPhase::equilibrate_TV",
00206                        "No convergence for V");
00207 
00208   done:;
00209     return iSuccess;
00210   }
00211 
00212 
00213   int vcs_MultiPhaseEquil::equilibrate_HP(doublereal Htarget, 
00214                                           int XY, double Tlow, double Thigh,
00215                                           int estimateEquil,
00216                                           int printLvl, doublereal err, 
00217                                           int maxsteps, int loglevel) {
00218     int maxiter = 100;
00219     int iSuccess;
00220     if (XY != HP && XY != UP) {
00221       throw CanteraError("vcs_MultiPhaseEquil::equilibrate_HP",
00222                          "Wrong XP" + XY);
00223     }
00224     int strt = estimateEquil;
00225   
00226     // Lower bound on T. This will change as we progress in the calculation
00227     if (Tlow <= 0.0) {
00228       Tlow = 0.5 * m_mix->minTemp();
00229     }    
00230       // Upper bound on T. This will change as we progress in the calculation
00231     if (Thigh <= 0.0 || Thigh > 1.0E6) { 
00232       Thigh = 2.0 * m_mix->maxTemp();
00233     }
00234     addLogEntry("problem type","fixed H,P");
00235     addLogEntry("H target",fp2str(Htarget));
00236 
00237     doublereal cpb = 1.0, dT, dTa, dTmax, Tnew;
00238     doublereal Hnow;
00239     doublereal Hlow = Undef;
00240     doublereal Hhigh = Undef;
00241     doublereal Herr, HConvErr;
00242     doublereal Tnow = m_mix->temperature();
00243     int printLvlSub = MAX(printLvl - 1, 0);
00244 
00245     for (int n = 0; n < maxiter; n++) {
00246 
00247 
00248       // start with a loose error tolerance, but tighten it as we get 
00249       // close to the final temperature
00250       beginLogGroup("iteration "+int2str(n));
00251 
00252       try {
00253         Tnow = m_mix->temperature();
00254         iSuccess = equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel); 
00255         strt = 0;
00256         if (XY == UP) {
00257           Hnow = m_mix->IntEnergy();
00258         } else {
00259           Hnow = m_mix->enthalpy();
00260         }
00261         double pmoles[10];
00262         pmoles[0] = m_mix->phaseMoles(0);
00263         double Tmoles = pmoles[0];
00264         double HperMole = Hnow/Tmoles;
00265         if (printLvl > 0) {
00266           plogf("T = %g, Hnow = %g ,Tmoles = %g,  HperMole = %g",
00267                 Tnow, Hnow, Tmoles, HperMole);
00268           plogendl();
00269         }
00270 
00271         // the equilibrium enthalpy monotonically increases with T; 
00272         // if the current value is below the target, then we know the
00273         // current temperature is too low. Set the lower bounds.
00274 
00275 
00276         if (Hnow < Htarget) {
00277           if (Tnow > Tlow) {
00278             Tlow = Tnow;
00279             Hlow = Hnow;
00280           }
00281         }
00282         // the current enthalpy is greater than the target; therefore the
00283         // current temperature is too high. Set the high bounds.
00284         else {
00285           if (Tnow < Thigh) {
00286             Thigh = Tnow;
00287             Hhigh = Hnow;
00288           }
00289         }
00290         if (Hlow != Undef && Hhigh != Undef) {
00291           cpb = (Hhigh - Hlow)/(Thigh - Tlow);
00292           dT = (Htarget - Hnow)/cpb;
00293           dTa = fabs(dT);
00294           dTmax = 0.5*fabs(Thigh - Tlow);
00295           if (dTa > dTmax) dT *= dTmax/dTa;  
00296         }
00297         else {
00298           Tnew = sqrt(Tlow*Thigh);
00299           dT = Tnew - Tnow;
00300           if (dT < -200.) dT = 200;
00301           if (dT > 200.) dT = 200.;
00302         }
00303         double acpb = MAX(fabs(cpb), 1.0E-6);
00304         double denom = MAX(fabs(Htarget), acpb);
00305         Herr = Htarget - Hnow;
00306         HConvErr = fabs((Herr)/denom);
00307         addLogEntry("T",fp2str(m_mix->temperature()));
00308         addLogEntry("H",fp2str(Hnow));
00309         addLogEntry("Herr",fp2str(Herr));
00310         addLogEntry("H rel error",fp2str(HConvErr));
00311         addLogEntry("lower T bound",fp2str(Tlow));
00312         addLogEntry("upper T bound",fp2str(Thigh));
00313         endLogGroup(); // iteration
00314         if (printLvl > 0) {
00315           plogf("   equilibrate_HP: It = %d, Tcurr  = %g Hcurr = %g, Htarget = %g\n",
00316                  n, Tnow, Hnow, Htarget);
00317           plogf("                   H rel error = %g, cp = %g, HConvErr = %g\n", 
00318                  Herr, cpb, HConvErr);
00319         }
00320 
00321         if (HConvErr < err) { // || dTa < 1.0e-4) {
00322           addLogEntry("T iterations",int2str(n));
00323           addLogEntry("Final T",fp2str(m_mix->temperature()));
00324           addLogEntry("H rel error",fp2str(Herr));
00325           if (printLvl > 0) {
00326             plogf("   equilibrate_HP: CONVERGENCE: Hfinal  = %g Tfinal = %g, Its = %d \n",
00327                    Hnow, Tnow, n);
00328             plogf("                   H rel error = %g, cp = %g, HConvErr = %g\n", 
00329                    Herr, cpb, HConvErr);
00330           }
00331           goto done;
00332         }
00333         Tnew = Tnow + dT;
00334         if (Tnew < 0.0) Tnew = 0.5*Tnow;
00335         m_mix->setTemperature(Tnew);
00336 
00337       }
00338       catch (CanteraError err) {
00339         if (!estimateEquil) {
00340           addLogEntry("no convergence",
00341                       "try estimating composition at the start");
00342           strt = -1;
00343         }
00344         else {
00345           Tnew = 0.5*(Tnow + Thigh);
00346           if (fabs(Tnew - Tnow) < 1.0) Tnew = Tnow + 1.0;
00347           m_mix->setTemperature(Tnew);
00348           addLogEntry("no convergence",
00349                       "trying T = "+fp2str(Tnow));
00350         }
00351         endLogGroup();
00352       }
00353 
00354     }
00355     addLogEntry("reached max number of T iterations",int2str(maxiter));
00356     endLogGroup();
00357     throw CanteraError("MultiPhase::equilibrate_HP",
00358                        "No convergence for T");
00359   done:;
00360     return iSuccess;
00361   }
00362 
00363   int vcs_MultiPhaseEquil::equilibrate_SP(doublereal Starget, 
00364                                           double Tlow, double Thigh,
00365                                           int estimateEquil,
00366                                           int printLvl, doublereal err, 
00367                                           int maxsteps, int loglevel) {
00368     int maxiter = 100;
00369     int iSuccess;
00370     int strt = estimateEquil;
00371  
00372     // Lower bound on T. This will change as we progress in the calculation
00373     if (Tlow <= 0.0) {
00374       Tlow = 0.5 * m_mix->minTemp();
00375     }    
00376       // Upper bound on T. This will change as we progress in the calculation
00377     if (Thigh <= 0.0 || Thigh > 1.0E6) { 
00378       Thigh = 2.0 * m_mix->maxTemp();
00379     }
00380     addLogEntry("problem type","fixed S,P");
00381     addLogEntry("S target",fp2str(Starget));
00382 
00383     doublereal cpb = 1.0, dT, dTa, dTmax, Tnew;
00384     doublereal Snow;
00385     doublereal Slow = Undef;
00386     doublereal Shigh = Undef;
00387     doublereal Serr, SConvErr;
00388     doublereal Tnow = m_mix->temperature();
00389     if (Tnow < Tlow) {
00390       Tlow = Tnow;
00391     }
00392     if (Tnow > Thigh) {
00393       Thigh = Tnow;
00394     }
00395     int printLvlSub = MAX(printLvl - 1, 0);
00396 
00397     for (int n = 0; n < maxiter; n++) {
00398 
00399       // start with a loose error tolerance, but tighten it as we get 
00400       // close to the final temperature
00401       beginLogGroup("iteration "+int2str(n));
00402 
00403       try {
00404         Tnow = m_mix->temperature();
00405         iSuccess = equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel); 
00406         strt = 0;
00407         Snow = m_mix->entropy();
00408         double pmoles[10];
00409         pmoles[0] = m_mix->phaseMoles(0);
00410         double Tmoles = pmoles[0];
00411         double SperMole = Snow/Tmoles;
00412         plogf("T = %g, Snow = %g ,Tmoles = %g,  SperMole = %g\n",
00413                Tnow, Snow, Tmoles, SperMole);
00414 
00415 
00416         // the equilibrium entropy monotonically increases with T; 
00417         // if the current value is below the target, then we know the
00418         // current temperature is too low. Set the lower bounds to the
00419         // current condition.
00420         if (Snow < Starget) {
00421           if (Tnow > Tlow) {
00422             Tlow = Tnow;
00423             Slow = Snow;
00424           } else {
00425             if (Slow > Starget) {
00426               if (Snow < Slow) {
00427                 Thigh = Tlow;
00428                 Shigh = Slow;
00429                 Tlow = Tnow;
00430                 Slow = Snow;
00431               }
00432             }
00433           }
00434         }
00435         // the current enthalpy is greater than the target; therefore the
00436         // current temperature is too high. Set the high bounds.
00437         else {
00438           if (Tnow < Thigh) {
00439             Thigh = Tnow;
00440             Shigh = Snow;
00441           }
00442         }
00443         if (Slow != Undef && Shigh != Undef) {
00444           cpb = (Shigh - Slow)/(Thigh - Tlow);
00445           dT = (Starget - Snow)/cpb;
00446           Tnew = Tnow + dT;
00447           dTa = fabs(dT);
00448           dTmax = 0.5*fabs(Thigh - Tlow);
00449           if (Tnew > Thigh || Tnew < Tlow) {
00450             dTmax = 1.5*fabs(Thigh - Tlow);
00451           }
00452           dTmax = MIN(dTmax, 300.);
00453           if (dTa > dTmax) dT *= dTmax/dTa;  
00454         } else {
00455           Tnew = sqrt(Tlow*Thigh);
00456           dT = Tnew - Tnow;
00457         }
00458 
00459         double acpb = MAX(fabs(cpb), 1.0E-6);
00460         double denom = MAX(fabs(Starget), acpb);
00461         Serr = Starget - Snow;
00462         SConvErr = fabs((Serr)/denom);
00463         addLogEntry("T",fp2str(m_mix->temperature()));
00464         addLogEntry("S",fp2str(Snow));
00465         addLogEntry("Serr",fp2str(Serr));
00466         addLogEntry("S rel error",fp2str(SConvErr));
00467         addLogEntry("lower T bound",fp2str(Tlow));
00468         addLogEntry("upper T bound",fp2str(Thigh));
00469         endLogGroup(); // iteration
00470         if (printLvl > 0) {
00471           plogf("   equilibrate_SP: It = %d, Tcurr  = %g Scurr = %g, Starget = %g\n",
00472                  n, Tnow, Snow, Starget);
00473           plogf("                   S rel error = %g, cp = %g, SConvErr = %g\n", 
00474                  Serr, cpb, SConvErr);
00475         }
00476 
00477         if (SConvErr < err) { // || dTa < 1.0e-4) {
00478           addLogEntry("T iterations",int2str(n));
00479           addLogEntry("Final T",fp2str(m_mix->temperature()));
00480           addLogEntry("S rel error",fp2str(Serr));
00481           if (printLvl > 0) {
00482             plogf("   equilibrate_SP: CONVERGENCE: Sfinal  = %g Tfinal = %g, Its = %d \n",
00483                    Snow, Tnow, n);
00484             plogf("                   S rel error = %g, cp = %g, HConvErr = %g\n", 
00485                    Serr, cpb, SConvErr);
00486           }
00487           goto done;
00488         }
00489         Tnew = Tnow + dT;
00490         if (Tnew < 0.0) Tnew = 0.5*Tnow;
00491         m_mix->setTemperature(Tnew);
00492 
00493       }
00494       catch (CanteraError err) {
00495         if (!estimateEquil) {
00496           addLogEntry("no convergence",
00497                       "try estimating composition at the start");
00498           strt = -1;
00499         }
00500         else {
00501           Tnew = 0.5*(Tnow + Thigh);
00502           if (fabs(Tnew - Tnow) < 1.0) Tnew = Tnow + 1.0;
00503           m_mix->setTemperature(Tnew);
00504           addLogEntry("no convergence",
00505                       "trying T = "+fp2str(Tnow));
00506         }
00507         endLogGroup();
00508       }
00509 
00510     }
00511     addLogEntry("reached max number of T iterations",int2str(maxiter));
00512     endLogGroup();
00513     throw CanteraError("MultiPhase::equilibrate_SP",
00514                        "No convergence for T");
00515   done:;
00516     return iSuccess;
00517   }
00518 
00519 
00520   /*
00521    * Equilibrate the solution using the current element abundances
00522    */
00523   int vcs_MultiPhaseEquil::equilibrate(int XY, int estimateEquil, 
00524                                        int printLvl, doublereal err, 
00525                                        int maxsteps, int loglevel) {
00526     int iSuccess;
00527     doublereal xtarget;
00528     if (XY == TP) {
00529       iSuccess = equilibrate_TP(estimateEquil, printLvl, err, maxsteps, loglevel); 
00530     } else if (XY == HP || XY == UP) {
00531       if (XY == HP) {
00532         xtarget = m_mix->enthalpy();
00533       } else {
00534         xtarget = m_mix->IntEnergy();
00535       }
00536        double Tlow  = 0.5 * m_mix->minTemp();
00537        double Thigh = 2.0 * m_mix->maxTemp();
00538        iSuccess = equilibrate_HP(xtarget, XY, Tlow, Thigh, 
00539                                  estimateEquil, printLvl, err, maxsteps, loglevel); 
00540     } else if (XY == SP) {
00541       xtarget = m_mix->entropy();
00542       double Tlow  = 0.5 * m_mix->minTemp();
00543       double Thigh = 2.0 * m_mix->maxTemp();
00544       iSuccess = equilibrate_SP(xtarget, Tlow, Thigh, 
00545                                 estimateEquil, printLvl, err, maxsteps, loglevel); 
00546 
00547     } else if (XY == TV) {
00548       xtarget = m_mix->temperature();
00549       iSuccess = equilibrate_TV(XY, xtarget,
00550                                 estimateEquil, printLvl, err, maxsteps, loglevel); 
00551     } else if (XY == HV) {
00552       xtarget = m_mix->enthalpy();
00553       iSuccess = equilibrate_TV(XY, xtarget,
00554                                 estimateEquil, printLvl, err, maxsteps, loglevel); 
00555     } else if (XY == UV) {
00556       xtarget = m_mix->IntEnergy();
00557       iSuccess = equilibrate_TV(XY, xtarget,
00558                                 estimateEquil, printLvl, err, maxsteps, loglevel); 
00559     } else if (XY == SV) {
00560       xtarget = m_mix->entropy();
00561       iSuccess = equilibrate_TV(XY, xtarget, estimateEquil,
00562                                 printLvl, err, maxsteps, loglevel); 
00563     } else {
00564       throw CanteraError(" vcs_MultiPhaseEquil::equilibrate",
00565                          "Unsupported Option");
00566     }
00567     return iSuccess;
00568   }
00569      
00570   /*
00571    * Equilibrate the solution using the current element abundances
00572    */
00573   int vcs_MultiPhaseEquil::equilibrate_TP(int estimateEquil, 
00574                                           int printLvl, doublereal err, 
00575                                           int maxsteps, int loglevel) {
00576    // Debugging level
00577    
00578     int maxit = maxsteps;;
00579     clockWC tickTock;
00580     int nsp = m_mix->nSpecies();
00581     int nel = m_mix->nElements();
00582     int nph = m_mix->nPhases();
00583     if (m_vprob == 0) {
00584       m_vprob = new VCS_PROB(nsp, nel, nph);
00585     }
00586     m_printLvl = printLvl;
00587     m_vprob->m_printLvl = printLvl;
00588   
00589 
00590    /*    
00591     *     Extract the current state information
00592     *     from the MultiPhase object and
00593     *     Transfer it to VCS_PROB object.
00594     */
00595    int res = vcs_Cantera_update_vprob(m_mix, m_vprob);
00596    if (res != 0) {
00597      plogf("problems\n");
00598    }
00599  
00600 
00601    // Set the estimation technique
00602    if (estimateEquil) {
00603      m_vprob->iest = estimateEquil;
00604    } else {
00605      m_vprob->iest = 0;
00606    }
00607 
00608    // Check obvious bounds on the temperature and pressure
00609    // NOTE, we may want to do more here with the real bounds 
00610    // given by the ThermoPhase objects.
00611    double T = m_mix->temperature();
00612    if (T <= 0.0) {
00613      throw CanteraError("vcs_MultiPhaseEquil::equilibrate",
00614                         "Temperature less than zero on input");
00615    }
00616    double pres = m_mix->pressure();
00617    if (pres <= 0.0) {
00618      throw CanteraError("vcs_MultiPhaseEquil::equilibrate",
00619                         "Pressure less than zero on input");
00620    }
00621    
00622    beginLogGroup("vcs_MultiPhaseEquil::equilibrate_TP", loglevel);
00623    addLogEntry("problem type","fixed T,P");
00624    addLogEntry("Temperature", T);
00625    addLogEntry("Pressure", pres);
00626    
00627 
00628    /*
00629     * Print out the problem specification from the point of
00630     * view of the vprob object.
00631     */
00632    m_vprob->prob_report(m_printLvl);
00633 
00634    /*
00635     * Call the thermo Program
00636     */
00637    int ip1 = m_printLvl;
00638    int ipr = MAX(0, m_printLvl-1);
00639    if (m_printLvl >= 3) {  
00640      ip1 = m_printLvl - 2;
00641    } else {
00642      ip1 = 0;
00643    }
00644    if (!m_vsolvePtr) {
00645      m_vsolvePtr = new VCS_SOLVE();
00646    }
00647    int iSuccess = m_vsolvePtr->vcs(m_vprob, 0, ipr, ip1, maxit);
00648 
00649    /*
00650     * Transfer the information back to the MultiPhase object.
00651     * Note we don't just call setMoles, because some multispecies
00652     * solution phases may be zeroed out, and that would cause a problem
00653     * for that routine. Also, the mole fractions of such zereod out
00654     * phases actually contain information about likely reemergent
00655     * states.
00656     */
00657    m_mix->uploadMoleFractionsFromPhases();
00658    int kGlob = 0;
00659    for (int ip = 0; ip < m_vprob->NPhase; ip++) {
00660      double phaseMole = 0.0;
00661      Cantera::ThermoPhase &tref = m_mix->phase(ip);
00662      int nspPhase = tref.nSpecies();
00663      for (int k = 0; k < nspPhase; k++, kGlob++) {
00664        phaseMole += m_vprob->w[kGlob];
00665      }
00666      //phaseMole *= 1.0E-3;
00667      m_mix->setPhaseMoles(ip, phaseMole);
00668    }
00669   
00670    double te = tickTock.secondsWC();
00671    if (printLvl > 0) {
00672      plogf("\n Results from vcs:\n");
00673      if (iSuccess != 0) {
00674        plogf("\nVCS FAILED TO CONVERGE!\n");
00675      }
00676      plogf("\n");
00677      plogf("Temperature = %g Kelvin\n",  m_vprob->T);
00678      plogf("Pressure    = %g Pa\n", m_vprob->PresPA);
00679      plogf("\n");
00680      plogf("----------------------------------------"
00681             "---------------------\n");
00682      plogf(" Name             Mole_Number");
00683      if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_MKS) {
00684        plogf("(kmol)");
00685      } else {
00686        plogf("(gmol)");
00687      }
00688      plogf("  Mole_Fraction     Chem_Potential");
00689      if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KCALMOL) 
00690        plogf(" (kcal/mol)\n");
00691      else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_UNITLESS) 
00692        plogf(" (Dimensionless)\n");
00693      else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KJMOL) 
00694        plogf(" (kJ/mol)\n");
00695      else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KELVIN) 
00696        plogf(" (Kelvin)\n");
00697      else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_MKS) 
00698        plogf(" (J/kmol)\n");
00699      plogf("--------------------------------------------------"
00700             "-----------\n");
00701      for (int i = 0; i < m_vprob->nspecies; i++) {
00702        plogf("%-12s", m_vprob->SpName[i].c_str());
00703        if (m_vprob->SpeciesUnknownType[i] == VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
00704          plogf("  %15.3e %15.3e  ", 0.0, m_vprob->mf[i]);
00705          plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
00706        } else {
00707        plogf("  %15.3e   %15.3e  ", m_vprob->w[i], m_vprob->mf[i]);
00708        if (m_vprob->w[i] <= 0.0) {
00709          int iph = m_vprob->PhaseID[i];
00710          vcs_VolPhase *VPhase = m_vprob->VPhaseList[iph];
00711          if (VPhase->nSpecies() > 1) {
00712            plogf("     -1.000e+300\n");
00713          } else {
00714            plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
00715          }
00716        } else {
00717          plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
00718        }
00719        }
00720      }
00721      plogf("------------------------------------------"
00722             "-------------------\n"); 
00723      if (printLvl > 2) {
00724        if (m_vsolvePtr->m_timing_print_lvl > 0) {
00725          plogf("Total time = %12.6e seconds\n", te);
00726        }
00727      }
00728    }
00729    if (loglevel > 0) {
00730      endLogGroup();
00731    }
00732    return iSuccess;
00733   }
00734 
00735 
00736 
00737   /**************************************************************************
00738    *
00739    *
00740    */
00741   void vcs_MultiPhaseEquil::reportCSV(const std::string &reportFile) {
00742     int k;
00743     int istart;
00744     int nSpecies;
00745   
00746     double vol = 0.0;
00747     string sName;
00748     int nphase = m_vprob->NPhase;
00749 
00750     FILE * FP = fopen(reportFile.c_str(), "w");
00751     if (!FP) {
00752       plogf("Failure to open file\n");
00753       exit(EXIT_FAILURE);
00754     }
00755     double Temp = m_mix->temperature();
00756     double pres = m_mix->pressure();
00757     double *mf = VCS_DATA_PTR(m_vprob->mf);
00758 #ifdef DEBUG_MODE
00759     double *fe = VCS_DATA_PTR(m_vprob->m_gibbsSpecies);
00760 #endif
00761     std::vector<double> VolPM;
00762     std::vector<double> activity;
00763     std::vector<double> ac;
00764     std::vector<double> mu;
00765     std::vector<double> mu0;
00766     std::vector<double> molalities;
00767 
00768 
00769     vol = 0.0;
00770     for (int iphase = 0; iphase < nphase; iphase++) {
00771       istart =    m_mix->speciesIndex(0, iphase);
00772       Cantera::ThermoPhase &tref = m_mix->phase(iphase);
00773       nSpecies = tref.nSpecies();
00774       VolPM.resize(nSpecies, 0.0);
00775       tref.getPartialMolarVolumes(VCS_DATA_PTR(VolPM));
00776       vcs_VolPhase *volP = m_vprob->VPhaseList[iphase];
00777   
00778       double TMolesPhase = volP->totalMoles();
00779       double VolPhaseVolumes = 0.0;
00780       for (k = 0; k < nSpecies; k++) {
00781         VolPhaseVolumes += VolPM[k] * mf[istart + k];
00782       }
00783       VolPhaseVolumes *= TMolesPhase;
00784       vol += VolPhaseVolumes;
00785     }
00786 
00787     fprintf(FP,"--------------------- VCS_MULTIPHASE_EQUIL FINAL REPORT"
00788             " -----------------------------\n");
00789     fprintf(FP,"Temperature  = %11.5g kelvin\n", Temp);
00790     fprintf(FP,"Pressure     = %11.5g Pascal\n", pres);
00791     fprintf(FP,"Total Volume = %11.5g m**3\n", vol);
00792     fprintf(FP,"Number Basis optimizations = %d\n", m_vprob->m_NumBasisOptimizations);
00793     fprintf(FP,"Number VCS iterations = %d\n", m_vprob->m_Iterations);
00794 
00795     for (int iphase = 0; iphase < nphase; iphase++) {
00796       istart =    m_mix->speciesIndex(0, iphase);
00797       Cantera::ThermoPhase &tref = m_mix->phase(iphase);
00798       Cantera::ThermoPhase *tp = &tref;
00799       string phaseName = tref.name();
00800       vcs_VolPhase *volP = m_vprob->VPhaseList[iphase];
00801       double TMolesPhase = volP->totalMoles();
00802       //AssertTrace(TMolesPhase == m_mix->phaseMoles(iphase));
00803       nSpecies = tref.nSpecies();
00804       activity.resize(nSpecies, 0.0);
00805       ac.resize(nSpecies, 0.0);
00806    
00807       mu0.resize(nSpecies, 0.0);
00808       mu.resize(nSpecies, 0.0);
00809       VolPM.resize(nSpecies, 0.0);
00810       molalities.resize(nSpecies, 0.0);
00811  
00812       int actConvention = tp->activityConvention();
00813       tp->getActivities(VCS_DATA_PTR(activity));
00814       tp->getActivityCoefficients(VCS_DATA_PTR(ac));
00815       tp->getStandardChemPotentials(VCS_DATA_PTR(mu0));
00816   
00817       tp->getPartialMolarVolumes(VCS_DATA_PTR(VolPM));
00818       tp->getChemPotentials(VCS_DATA_PTR(mu));
00819       double VolPhaseVolumes = 0.0;
00820       for (k = 0; k < nSpecies; k++) {
00821         VolPhaseVolumes += VolPM[k] * mf[istart + k];
00822       }
00823       VolPhaseVolumes *= TMolesPhase;
00824       vol += VolPhaseVolumes;
00825 
00826  
00827       if (actConvention == 1) {
00828 #ifdef WITH_ELECTROLYTES
00829         MolalityVPSSTP *mTP = static_cast<MolalityVPSSTP *>(tp);
00830         mTP->getMolalities(VCS_DATA_PTR(molalities));
00831 #endif
00832         tp->getChemPotentials(VCS_DATA_PTR(mu));
00833   
00834         if (iphase == 0) {
00835           fprintf(FP,"        Name,      Phase,  PhaseMoles,  Mole_Fract, "
00836                   "Molalities,  ActCoeff,   Activity,"
00837                   "ChemPot_SS0,   ChemPot,   mole_num,       PMVol, Phase_Volume\n");
00838      
00839           fprintf(FP,"            ,           ,      (kmol),            , "
00840                   "          ,          ,           ,"
00841                   "   (J/kmol),  (J/kmol),     (kmol), (m**3/kmol),     (m**3)\n"); 
00842         }
00843         for (k = 0; k < nSpecies; k++) {
00844           sName = tp->speciesName(k);
00845           fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e,"
00846                   "%11.3e, %11.3e, %11.3e, %11.3e, %11.3e\n", 
00847                   sName.c_str(), 
00848                   phaseName.c_str(), TMolesPhase,
00849                   mf[istart + k], molalities[k], ac[k], activity[k],
00850                   mu0[k]*1.0E-6, mu[k]*1.0E-6,
00851                   mf[istart + k] * TMolesPhase,
00852                   VolPM[k],  VolPhaseVolumes );
00853         }
00854  
00855       } else {
00856         if (iphase == 0) {
00857           fprintf(FP,"        Name,       Phase,  PhaseMoles,  Mole_Fract,  "
00858                   "Molalities,   ActCoeff,    Activity,"
00859                   "  ChemPotSS0,     ChemPot,   mole_num,       PMVol, Phase_Volume\n");
00860     
00861           fprintf(FP,"            ,            ,      (kmol),            ,  "
00862                   "          ,           ,            ,"
00863                   "    (J/kmol),    (J/kmol),     (kmol), (m**3/kmol),       (m**3)\n");
00864         }
00865         for (k = 0; k < nSpecies; k++) {
00866           molalities[k] = 0.0;
00867         }
00868         for (k = 0; k < nSpecies; k++) {
00869           sName = tp->speciesName(k);
00870           fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e, "
00871                   "%11.3e, %11.3e,% 11.3e, %11.3e, %11.3e\n",
00872                   sName.c_str(),
00873                   phaseName.c_str(), TMolesPhase,
00874                   mf[istart + k],  molalities[k], ac[k], 
00875                   activity[k], mu0[k]*1.0E-6, mu[k]*1.0E-6, 
00876                   mf[istart + k] * TMolesPhase,
00877                   VolPM[k],  VolPhaseVolumes );       
00878         }
00879       }
00880 
00881 #ifdef DEBUG_MODE
00882       /*
00883        * Check consistency: These should be equal
00884        */
00885       tp->getChemPotentials(fe+istart);
00886       for (k = 0; k < nSpecies; k++) {
00887         if (!vcs_doubleEqual(fe[istart+k], mu[k])) {
00888           fprintf(FP,"ERROR: incompatibility!\n");
00889           fclose(FP);
00890           plogf("ERROR: incompatibility!\n");
00891           exit(EXIT_FAILURE);
00892         }
00893       }
00894 #endif
00895 
00896     }
00897     fclose(FP);
00898   }
00899 
00900  
00901   static void print_char(const char letter, const int num) {
00902     for (int i = 0; i < num; i++) plogf("%c", letter);
00903   }
00904   
00905   /*
00906    * 
00907    *
00908    * HKM -> Work on transfering the current value of the voltages into the 
00909    *        equilibrium problem.
00910    */
00911   int  vcs_Cantera_to_vprob(Cantera::MultiPhase *mphase,
00912                             VCSnonideal::VCS_PROB *vprob) {
00913     int k;
00914     VCS_SPECIES_THERMO *ts_ptr = 0;
00915 
00916     /*
00917      * Calculate the total number of species and phases in the problem
00918      */
00919     int totNumPhases = mphase->nPhases();
00920     int totNumSpecies = mphase->nSpecies();
00921 
00922     // Problem type has yet to be worked out.
00923     vprob->prob_type = 0;
00924     vprob->nspecies  = totNumSpecies;
00925     vprob->ne        = 0;
00926     vprob->NPhase    = totNumPhases;
00927     vprob->m_VCS_UnitsFormat      = VCS_UNITS_MKS;
00928     // Set the initial estimate to a machine generated estimate for now
00929     // We will work out the details later.
00930     vprob->iest      = -1;
00931     vprob->T         = mphase->temperature();
00932     vprob->PresPA    = mphase->pressure();
00933     vprob->Vol       = mphase->volume();
00934     vprob->Title     = "MultiPhase Object";
00935 
00936     Cantera::ThermoPhase *tPhase = 0;
00937 
00938     int iSurPhase = -1;
00939     bool gasPhase;
00940     int printLvl = vprob->m_printLvl;
00941 
00942     /*
00943      * Loop over the phases, transfering pertinent information
00944      */
00945     int kT = 0;
00946     for (int iphase = 0; iphase < totNumPhases; iphase++) {
00947 
00948       /*
00949        * Get the thermophase object - assume volume phase
00950        */
00951       iSurPhase = -1;
00952       tPhase = &(mphase->phase(iphase));
00953       int nelem = tPhase->nElements();
00954     
00955       /*
00956        * Query Cantera for the equation of state type of the
00957        * current phase.
00958        */
00959       int eos = tPhase->eosType();
00960       if (eos == cIdealGas) gasPhase = true;
00961       else                  gasPhase = false;
00962     
00963       /*
00964        *    Find out the number of species in the phase
00965        */
00966       int nSpPhase = tPhase->nSpecies();
00967       /*
00968        *    Find out the name of the phase
00969        */
00970       string phaseName = tPhase->name();
00971          
00972       /*
00973        *    Call the basic vcs_VolPhase creation routine.
00974        *    Properties set here: 
00975        *       ->PhaseNum = phase number in the thermo problem
00976        *       ->GasPhase = Boolean indicating whether it is a gas phase
00977        *       ->NumSpecies = number of species in the phase
00978        *       ->TMolesInert = Inerts in the phase = 0.0 for cantera
00979        *       ->PhaseName  = Name of the phase
00980        */
00981 
00982       vcs_VolPhase *VolPhase = vprob->VPhaseList[iphase];
00983       VolPhase->resize(iphase, nSpPhase, nelem, phaseName.c_str(), 0.0);
00984       VolPhase->m_gasPhase = gasPhase;
00985       /*
00986        * Tell the vcs_VolPhase pointer about cantera
00987        */
00988       VolPhase->p_VCS_UnitsFormat = vprob->m_VCS_UnitsFormat;
00989       VolPhase->setPtrThermoPhase(tPhase);
00990       VolPhase->setTotalMoles(0.0);
00991       /*
00992        * Set the electric potential of the volume phase from the
00993        * ThermoPhase object's value.
00994        */
00995       VolPhase->setElectricPotential(tPhase->electricPotential());
00996       /*
00997        * Query the ThermoPhase object to find out what convention
00998        * it uses for the specification of activity and Standard State.
00999        */
01000       VolPhase->p_activityConvention = tPhase->activityConvention();
01001       /*
01002        * Assign the value of eqn of state 
01003        *  -> Handle conflicts here.
01004        */
01005       switch (eos) {
01006       case cIdealGas:
01007         VolPhase->m_eqnState = VCS_EOS_IDEAL_GAS;
01008         break;
01009       case cIncompressible:
01010         VolPhase->m_eqnState = VCS_EOS_CONSTANT;
01011         break;
01012       case cSurf:
01013         plogf("cSurf not handled yet\n");
01014         exit(EXIT_FAILURE);
01015       case cStoichSubstance:
01016         VolPhase->m_eqnState = VCS_EOS_STOICH_SUB;
01017         break;
01018       case  cPureFluid:
01019         if (printLvl > 1) {
01020           plogf("cPureFluid not recognized yet by VCSnonideal\n");
01021         }
01022         break;
01023       case cEdge:
01024         plogf("cEdge not handled yet\n");
01025         exit(EXIT_FAILURE);
01026       case cIdealSolidSolnPhase0:
01027       case cIdealSolidSolnPhase1:
01028       case cIdealSolidSolnPhase2:
01029         VolPhase->m_eqnState = VCS_EOS_IDEAL_SOLN;
01030         break;
01031       default:
01032         if (printLvl > 1) {
01033           plogf("Unknown Cantera EOS to VCSnonideal: %d\n", eos);
01034         }
01035         VolPhase->m_eqnState = VCS_EOS_UNK_CANTERA;
01036         if (!VolPhase->usingCanteraCalls()) {
01037           plogf("vcs functions asked for, but unimplemented\n");
01038           exit(EXIT_FAILURE);
01039         }
01040         break;
01041       }
01042   
01043       /*
01044        * Transfer all of the element information from the
01045        * ThermoPhase object to the vcs_VolPhase object.
01046        * Also decide whether we need a new charge neutrality
01047        * element in the phase to enforce a charge neutrality
01048        * constraint.
01049        *  We also decide whether this is a single species phase
01050        *  with the voltage being the independent variable setting
01051        *  the chemical potential of the electrons.
01052        */
01053       VolPhase->transferElementsFM(tPhase);
01054 
01055       /*
01056        * Combine the element information in the vcs_VolPhase
01057        * object into the vprob object.
01058        */
01059       vprob->addPhaseElements(VolPhase);
01060 
01061       VolPhase->setState_TP(vprob->T, vprob->PresPA);
01062       vector<double> muPhase(tPhase->nSpecies(),0.0);
01063       tPhase->getChemPotentials(&muPhase[0]);
01064       double tMoles = 0.0;
01065       /*
01066        *    Loop through each species in the current phase
01067        */ 
01068       for (k = 0; k < nSpPhase; k++) {
01069         /*
01070          * Obtain the molecular weight of the species from the
01071          * ThermoPhase object
01072          */
01073         vprob->WtSpecies[kT] = tPhase->molecularWeight(k);
01074 
01075         /*
01076          * Obtain the charges of the species from the
01077          * ThermoPhase object
01078          */
01079         vprob->Charge[kT] = tPhase->charge(k);
01080 
01081         /*
01082          *   Set the phaseid of the species
01083          */
01084         vprob->PhaseID[kT] = iphase;
01085 
01086         /*
01087          *  Transfer the Species name
01088          */
01089         string stmp = mphase->speciesName(kT);
01090         vprob->SpName[kT] = stmp;
01091 
01092         /*
01093          *   Set the initial estimate of the number of kmoles of the species
01094          *   and the mole fraction vector. translate from
01095          *   kmol to gmol.
01096          */
01097         vprob->w[kT] = mphase->speciesMoles(kT);
01098         tMoles += vprob->w[kT];
01099         vprob->mf[kT] = mphase->moleFraction(kT);
01100 
01101         /*
01102          * transfer chemical potential vector
01103          */
01104         vprob->m_gibbsSpecies[kT] = muPhase[k];
01105         /*
01106          * Transfer the type of unknown
01107          */
01108         vprob->SpeciesUnknownType[kT] = VolPhase->speciesUnknownType(k);
01109         /*
01110          * Transfer the species information from the 
01111          * volPhase structure to the VPROB structure
01112          * This includes:
01113          *      FormulaMatrix[][]
01114          *      VolPhase->IndSpecies[]
01115          */
01116         vprob->addOnePhaseSpecies(VolPhase, k, kT);
01117 
01118         /*
01119          * Get a pointer to the thermo object
01120          */
01121         ts_ptr = vprob->SpeciesThermo[kT]; 
01122         /*
01123          * Fill in the vcs_SpeciesProperty structure
01124          */
01125         vcs_SpeciesProperties *sProp = VolPhase->speciesProperty(k);
01126         sProp->NumElements = vprob->ne;
01127         sProp->SpName = vprob->SpName[kT];
01128         sProp->SpeciesThermo = ts_ptr;
01129         sProp->WtSpecies = tPhase->molecularWeight(k);
01130         sProp->FormulaMatrixCol.resize(vprob->ne, 0.0);
01131         for (int e = 0; e < vprob->ne; e++) {
01132           sProp->FormulaMatrixCol[e] = vprob->FormulaMatrix[e][kT];
01133         }
01134         sProp->Charge = tPhase->charge(k);
01135         sProp->SurfaceSpecies = false;
01136         sProp->VolPM = 0.0;
01137           
01138         /*
01139          *  Transfer the thermo specification of the species
01140          *              vprob->SpeciesThermo[]
01141          */
01142         ts_ptr->UseCanteraCalls = VolPhase->usingCanteraCalls();
01143         ts_ptr->m_VCS_UnitsFormat = VolPhase->p_VCS_UnitsFormat;
01144         /*
01145          * Add lookback connectivity into the thermo object first
01146          */
01147         ts_ptr->IndexPhase = iphase;
01148         ts_ptr->IndexSpeciesPhase = k;
01149         ts_ptr->OwningPhase = VolPhase;
01150         /*
01151          *   get a reference to the Cantera species thermo.
01152          */
01153         SpeciesThermo &sp = tPhase->speciesThermo();
01154 
01155         int spType;
01156         double c[150];
01157         double minTemp, maxTemp, refPressure;
01158         sp.reportParams(k, spType, c, minTemp, maxTemp, refPressure);
01159 
01160         if (spType == SIMPLE) {
01161           ts_ptr->SS0_Model  = VCS_SS0_CONSTANT;
01162           ts_ptr->SS0_T0  = c[0];
01163           ts_ptr->SS0_H0  = c[1];
01164           ts_ptr->SS0_S0  = c[2];
01165           ts_ptr->SS0_Cp0 = c[3];
01166           if (gasPhase) {
01167             ts_ptr->SSStar_Model = VCS_SSSTAR_IDEAL_GAS;
01168             ts_ptr->SSStar_Vol_Model  = VCS_SSVOL_IDEALGAS;            
01169           } else {
01170             ts_ptr->SSStar_Model = VCS_SSSTAR_CONSTANT;
01171             ts_ptr->SSStar_Vol_Model  = VCS_SSVOL_CONSTANT;
01172           }
01173           ts_ptr->Activity_Coeff_Model  = VCS_AC_CONSTANT;
01174           ts_ptr->Activity_Coeff_Params = NULL;
01175         } else {
01176           if (vprob->m_printLvl > 2) {
01177             plogf("vcs_Cantera_convert: Species Type %d not known \n",
01178                   spType);
01179           }
01180           ts_ptr->SS0_Model = VCS_SS0_NOTHANDLED;
01181           ts_ptr->SSStar_Model = VCS_SSSTAR_NOTHANDLED;
01182           if (!(ts_ptr->UseCanteraCalls )) {
01183             plogf("Cantera calls not being used -> exiting\n");
01184             exit(EXIT_FAILURE);
01185           }
01186         }
01187             
01188         /*
01189          *  Transfer the Volume Information -> NEEDS WORK
01190          */
01191         if (gasPhase) {
01192           ts_ptr->SSStar_Vol_Model = VCS_SSVOL_IDEALGAS;
01193           ts_ptr->SSStar_Vol_Params = NULL;
01194           ts_ptr->SSStar_Vol0 = 82.05 * 273.15 / 1.0;
01195 
01196         } else {
01197           std::vector<double> phaseTermCoeff(nSpPhase, 0.0);
01198           int nCoeff;
01199           tPhase->getParameters(nCoeff, VCS_DATA_PTR(phaseTermCoeff));
01200           ts_ptr->SSStar_Vol_Model = VCS_SSVOL_CONSTANT;
01201           ts_ptr->SSStar_Vol0 = phaseTermCoeff[k];
01202         }
01203         kT++;
01204       }
01205 
01206       /*
01207        * Now go back through the species in the phase and assign
01208        * a valid mole fraction to all phases, even if the initial
01209        * estimate of the total number of moles is zero.
01210        */
01211       if (tMoles > 0.0) {
01212         for (k = 0; k < nSpPhase; k++) {
01213           int kTa = VolPhase->spGlobalIndexVCS(k);
01214           vprob->mf[kTa] = vprob->w[kTa] / tMoles;
01215         }
01216       } else {
01217         /*
01218          * Perhaps, we could do a more sophisticated treatment below.
01219          * But, will start with this.
01220          */
01221         for (k = 0; k < nSpPhase; k++) {
01222           int kTa = VolPhase->spGlobalIndexVCS(k);
01223           vprob->mf[kTa]= 1.0 / (double) nSpPhase;
01224         }
01225       }
01226 
01227       VolPhase->setMolesFromVCS(VCS_STATECALC_OLD, VCS_DATA_PTR(vprob->w));
01228       /*
01229        * Now, calculate a sample naught gibbs free energy calculation
01230        * at the specified temperature.
01231        */
01232       double R = vcsUtil_gasConstant(vprob->m_VCS_UnitsFormat);
01233       for (k = 0; k < nSpPhase; k++) {
01234         vcs_SpeciesProperties *sProp = VolPhase->speciesProperty(k);
01235         ts_ptr = sProp->SpeciesThermo;
01236         ts_ptr->SS0_feSave = VolPhase->G0_calc_one(k)/ R;
01237         ts_ptr->SS0_TSave = vprob->T;
01238       }
01239      
01240     }
01241 
01242     /*
01243      *  Transfer initial element abundances to the vprob object.
01244      *  We have to find the mapping index from one to the other
01245      *
01246      */
01247     vprob->gai.resize(vprob->ne, 0.0);
01248     vprob->set_gai();
01249 
01250     /*
01251      *          Printout the species information: PhaseID's and mole nums
01252      */
01253     if (vprob->m_printLvl > 1) {
01254       plogf("\n"); print_char('=', 80); plogf("\n");
01255       print_char('=', 16);
01256       plogf(" Cantera_to_vprob: START OF PROBLEM STATEMENT ");
01257       print_char('=', 20); plogf("\n");
01258       print_char('=', 80); plogf("\n");
01259       plogf("             Phase IDs of species\n");
01260       plogf("            species     phaseID        phaseName   ");
01261       plogf(" Initial_Estimated_kMols\n");
01262       for (int i = 0; i < vprob->nspecies; i++) {
01263         int iphase = vprob->PhaseID[i];
01264 
01265         vcs_VolPhase *VolPhase = vprob->VPhaseList[iphase];
01266         plogf("%16s      %5d   %16s", vprob->SpName[i].c_str(), iphase,
01267                VolPhase->PhaseName.c_str());
01268         plogf("             %-10.5g\n",  vprob->w[i]);
01269       }
01270       
01271       /*
01272        *   Printout of the Phase structure information
01273        */
01274       plogf("\n"); print_char('-', 80); plogf("\n");
01275       plogf("             Information about phases\n");
01276       plogf("  PhaseName    PhaseNum SingSpec GasPhase EqnState NumSpec");
01277       plogf("  TMolesInert       Tmoles(kmol)\n");
01278    
01279       for (int iphase = 0; iphase < vprob->NPhase; iphase++) {
01280         vcs_VolPhase *VolPhase = vprob->VPhaseList[iphase];
01281         std::string sEOS = string16_EOSType(VolPhase->m_eqnState);
01282         plogf("%16s %5d %5d %8d %16s %8d %16e ", VolPhase->PhaseName.c_str(),
01283                VolPhase->VP_ID,       VolPhase->m_singleSpecies,
01284                VolPhase->m_gasPhase,    sEOS.c_str(),
01285                VolPhase->nSpecies(), VolPhase->totalMolesInert() );
01286         plogf("%16e\n",  VolPhase->totalMoles());
01287       }
01288    
01289       plogf("\n"); print_char('=', 80); plogf("\n");
01290       print_char('=', 16); 
01291       plogf(" Cantera_to_vprob: END OF PROBLEM STATEMENT ");
01292       print_char('=', 20); plogf("\n");
01293       print_char('=', 80); plogf("\n\n");
01294     }
01295  
01296     return VCS_SUCCESS;
01297   }
01298 
01299   // Transfer the current state of mphase into the VCS_PROB object
01300   /*
01301    * The basic problem has already been set up.
01302    */
01303   int vcs_Cantera_update_vprob(Cantera::MultiPhase *mphase, 
01304                                VCSnonideal::VCS_PROB *vprob) {
01305     int totNumPhases = mphase->nPhases();
01306     int kT = 0;
01307     std::vector<double> tmpMoles;
01308     // Problem type has yet to be worked out.
01309     vprob->prob_type = 0;
01310     // Whether we have an estimate or not gets overwritten on
01311     // the call to the equilibrium solver.
01312     vprob->iest      = -1;
01313     vprob->T         = mphase->temperature();
01314     vprob->PresPA    = mphase->pressure();
01315     vprob->Vol       = mphase->volume();
01316     Cantera::ThermoPhase *tPhase = 0;
01317 
01318     for (int iphase = 0; iphase < totNumPhases; iphase++) {
01319       tPhase = &(mphase->phase(iphase));
01320       vcs_VolPhase *volPhase = vprob->VPhaseList[iphase];
01321       /*
01322        * Set the electric potential of the volume phase from the
01323        * ThermoPhase object's value.
01324        */
01325       volPhase->setElectricPotential(tPhase->electricPotential());
01326 
01327       volPhase->setState_TP(vprob->T, vprob->PresPA);
01328       vector<double> muPhase(tPhase->nSpecies(),0.0);
01329       tPhase->getChemPotentials(&muPhase[0]);
01330       /*
01331        *    Loop through each species in the current phase
01332        */
01333       int nSpPhase = tPhase->nSpecies();
01334       // volPhase->TMoles = 0.0;
01335       tmpMoles.resize(nSpPhase);
01336       for (int k = 0; k < nSpPhase; k++) {
01337         tmpMoles[k] = mphase->speciesMoles(kT);
01338         vprob->w[kT] = mphase->speciesMoles(kT);
01339         vprob->mf[kT] = mphase->moleFraction(kT);
01340 
01341         /*
01342          * transfer chemical potential vector
01343          */
01344         vprob->m_gibbsSpecies[kT] = muPhase[k];
01345 
01346         kT++;
01347       }
01348       if (volPhase->phiVarIndex() >= 0) {
01349         int kphi = volPhase->phiVarIndex();
01350         int kglob = volPhase->spGlobalIndexVCS(kphi);
01351         vprob->w[kglob] = tPhase->electricPotential();
01352       }
01353       volPhase->setMolesFromVCS(VCS_STATECALC_OLD, VCS_DATA_PTR(vprob->w));
01354       if ((nSpPhase == 1) && (volPhase->phiVarIndex() == 0)) {
01355         volPhase->setExistence(VCS_PHASE_EXIST_ALWAYS);
01356       } else if (volPhase->totalMoles() > 0.0) {
01357         volPhase->setExistence(VCS_PHASE_EXIST_YES);
01358       } else {
01359         volPhase->setExistence(VCS_PHASE_EXIST_NO);
01360       }
01361    
01362     }
01363     /*
01364      *  Transfer initial element abundances to the vprob object.
01365      *  Put them in the front of the object. There may be
01366      *  more constraints than there are elements. But, we 
01367      *  know the element abundances are in the front of the
01368      *  vector.
01369      */
01370     vprob->set_gai();
01371 
01372     /*
01373      *          Printout the species information: PhaseID's and mole nums
01374      */
01375     if (vprob->m_printLvl > 1) {
01376       plogf("\n"); print_char('=', 80); plogf("\n");
01377       print_char('=', 20);
01378       plogf(" Cantera_to_vprob: START OF PROBLEM STATEMENT ");
01379       print_char('=', 20); plogf("\n");
01380       print_char('=', 80); plogf("\n\n");
01381       plogf("             Phase IDs of species\n");
01382       plogf("            species     phaseID        phaseName   ");
01383       plogf(" Initial_Estimated_kMols\n");
01384       for (int i = 0; i < vprob->nspecies; i++) {
01385         int iphase = vprob->PhaseID[i];
01386 
01387         vcs_VolPhase *VolPhase = vprob->VPhaseList[iphase];
01388         plogf("%16s      %5d   %16s", vprob->SpName[i].c_str(), iphase,
01389                VolPhase->PhaseName.c_str());
01390         plogf("             %-10.5g\n",  vprob->w[i]);
01391       }
01392       
01393       /*
01394        *   Printout of the Phase structure information
01395        */
01396       plogf("\n"); print_char('-', 80); plogf("\n");
01397       plogf("             Information about phases\n");
01398       plogf("  PhaseName    PhaseNum SingSpec GasPhase EqnState NumSpec");
01399       plogf("  TMolesInert       Tmoles(kmol)\n");
01400    
01401       for (int iphase = 0; iphase < vprob->NPhase; iphase++) {
01402         vcs_VolPhase *VolPhase = vprob->VPhaseList[iphase];
01403         std::string sEOS = string16_EOSType(VolPhase->m_eqnState);
01404         plogf("%16s %5d %5d %8d %16s %8d %16e ", VolPhase->PhaseName.c_str(),
01405                VolPhase->VP_ID,       VolPhase->m_singleSpecies,
01406                VolPhase->m_gasPhase,    sEOS.c_str(),
01407                VolPhase->nSpecies(), VolPhase->totalMolesInert() );
01408         plogf("%16e\n",  VolPhase->totalMoles() ); 
01409       }
01410    
01411       plogf("\n"); print_char('=', 80); plogf("\n");
01412       print_char('=', 20); 
01413       plogf(" Cantera_to_vprob: END OF PROBLEM STATEMENT ");
01414       print_char('=', 20); plogf("\n");
01415       print_char('=', 80); plogf("\n\n");
01416     }
01417  
01418     return VCS_SUCCESS;
01419   }
01420 
01421   // This routine hasn't been checked yet
01422   void vcs_MultiPhaseEquil::getStoichVector(index_t rxn, Cantera::vector_fp& nu) {
01423     int nsp = m_vsolvePtr->m_numSpeciesTot;
01424     nu.resize(nsp, 0.0);
01425     for (int i = 0; i < nsp; i++) {
01426       nu[i] = 0.0;
01427     }
01428     int nc = numComponents();
01429     // scMatrix [nrxn][ncomp]
01430     const DoubleStarStar &scMatrix = m_vsolvePtr->m_stoichCoeffRxnMatrix;
01431     const  std::vector<int> indSpecies = m_vsolvePtr->m_speciesMapIndex;
01432     if ((int) rxn > nsp - nc) return;
01433     int j = indSpecies[rxn + nc];
01434     nu[j] = 1.0;
01435     for (int kc = 0; kc < nc; kc++) {
01436       j = indSpecies[kc];
01437       nu[j] = scMatrix[rxn][kc];
01438     }
01439     
01440   }
01441   
01442   int vcs_MultiPhaseEquil::numComponents() const {
01443     int nc = -1;
01444     if (m_vsolvePtr) {
01445       nc =  m_vsolvePtr->m_numComponents;
01446     }
01447     return nc;
01448   }
01449 
01450   int vcs_MultiPhaseEquil::numElemConstraints() const {
01451     int nec = -1;
01452     if (m_vsolvePtr) {
01453       nec =  m_vsolvePtr->m_numElemConstraints;
01454     }
01455     return nec;
01456   }
01457  
01458 
01459   int vcs_MultiPhaseEquil::component(int m) const {
01460     int nc = numComponents();
01461     if (m < nc) return m_vsolvePtr->m_speciesMapIndex[m]; 
01462     else return -1;
01463   }
01464 
01465 }
Generated by  doxygen 1.6.3