コード例 #1
0
/*!
 *   This is done by running
 *   each reaction as far forward or backward as possible, subject
 *   to the constraint that all mole numbers remain
 *   non-negative. Reactions for which \f$ \Delta \mu^0 \f$ are
 *   positive are run in reverse, and ones for which it is negative
 *   are run in the forward direction. The end result is equivalent
 *   to solving the linear programming problem of minimizing the
 *   linear Gibbs function subject to the element and
 *   non-negativity constraints.
 */
int VCS_SOLVE::vcs_setMolesLinProg() {
  int ik, irxn;
  double test = -1.0E-10;

#ifdef DEBUG_MODE
    std::string pprefix(" --- seMolesLinProg ");
    if (m_debug_print_lvl >= 2) {
      plogf("   --- call setInitialMoles\n"); 
    }
#endif


  // m_mu are standard state chemical potentials
  //  Boolean on the end specifies standard chem potentials
  // m_mix->getValidChemPotentials(not_mu, DATA_PTR(m_mu), true);
  // -> This is already done coming into the routine.
  double dg_rt;

  int idir;
  double nu;
  double delta_xi, dxi_min = 1.0e10;
  bool redo = true;
  int jcomp;
  int retn;
  int iter = 0;
  bool abundancesOK = true;
  int usedZeroedSpecies;

  std::vector<double> sm(m_numElemConstraints*m_numElemConstraints, 0.0);
  std::vector<double> ss(m_numElemConstraints, 0.0);
  std::vector<double> sa(m_numElemConstraints, 0.0);
  std::vector<double> wx(m_numElemConstraints, 0.0);
  std::vector<double> aw(m_numSpeciesTot, 0.0);

  for (ik = 0; ik <  m_numSpeciesTot; ik++) {
    if (m_speciesUnknownType[ik] !=  VCS_SPECIES_INTERFACIALVOLTAGE) {
      m_molNumSpecies_old[ik] = MAX(0.0, m_molNumSpecies_old[ik]);
    }
  }

#ifdef DEBUG_MODE
  if (m_debug_print_lvl >= 2) {
    printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
  }
#endif
  
  while (redo) {
 
    if (!vcs_elabcheck(0)) {
#ifdef DEBUG_MODE
      if (m_debug_print_lvl >= 2) {
	plogf("%s Mole numbers failing element abundances\n", pprefix.c_str());  
	plogf("%sCall vcs_elcorr to attempt fix\n",          pprefix.c_str());
      }
#endif
      retn = vcs_elcorr(VCS_DATA_PTR(sm), VCS_DATA_PTR(wx));
      if (retn >= 2) {
	abundancesOK = false;
      } else {
	abundancesOK = true;
      }
    } else {
      abundancesOK = true;
    }
    /*
     *  Now find the optimized basis that spans the stoichiometric
     *  coefficient matrix, based on the current composition, m_molNumSpecies_old[]
     *  We also calculate sc[][], the reaction matrix.
     */
    retn = vcs_basopt(FALSE, VCS_DATA_PTR(aw), VCS_DATA_PTR(sa),
			  VCS_DATA_PTR(sm), VCS_DATA_PTR(ss), 
			  test, &usedZeroedSpecies);
    if (retn != VCS_SUCCESS) return retn;

#ifdef DEBUG_MODE
    if (m_debug_print_lvl >= 2) {
      plogf("iteration %d\n", iter);  
    }
#endif
    redo = false;
    iter++;
    if (iter > 15) break;

    // loop over all reactions
    for (irxn = 0; irxn < m_numRxnTot; irxn++) {
	   
      // dg_rt is the Delta_G / RT value for the reaction
      ik = m_numComponents + irxn;
      dg_rt = m_SSfeSpecies[ik];
      dxi_min = 1.0e10;
      const double *sc_irxn = m_stoichCoeffRxnMatrix[irxn];
      for (jcomp = 0; jcomp < m_numElemConstraints; jcomp++) {
	dg_rt += m_SSfeSpecies[jcomp] * sc_irxn[jcomp];
      }
      // fwd or rev direction. 
      //  idir > 0 implies increasing the current species
      //  idir < 0  implies decreasing the current species
      idir = (dg_rt < 0.0 ? 1 : -1);
      if (idir < 0) {
	dxi_min = m_molNumSpecies_old[ik];
      }
	    
      for (jcomp = 0; jcomp < m_numComponents; jcomp++) {
	nu = sc_irxn[jcomp];
	      
	// set max change in progress variable by
	// non-negativity requirement
	if (nu*idir < 0) {
	  delta_xi = fabs(m_molNumSpecies_old[jcomp]/nu);
	  // if a component has nearly zero moles, redo
	  // with a new set of components
	  if (!redo) {
	    if (delta_xi < 1.0e-10 && (m_molNumSpecies_old[ik] >= 1.0E-10)) {
#ifdef DEBUG_MODE
	      if (m_debug_print_lvl >= 2) {
		plogf("   --- Component too small: %s\n", m_speciesName[jcomp].c_str()); 
	      }
#endif
	      redo = true;
	    }
	  }
	  if (delta_xi < dxi_min) dxi_min = delta_xi;
	}
      }
	    
      // step the composition by dxi_min, check against zero, since
      // we are zeroing components and species on every step.
      // Redo the iteration, if a component went from positive to zero on this step.
      double dsLocal = idir*dxi_min;
      m_molNumSpecies_old[ik] += dsLocal;
      m_molNumSpecies_old[ik] = MAX(0.0,  m_molNumSpecies_old[ik]);
      for (jcomp = 0; jcomp < m_numComponents; jcomp++) {
	bool full = false;
	if (m_molNumSpecies_old[jcomp] > 1.0E-15) {
	  full = true;
	}
	m_molNumSpecies_old[jcomp] += sc_irxn[jcomp] * dsLocal;
	m_molNumSpecies_old[jcomp] = MAX(0.0, m_molNumSpecies_old[jcomp]);
	if (full) {
	  if (m_molNumSpecies_old[jcomp] < 1.0E-60) {
	    redo = true;
	  }
	}
      }
    }

    // set the moles of the phase objects to match
    //  updateMixMoles();
    // Update the phase objects with the contents of the m_molNumSpecies_old vector
    // vcs_updateVP(0);
#ifdef DEBUG_MODE
    if (m_debug_print_lvl >= 2) {
      printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
    }
#endif
  }

#ifdef DEBUG_MODE
  if (m_debug_print_lvl == 1) {
    printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
    plogf("   --- setInitialMoles end\n"); 
  }
#endif
  retn = 0;
  if (!abundancesOK) {
    retn = -1;
  } else if (iter > 15) {
    retn = 1;
  }
  return retn;
}
コード例 #2
0
ファイル: vcs_elem.cpp プロジェクト: anujg1991/cantera
  int VCS_SOLVE::vcs_elcorr(double aa[], double x[])
   
    /**************************************************************************
     *
     * vcs_elcorr:
     *
     * This subroutine corrects for element abundances. At the end of the 
     * surbroutine, the total moles in all phases are recalculated again,
     * because we have changed the number of moles in this routine.
     *
     * Input
     *  -> temporary work vectors:
     *     aa[ne*ne]
     *     x[ne]
     *
     * Return Values:
     *      0 = Nothing of significance happened,   
     *          Element abundances were and still are good.
     *      1 = The solution changed significantly; 
     *          The element abundances are now good.
     *      2 = The solution changed significantly,
     *          The element abundances are still bad.
     *      3 = The solution changed significantly,
     *          The element abundances are still bad and a component 
     *          species got zeroed out.
     *
     *  Internal data to be worked on::
     *
     *  ga    Current element abundances
     *  m_elemAbundancesGoal   Required elemental abundances
     *  m_molNumSpecies_old     Current mole number of species.
     *  m_formulaMatrix[][]  Formular matrix of the species
     *  ne    Number of elements
     *  nc    Number of components.
     *
     * NOTES:
     *  This routine is turning out to be very problematic. There are 
     *  lots of special cases and problems with zeroing out species.
     *
     *  Still need to check out when we do loops over nc vs. ne.
     *  
     *************************************************************************/
  {
    int i, j, retn = 0, kspec, goodSpec, its; 
    double xx, par, saveDir, dir;

#ifdef DEBUG_MODE
    double l2before = 0.0, l2after = 0.0;
    std::vector<double> ga_save(m_numElemConstraints, 0.0);
    vcs_dcopy(VCS_DATA_PTR(ga_save), VCS_DATA_PTR(m_elemAbundances), m_numElemConstraints);
    if (m_debug_print_lvl >= 2) {
      plogf("   --- vcsc_elcorr: Element abundances correction routine");
      if (m_numElemConstraints != m_numComponents) {
	plogf(" (m_numComponents != m_numElemConstraints)");
      }
      plogf("\n");
    }

    for (i = 0; i < m_numElemConstraints; ++i) {
      x[i] = m_elemAbundances[i] - m_elemAbundancesGoal[i];
    }
    l2before = 0.0;
    for (i = 0; i < m_numElemConstraints; ++i) {
      l2before += x[i] * x[i];
    }
    l2before = sqrt(l2before/m_numElemConstraints);
#endif

    /*
     * Special section to take out single species, single component,
     * moles. These are species which have non-zero entries in the
     * formula matrix, and no other species have zero values either.
     *
     */
    int numNonZero = 0;
    bool changed = false;
    bool multisign = false;
    for (i = 0; i < m_numElemConstraints; ++i) {
      numNonZero = 0;
      multisign = false;
      for (kspec = 0; kspec < m_numSpeciesTot; kspec++) {
	if (m_speciesUnknownType[kspec] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
	  double eval = m_formulaMatrix[i][kspec];
	  if (eval < 0.0) {
	    multisign = true;
	  }
	  if (eval != 0.0) {
	    numNonZero++;
	  }
	}
      }
      if (!multisign) {
	if (numNonZero < 2) {
	  for (kspec = 0; kspec < m_numSpeciesTot; kspec++) {
	    if (m_speciesUnknownType[kspec] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
	      double eval = m_formulaMatrix[i][kspec];
	      if (eval > 0.0) {
		m_molNumSpecies_old[kspec] = m_elemAbundancesGoal[i] / eval;
		changed = true;
	      }
	    }
	  }
	} else {
	  int numCompNonZero = 0;
	  int compID = -1;
	  for (kspec = 0; kspec < m_numComponents; kspec++) {
	    if (m_speciesUnknownType[kspec] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
	      double eval = m_formulaMatrix[i][kspec];
	      if (eval > 0.0) {
		compID = kspec;
		numCompNonZero++;
	      }
	    }
	  }
	  if (numCompNonZero == 1) {
	    double diff = m_elemAbundancesGoal[i];
	    for (kspec = m_numComponents; kspec < m_numSpeciesTot; kspec++) {
	      if (m_speciesUnknownType[kspec] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
		double eval = m_formulaMatrix[i][kspec];
		diff -= eval * m_molNumSpecies_old[kspec];
	      }
	      m_molNumSpecies_old[compID] = MAX(0.0,diff/m_formulaMatrix[i][compID]);
	      changed = true;
	    }
	  }
	}
      }
    }
    if (changed) {
      vcs_elab();
    }

    /*
     *  Section to check for maximum bounds errors on all species
     *  due to elements.
     *    This may only be tried on element types which are VCS_ELEM_TYPE_ABSPOS.
     *    This is because no other species may have a negative number of these.
     *
     *  Note, also we can do this over ne, the number of elements, not just
     *  the number of components.
     */
    changed = false;
    for (i = 0; i < m_numElemConstraints; ++i) {
      int elType = m_elType[i];
      if (elType == VCS_ELEM_TYPE_ABSPOS) {
	for (kspec = 0; kspec < m_numSpeciesTot; kspec++) {
	  if (m_speciesUnknownType[kspec] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
	    double atomComp = m_formulaMatrix[i][kspec];
	    if (atomComp > 0.0) {
	      double maxPermissible = m_elemAbundancesGoal[i] / atomComp;
	      if (m_molNumSpecies_old[kspec] > maxPermissible) {
	      
#ifdef DEBUG_MODE
		if (m_debug_print_lvl >= 3) {
		  plogf("  ---  vcs_elcorr: Reduced species %s from %g to %g "
			"due to %s max bounds constraint\n",
			m_speciesName[kspec].c_str(), m_molNumSpecies_old[kspec], 
			maxPermissible, m_elementName[i].c_str());
		}
#endif
		m_molNumSpecies_old[kspec] = maxPermissible;
		changed = true;
		if (m_molNumSpecies_old[kspec] < VCS_DELETE_MINORSPECIES_CUTOFF) {
		  m_molNumSpecies_old[kspec] = 0.0;
		  if (m_SSPhase[kspec]) {
		    m_speciesStatus[kspec] = VCS_SPECIES_ZEROEDSS;
		  } else {
		    m_speciesStatus[kspec] = VCS_SPECIES_ACTIVEBUTZERO;
		  } 
#ifdef DEBUG_MODE
		  if (m_debug_print_lvl >= 2) {
		    plogf("  ---  vcs_elcorr: Zeroed species %s and changed "
			  "status to %d due to max bounds constraint\n",
			  m_speciesName[kspec].c_str(), m_speciesStatus[kspec]);
		  }
#endif
		}
	      }
	    }
	  }
	}
      }
    }

    // Recalculate the element abundances if something has changed.
    if (changed) {
      vcs_elab();
    }

    /*
     * Ok, do the general case. Linear algebra problem is 
     * of length nc, not ne, as there may be degenerate rows when
     * nc .ne. ne.
     */
    for (i = 0; i < m_numComponents; ++i) {
      x[i] = m_elemAbundances[i] - m_elemAbundancesGoal[i];
      if (fabs(x[i]) > 1.0E-13) retn = 1;
      for (j = 0; j < m_numComponents; ++j) {
	aa[j + i*m_numElemConstraints] = m_formulaMatrix[j][i];
      }
    }
    i = vcsUtil_mlequ(aa, m_numElemConstraints, m_numComponents, x, 1);
    if (i == 1) {
      plogf("vcs_elcorr ERROR: mlequ returned error condition\n");
      return VCS_FAILED_CONVERGENCE;
    }
    /*
     * Now apply the new direction without creating negative species.
     */
    par = 0.5;
    for (i = 0; i < m_numComponents; ++i) {
      if (m_molNumSpecies_old[i] > 0.0) {
	xx = -x[i] / m_molNumSpecies_old[i];
	if (par < xx) par = xx;
      }
    }
    if (par > 100.0) {
      par = 100.0;
    }
    par = 1.0 / par;
    if (par < 1.0 && par > 0.0) {
      retn = 2;
      par *= 0.9999;
      for (i = 0; i < m_numComponents; ++i) {
	double tmp = m_molNumSpecies_old[i] + par * x[i];
	if (tmp > 0.0) {
	  m_molNumSpecies_old[i] = tmp;
	} else {
	  if (m_SSPhase[i]) {
	    m_molNumSpecies_old[i] =  0.0;
	  }  else {
	    m_molNumSpecies_old[i] = m_molNumSpecies_old[i] * 0.0001;
	  }
	}
      }
    } else {
      for (i = 0; i < m_numComponents; ++i) {
	double tmp = m_molNumSpecies_old[i] + x[i];
	if (tmp > 0.0) {
	  m_molNumSpecies_old[i] = tmp;
	} else { 
	  if (m_SSPhase[i]) {
	    m_molNumSpecies_old[i] =  0.0;
	  }  else {
	    m_molNumSpecies_old[i] = m_molNumSpecies_old[i] * 0.0001;
	  }
	}
      }
    }
   
    /*
     *   We have changed the element abundances. Calculate them again
     */
    vcs_elab();
    /*
     *   We have changed the total moles in each phase. Calculate them again
     */
    vcs_tmoles();
    
    /*
     *       Try some ad hoc procedures for fixing the problem
     */
    if (retn >= 2) {
      /*
       *       First find a species whose adjustment is a win-win
       *       situation.
       */
      for (kspec = 0; kspec < m_numSpeciesTot; kspec++) {
	if (m_speciesUnknownType[kspec] == VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
	  continue;
	}
	saveDir = 0.0;
	goodSpec = TRUE;
	for (i = 0; i < m_numComponents; ++i) {
	  dir = m_formulaMatrix[i][kspec] *  (m_elemAbundancesGoal[i] - m_elemAbundances[i]);
	  if (fabs(dir) > 1.0E-10) {
	    if (dir > 0.0) {
	      if (saveDir < 0.0) {
		goodSpec = FALSE;
		break;
	      }
	    } else {
	      if (saveDir > 0.0) {
		goodSpec = FALSE;
		break;
	      }		   
	    }
	    saveDir = dir;
	  } else {
	    if (m_formulaMatrix[i][kspec] != 0.) {
	      goodSpec = FALSE;
	      break;
	    }
	  }
	}
	if (goodSpec) {
	  its = 0;
	  xx = 0.0;
	  for (i = 0; i < m_numComponents; ++i) {
	    if (m_formulaMatrix[i][kspec] != 0.0) {
	      xx += (m_elemAbundancesGoal[i] - m_elemAbundances[i]) / m_formulaMatrix[i][kspec];
	      its++;
	    }
	  }
	  if (its > 0) xx /= its;
	  m_molNumSpecies_old[kspec] += xx;
	  m_molNumSpecies_old[kspec] = MAX(m_molNumSpecies_old[kspec], 1.0E-10);
	  /*
	   *   If we are dealing with a deleted species, then
	   *   we need to reinsert it into the active list.
	   */
	  if (kspec >= m_numSpeciesRdc) {
	    vcs_reinsert_deleted(kspec);	
	    m_molNumSpecies_old[m_numSpeciesRdc - 1] = xx;
	    vcs_elab();
	    goto L_CLEANUP;
	  }
	  vcs_elab();  
	}
      }     
    }
    if (vcs_elabcheck(0)) {
      retn = 1;
      goto L_CLEANUP;
    }
  
    for (i = 0; i < m_numElemConstraints; ++i) {
      if (m_elType[i] == VCS_ELEM_TYPE_CHARGENEUTRALITY ||
	  (m_elType[i] == VCS_ELEM_TYPE_ABSPOS && m_elemAbundancesGoal[i] == 0.0)) { 
	for (kspec = 0; kspec < m_numSpeciesRdc; kspec++) {
	  if (m_elemAbundances[i] > 0.0) {
	    if (m_formulaMatrix[i][kspec] < 0.0) {
	      m_molNumSpecies_old[kspec] -= m_elemAbundances[i] / m_formulaMatrix[i][kspec] ;
	      if (m_molNumSpecies_old[kspec] < 0.0) {
		m_molNumSpecies_old[kspec] = 0.0;
	      }
	      vcs_elab();
	      break;
	    }
	  }
	  if (m_elemAbundances[i] < 0.0) {
	    if (m_formulaMatrix[i][kspec] > 0.0) {
	      m_molNumSpecies_old[kspec] -= m_elemAbundances[i] / m_formulaMatrix[i][kspec];
	      if (m_molNumSpecies_old[kspec] < 0.0) {
		m_molNumSpecies_old[kspec] = 0.0;
	      }
	      vcs_elab();
	      break;
	    }
	  }
	}
      }
    }
    if (vcs_elabcheck(1)) {
      retn = 1;      
      goto L_CLEANUP;
    }

    /*
     *  For electron charges element types, we try positive deltas
     *  in the species concentrations to match the desired
     *  electron charge exactly.
     */
    for (i = 0; i < m_numElemConstraints; ++i) {
      double dev = m_elemAbundancesGoal[i] - m_elemAbundances[i];
      if (m_elType[i] == VCS_ELEM_TYPE_ELECTRONCHARGE && (fabs(dev) > 1.0E-300)) {
	bool useZeroed = true;
	for (kspec = 0; kspec < m_numSpeciesRdc; kspec++) {
	  if (dev < 0.0) {
	    if (m_formulaMatrix[i][kspec] < 0.0) {
	      if (m_molNumSpecies_old[kspec] > 0.0) {
		useZeroed = false;
	      }
	    }
	  } else {
	    if (m_formulaMatrix[i][kspec] > 0.0) {
	      if (m_molNumSpecies_old[kspec] > 0.0) {
		useZeroed = false;
	      }
	    }
	  }
	}
	for (kspec = 0; kspec < m_numSpeciesRdc; kspec++) {
	  if (m_molNumSpecies_old[kspec] > 0.0 || useZeroed) {
	    if (dev < 0.0) {
	      if (m_formulaMatrix[i][kspec] < 0.0) {
		double delta = dev / m_formulaMatrix[i][kspec] ;
		m_molNumSpecies_old[kspec] += delta;
		if (m_molNumSpecies_old[kspec] < 0.0) {
		  m_molNumSpecies_old[kspec] = 0.0;
		}
		vcs_elab();
		break;
	      }
	    }
	    if (dev > 0.0) {
	      if (m_formulaMatrix[i][kspec] > 0.0) {
		double delta = dev / m_formulaMatrix[i][kspec] ;
		m_molNumSpecies_old[kspec] += delta;
		if (m_molNumSpecies_old[kspec] < 0.0) {
		  m_molNumSpecies_old[kspec] = 0.0;
		}
		vcs_elab();
		break;
	      }
	    }
	  }
	}
      }
    }
    if (vcs_elabcheck(1)) {
      retn = 1;      
      goto L_CLEANUP;
    }

  L_CLEANUP: ;
    vcs_tmoles();
#ifdef DEBUG_MODE
    l2after = 0.0;
    for (i = 0; i < m_numElemConstraints; ++i) {
      l2after += SQUARE(m_elemAbundances[i] - m_elemAbundancesGoal[i]);
    }
    l2after = sqrt(l2after/m_numElemConstraints);
    if (m_debug_print_lvl >= 2) {
      plogf("   ---    Elem_Abund:  Correct             Initial  "
	    "              Final\n");
      for (i = 0; i < m_numElemConstraints; ++i) {
	plogf("   ---       "); plogf("%-2.2s", m_elementName[i].c_str());
	plogf(" %20.12E %20.12E %20.12E\n", m_elemAbundancesGoal[i], ga_save[i], m_elemAbundances[i]);
      }
      plogf("   ---            Diff_Norm:         %20.12E %20.12E\n",
	    l2before, l2after);
    }
#endif
    return retn;
  }
