/* * This routine is always followed by vcs_prep(). Therefore, tasks * that need to be done for every call to vcsc() should be placed in * vcs_prep() and not in this routine. * * The problem structure refers to: * * the number and identity of the species. * the formula matrix and thus the number of components. * the number and identity of the phases. * the equation of state * the method and parameters for determining the standard state * The method and parameters for determining the activity coefficients. * * Tasks: * 0) Fill in the SSPhase[] array. * 1) Check to see if any multispecies phases actually have only one * species in that phase. If true, reassign that phase and species * to be a single-species phase. * 2) Determine the number of components in the problem if not already * done so. During this process the order of the species is changed * in the private data structure. All references to the species * properties must employ the ind[] index vector. * * @param printLvl Print level of the routine * * @return the return code * VCS_SUCCESS = everything went OK * */ int VCS_SOLVE::vcs_prep_oneTime(int printLvl) { size_t kspec, i; int retn = VCS_SUCCESS; double pres, test; double *aw, *sa, *sm, *ss; bool modifiedSoln = false; bool conv; m_debug_print_lvl = printLvl; /* * Calculate the Single Species status of phases * Also calculate the number of species per phase */ vcs_SSPhase(); /* * Set an initial estimate for the number of noncomponent species * equal to nspecies - nelements. This may be changed below */ m_numRxnTot = m_numSpeciesTot - m_numElemConstraints; m_numRxnRdc = m_numRxnTot; m_numSpeciesRdc = m_numSpeciesTot; for (i = 0; i < m_numRxnRdc; ++i) { m_indexRxnToSpecies[i] = m_numElemConstraints + i; } for (kspec = 0; kspec < m_numSpeciesTot; ++kspec) { size_t pID = m_phaseID[kspec]; size_t spPhIndex = m_speciesLocalPhaseIndex[kspec]; vcs_VolPhase *vPhase = m_VolPhaseList[pID]; vcs_SpeciesProperties *spProp = vPhase->speciesProperty(spPhIndex); double sz = 0.0; size_t eSize = spProp->FormulaMatrixCol.size(); for (size_t e = 0; e < eSize; e++) { sz += fabs(spProp->FormulaMatrixCol[e]); } if (sz > 0.0) { m_spSize[kspec] = sz; } else { m_spSize[kspec] = 1.0; } } /* ***************************************************** */ /* **** DETERMINE THE NUMBER OF COMPONENTS ************* */ /* ***************************************************** */ /* * Obtain a valid estimate of the mole fraction. This will * be used as an initial ordering vector for prioritizing * which species are defined as components. * * If a mole number estimate was supplied from the * input file, use that mole number estimate. * * If a solution estimate wasn't supplied from the input file, * supply an initial estimate for the mole fractions * based on the relative reverse ordering of the * chemical potentials. * * For voltage unknowns, set these to zero for the moment. */ test = -1.0e-10; if (m_doEstimateEquil < 0) { double sum = 0.0; for (kspec = 0; kspec < m_numSpeciesTot; ++kspec) { if (m_speciesUnknownType[kspec] == VCS_SPECIES_TYPE_MOLNUM) { sum += fabs(m_molNumSpecies_old[kspec]); } } if (fabs(sum) < 1.0E-6) { modifiedSoln = true; if (m_pressurePA <= 0.0) pres = 1.01325E5; else pres = m_pressurePA; retn = vcs_evalSS_TP(0, 0, m_temperature, pres); for (kspec = 0; kspec < m_numSpeciesTot; ++kspec) { if (m_speciesUnknownType[kspec] == VCS_SPECIES_TYPE_MOLNUM) { m_molNumSpecies_old[kspec] = - m_SSfeSpecies[kspec]; } else { m_molNumSpecies_old[kspec] = 0.0; } } } test = -1.0e20; } /* * NC = number of components is in the vcs.h common block * This call to BASOPT doesn't calculate the stoichiometric * reaction matrix. */ std::vector<double> awSpace( m_numSpeciesTot + (m_numElemConstraints + 2)*(m_numElemConstraints), 0.0); aw = VCS_DATA_PTR(awSpace); if (aw == NULL) { plogf("vcs_prep_oneTime: failed to get memory: global bailout\n"); return VCS_NOMEMORY; } sa = aw + m_numSpeciesTot; sm = sa + m_numElemConstraints; ss = sm + (m_numElemConstraints)*(m_numElemConstraints); retn = vcs_basopt(true, aw, sa, sm, ss, test, &conv); if (retn != VCS_SUCCESS) { plogf("vcs_prep_oneTime:"); plogf(" Determination of number of components failed: %d\n", retn); plogf(" Global Bailout!\n"); return retn; } if (m_numElemConstraints != m_numComponents) { m_numRxnTot = m_numRxnRdc = m_numSpeciesTot - m_numComponents; for (i = 0; i < m_numRxnRdc; ++i) { m_indexRxnToSpecies[i] = m_numComponents + i; } } /* * The elements might need to be rearranged. */ awSpace.resize(m_numElemConstraints + (m_numElemConstraints + 2)*(m_numElemConstraints), 0.0); aw = VCS_DATA_PTR(awSpace); sa = aw + m_numElemConstraints; sm = sa + m_numElemConstraints; ss = sm + (m_numElemConstraints)*(m_numElemConstraints); retn = vcs_elem_rearrange(aw, sa, sm, ss); if (retn != VCS_SUCCESS) { plogf("vcs_prep_oneTime:"); plogf(" Determination of element reordering failed: %d\n", retn); plogf(" Global Bailout!\n"); return retn; } // If we mucked up the solution unknowns because they were all // zero to start with, set them back to zero here if (modifiedSoln) { for (kspec = 0; kspec < m_numSpeciesTot; ++kspec) { m_molNumSpecies_old[kspec] = 0.0; } } return VCS_SUCCESS; }
int VCS_SOLVE::vcs_prep(int printLvl) { int retn = VCS_SUCCESS; m_debug_print_lvl = printLvl; // Calculate the Single Species status of phases // Also calculate the number of species per phase vcs_SSPhase(); // Set an initial estimate for the number of noncomponent species equal to // nspecies - nelements. This may be changed below if (m_nelem > m_nsp) { m_numRxnTot = 0; } else { m_numRxnTot = m_nsp - m_nelem; } m_numRxnRdc = m_numRxnTot; m_numSpeciesRdc = m_nsp; for (size_t i = 0; i < m_numRxnRdc; ++i) { m_indexRxnToSpecies[i] = m_nelem + i; } for (size_t kspec = 0; kspec < m_nsp; ++kspec) { size_t pID = m_phaseID[kspec]; size_t spPhIndex = m_speciesLocalPhaseIndex[kspec]; vcs_VolPhase* vPhase = m_VolPhaseList[pID].get(); vcs_SpeciesProperties* spProp = vPhase->speciesProperty(spPhIndex); double sz = 0.0; size_t eSize = spProp->FormulaMatrixCol.size(); for (size_t e = 0; e < eSize; e++) { sz += fabs(spProp->FormulaMatrixCol[e]); } if (sz > 0.0) { m_spSize[kspec] = sz; } else { m_spSize[kspec] = 1.0; } } // DETERMINE THE NUMBER OF COMPONENTS // // Obtain a valid estimate of the mole fraction. This will be used as an // initial ordering vector for prioritizing which species are defined as // components. // // If a mole number estimate was supplied from the input file, use that mole // number estimate. // // If a solution estimate wasn't supplied from the input file, supply an // initial estimate for the mole fractions based on the relative reverse // ordering of the chemical potentials. // // For voltage unknowns, set these to zero for the moment. double test = -1.0e-10; bool modifiedSoln = false; if (m_doEstimateEquil < 0) { double sum = 0.0; for (size_t kspec = 0; kspec < m_nsp; ++kspec) { if (m_speciesUnknownType[kspec] == VCS_SPECIES_TYPE_MOLNUM) { sum += fabs(m_molNumSpecies_old[kspec]); } } if (fabs(sum) < 1.0E-6) { modifiedSoln = true; double pres = (m_pressurePA <= 0.0) ? 1.01325E5 : m_pressurePA; retn = vcs_evalSS_TP(0, 0, m_temperature, pres); for (size_t kspec = 0; kspec < m_nsp; ++kspec) { if (m_speciesUnknownType[kspec] == VCS_SPECIES_TYPE_MOLNUM) { m_molNumSpecies_old[kspec] = - m_SSfeSpecies[kspec]; } else { m_molNumSpecies_old[kspec] = 0.0; } } } test = -1.0e20; } // NC = number of components is in the vcs.h common block. This call to // BASOPT doesn't calculate the stoichiometric reaction matrix. vector_fp awSpace(m_nsp + (m_nelem + 2)*(m_nelem), 0.0); double* aw = &awSpace[0]; if (aw == NULL) { plogf("vcs_prep_oneTime: failed to get memory: global bailout\n"); return VCS_NOMEMORY; } double* sa = aw + m_nsp; double* sm = sa + m_nelem; double* ss = sm + m_nelem * m_nelem; bool conv; retn = vcs_basopt(true, aw, sa, sm, ss, test, &conv); if (retn != VCS_SUCCESS) { plogf("vcs_prep_oneTime:"); plogf(" Determination of number of components failed: %d\n", retn); plogf(" Global Bailout!\n"); return retn; } if (m_nsp >= m_numComponents) { m_numRxnTot = m_numRxnRdc = m_nsp - m_numComponents; for (size_t i = 0; i < m_numRxnRdc; ++i) { m_indexRxnToSpecies[i] = m_numComponents + i; } } else { m_numRxnTot = m_numRxnRdc = 0; } // The elements might need to be rearranged. awSpace.resize(m_nelem + (m_nelem + 2)*m_nelem, 0.0); aw = &awSpace[0]; sa = aw + m_nelem; sm = sa + m_nelem; ss = sm + m_nelem * m_nelem; retn = vcs_elem_rearrange(aw, sa, sm, ss); if (retn != VCS_SUCCESS) { plogf("vcs_prep_oneTime:"); plogf(" Determination of element reordering failed: %d\n", retn); plogf(" Global Bailout!\n"); return retn; } // If we mucked up the solution unknowns because they were all // zero to start with, set them back to zero here if (modifiedSoln) { for (size_t kspec = 0; kspec < m_nsp; ++kspec) { m_molNumSpecies_old[kspec] = 0.0; } } // Initialize various arrays in the data to zero m_feSpecies_old.assign(m_feSpecies_old.size(), 0.0); m_feSpecies_new.assign(m_feSpecies_new.size(), 0.0); m_molNumSpecies_new.assign(m_molNumSpecies_new.size(), 0.0); m_deltaMolNumPhase.zero(); m_phaseParticipation.zero(); m_deltaPhaseMoles.assign(m_deltaPhaseMoles.size(), 0.0); m_tPhaseMoles_new.assign(m_tPhaseMoles_new.size(), 0.0); // Calculate the total number of moles in all phases. vcs_tmoles(); // Check to see if the current problem is well posed. double sum = 0.0; for (size_t e = 0; e < m_nelem; e++) { sum += m_mix->elementMoles(e); } if (sum < 1.0E-20) { // Check to see if the current problem is well posed. plogf("vcs has determined the problem is not well posed: Bailing\n"); return VCS_PUB_BAD; } return VCS_SUCCESS; }