コード例 #3
0
int VCS_SOLVE::vcs_setMolesLinProg()
{
    size_t ik, irxn;
    double test = -1.0E-10;

    if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
        plogf("   --- call setInitialMoles\n");
    }

    double dg_rt;
    int idir;
    double nu;
    double delta_xi, dxi_min = 1.0e10;
    bool redo = true;
    int retn;
    int iter = 0;
    bool abundancesOK = true;
    bool usedZeroedSpecies;
    vector_fp sm(m_numElemConstraints*m_numElemConstraints, 0.0);
    vector_fp ss(m_numElemConstraints, 0.0);
    vector_fp sa(m_numElemConstraints, 0.0);
    vector_fp wx(m_numElemConstraints, 0.0);
    vector_fp aw(m_numSpeciesTot, 0.0);

    for (ik = 0; ik < m_numSpeciesTot; ik++) {
        if (m_speciesUnknownType[ik] != VCS_SPECIES_INTERFACIALVOLTAGE) {
            m_molNumSpecies_old[ik] = max(0.0, m_molNumSpecies_old[ik]);
        }
    }

    if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
        printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
    }

    while (redo) {
        if (!vcs_elabcheck(0)) {
            if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
                plogf(" --- seMolesLinProg  Mole numbers failing element abundances\n");
                plogf(" --- seMolesLinProg  Call vcs_elcorr to attempt fix\n");
            }
            retn = vcs_elcorr(&sm[0], &wx[0]);
            if (retn >= 2) {
                abundancesOK = false;
            } else {
                abundancesOK = true;
            }
        } else {
            abundancesOK = true;
        }
        /*
         *  Now find the optimized basis that spans the stoichiometric
         *  coefficient matrix, based on the current composition, m_molNumSpecies_old[]
         *  We also calculate sc[][], the reaction matrix.
         */
        retn = vcs_basopt(false, &aw[0], &sa[0], &sm[0], &ss[0],
                          test, &usedZeroedSpecies);
        if (retn != VCS_SUCCESS) {
            return retn;
        }

        if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
            plogf("iteration %d\n", iter);
        }
        redo = false;
        iter++;
        if (iter > 15) {
            break;
        }

        // loop over all reactions
        for (irxn = 0; irxn < m_numRxnTot; irxn++) {
            // dg_rt is the Delta_G / RT value for the reaction
            ik = m_numComponents + irxn;
            dg_rt = m_SSfeSpecies[ik];
            dxi_min = 1.0e10;
            const double* sc_irxn = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
            for (size_t jcomp = 0; jcomp < m_numElemConstraints; jcomp++) {
                dg_rt += m_SSfeSpecies[jcomp] * sc_irxn[jcomp];
            }
            // fwd or rev direction.
            //  idir > 0 implies increasing the current species
            //  idir < 0 implies decreasing the current species
            idir = (dg_rt < 0.0 ? 1 : -1);
            if (idir < 0) {
                dxi_min = m_molNumSpecies_old[ik];
            }

            for (size_t jcomp = 0; jcomp < m_numComponents; jcomp++) {
                nu = sc_irxn[jcomp];
                // set max change in progress variable by
                // non-negativity requirement
                if (nu*idir < 0) {
                    delta_xi = fabs(m_molNumSpecies_old[jcomp]/nu);
                    // if a component has nearly zero moles, redo
                    // with a new set of components
                    if (!redo && delta_xi < 1.0e-10 && (m_molNumSpecies_old[ik] >= 1.0E-10)) {
                        if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
                            plogf("   --- Component too small: %s\n", m_speciesName[jcomp]);
                        }
                        redo = true;
                    }
                    dxi_min = std::min(dxi_min, delta_xi);
                }
            }

            // step the composition by dxi_min, check against zero, since
            // we are zeroing components and species on every step.
            // Redo the iteration, if a component went from positive to zero on this step.
            double dsLocal = idir*dxi_min;
            m_molNumSpecies_old[ik] += dsLocal;
            m_molNumSpecies_old[ik] = max(0.0, m_molNumSpecies_old[ik]);
            for (size_t jcomp = 0; jcomp < m_numComponents; jcomp++) {
                bool full = false;
                if (m_molNumSpecies_old[jcomp] > 1.0E-15) {
                    full = true;
                }
                m_molNumSpecies_old[jcomp] += sc_irxn[jcomp] * dsLocal;
                m_molNumSpecies_old[jcomp] = max(0.0, m_molNumSpecies_old[jcomp]);
                if (full && m_molNumSpecies_old[jcomp] < 1.0E-60) {
                    redo = true;
                }
            }
        }

        if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
            printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
        }
    }

    if (DEBUG_MODE_ENABLED && m_debug_print_lvl == 1) {
        printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
        plogf("   --- setInitialMoles end\n");
    }
    retn = 0;
    if (!abundancesOK) {
        retn = -1;
    } else if (iter > 15) {
        retn = 1;
    }
    return retn;
}
コード例 #4
0
ファイル: vcs_inest.cpp プロジェクト: Cantera/cantera-svn
int VCS_SOLVE::vcs_inest_TP()
{
    int retn = 0;
    Cantera::clockWC tickTock;

    if (m_doEstimateEquil > 0) {
        /*
         *  Calculate the elemental abundances
         */
        vcs_elab();
        if (vcs_elabcheck(0)) {
            if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
                plogf("%s Initial guess passed element abundances on input\n", pprefix);
                plogf("%s m_doEstimateEquil = 1 so will use the input mole "
                      "numbers as estimates", pprefix);
                plogendl();
            }
            return retn;
        } else if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
            plogf("%s Initial guess failed element abundances on input\n", pprefix);
            plogf("%s m_doEstimateEquil = 1 so will discard input "
                  "mole numbers and find our own estimate", pprefix);
            plogendl();
        }
    }

    /*
     *  Malloc temporary space for usage in this routine and in
     *  subroutines
     *        sm[ne*ne]
     *        ss[ne]
     *        sa[ne]
     *        aw[m]
     */
    std::vector<double> sm(m_numElemConstraints*m_numElemConstraints, 0.0);
    std::vector<double> ss(m_numElemConstraints, 0.0);
    std::vector<double> sa(m_numElemConstraints, 0.0);
    std::vector<double> aw(m_numSpeciesTot+ m_numElemConstraints, 0.0);
    /*
     *  Go get the estimate of the solution
     */
    if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
        plogf("%sGo find an initial estimate for the equilibrium problem",
              pprefix);
        plogendl();
    }
    double test = -1.0E20;
    vcs_inest(VCS_DATA_PTR(aw), VCS_DATA_PTR(sa), VCS_DATA_PTR(sm),
              VCS_DATA_PTR(ss), test);
    /*
     *  Calculate the elemental abundances
     */
    vcs_elab();

    /*
     *      If we still fail to achieve the correct elemental abundances,
     *      try to fix the problem again by calling the main elemental abundances
     *      fixer routine, used in the main program. This
     *      attempts to tweak the mole numbers of the component species to
     *      satisfy the element abundance constraints.
     *
     *       Note: We won't do this unless we have to since it involves inverting
     *             a matrix.
     */
    bool rangeCheck = vcs_elabcheck(1);
    if (!vcs_elabcheck(0)) {
        if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
            plogf("%sInitial guess failed element abundances\n", pprefix);
            plogf("%sCall vcs_elcorr to attempt fix", pprefix);
            plogendl();
        }
        vcs_elcorr(VCS_DATA_PTR(sm), VCS_DATA_PTR(aw));
        rangeCheck  = vcs_elabcheck(1);
        if (!vcs_elabcheck(0)) {
            plogf("%sInitial guess still fails element abundance equations\n",
                  pprefix);
            plogf("%s - Inability to ever satisfy element abundance "
                  "constraints is probable", pprefix);
            plogendl();
            retn = -1;
        } else {
            if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
                if (rangeCheck) {
                    plogf("%sInitial guess now satisfies element abundances", pprefix);
                    plogendl();
                } else {
                    plogf("%sElement Abundances RANGE ERROR\n", pprefix);
                    plogf("%s - Initial guess satisfies NC=%d element abundances, "
                          "BUT not NE=%d element abundances", pprefix,
                          m_numComponents, m_numElemConstraints);
                    plogendl();
                }
            }
        }
    } else {
        if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
            if (rangeCheck) {
                plogf("%sInitial guess satisfies element abundances", pprefix);
                plogendl();
            } else {
                plogf("%sElement Abundances RANGE ERROR\n", pprefix);
                plogf("%s - Initial guess satisfies NC=%d element abundances, "
                      "BUT not NE=%d element abundances", pprefix,
                      m_numComponents, m_numElemConstraints);
                plogendl();
            }
        }
    }

    if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
        plogf("%sTotal Dimensionless Gibbs Free Energy = %15.7E", pprefix,
              vcs_Total_Gibbs(VCS_DATA_PTR(m_molNumSpecies_old), VCS_DATA_PTR(m_feSpecies_new),
                              VCS_DATA_PTR(m_tPhaseMoles_old)));
        plogendl();
    }

    /*
     * Record time
     */
    m_VCount->T_Time_inest += tickTock.secondsWC();
    (m_VCount->T_Calls_Inest)++;
    return retn;
}