Example #1
0
  // Chose the variable pressure standard state manager 
  // and the reference standard state manager
  VPSSMgr* 
  VPSSMgrFactory::newVPSSMgr(VPStandardStateTP *vp_ptr, 
			     XML_Node* phaseNode_ptr,
			     std::vector<XML_Node*> & spDataNodeList) {

    std::string ssManager="";
    std::string vpssManager="";
    VPSSMgr *vpss = 0;

    // First look for any explicit instructions within the XML Database
    // for the standard state manager and the variable pressure 
    // standard state manager
    if (phaseNode_ptr) {
      if (phaseNode_ptr->hasChild("thermo")) {
	const XML_Node& thermoNode = phaseNode_ptr->child("thermo");
	if (thermoNode.hasChild("standardStateManager")) {
	  const XML_Node& ssNode = thermoNode.child("standardStateManager");
	  ssManager = ssNode["model"];
	}
	if (thermoNode.hasChild("variablePressureStandardStateManager")) {
	  const XML_Node& vpssNode = thermoNode.child("variablePressureStandardStateManager");
	  vpssManager = vpssNode["model"];
	}
      }
    }

    // first get the reference state handler. If we have explicit instructions,
    // use them to spawn the object.
    SpeciesThermo *spth = 0;
    if (ssManager != "") {
      spth = newSpeciesThermoMgr(ssManager);
    } else {
      spth = newSpeciesThermoMgr(spDataNodeList);
    }
    vp_ptr->setSpeciesThermo(spth);

    // Next, if we have specific directions, use them to get the VPSSSMgr object
    // and return immediately
    if (vpssManager != "") {
      VPSSMgr_enumType type = VPSSMgr_StringConversion(vpssManager);
      vpss = newVPSSMgr(type, vp_ptr);
      return vpss;
    }

 
    // If it comes back as general, then there may be some unknown 
    // parameterizations to the SpeciesThermo factory routine.
    bool haveSomeUnknowns = true;
    GeneralSpeciesThermo *ttmp = dynamic_cast<GeneralSpeciesThermo *>(spth);
    if (ttmp == 0) {
      haveSomeUnknowns = false;
    }
 
    // Handle special cases based on the VPStandardState types
    if (vp_ptr->eosType() == cVPSS_IdealGas) {
      vpss = new VPSSMgr_IdealGas(vp_ptr, spth);
      return vpss;
    } else if (vp_ptr->eosType() == cVPSS_ConstVol) {
      vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
      return vpss;
    }


    int inasaIG = 0, inasaCV = 0, ishomateIG = 0, ishomateCV = 0,
      isimpleIG = 0, isimpleCV = 0, 
      iwater = 0, itpx = 0, iother = 0;
    int ihptx = 0;
  
    try {
      getVPSSMgrTypes(spDataNodeList, inasaIG, inasaCV, ishomateIG, ishomateCV,
		      isimpleIG, isimpleCV, iwater, itpx, ihptx, iother);
    } catch (UnknownSpeciesThermoModel) {
      iother = 1;
      popError();
    }
    
    if (iwater == 1) {
      if (ihptx == 0) {
	if (inasaIG ||  ishomateIG || isimpleIG) {
	  throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
	} else {
	  vpss = new VPSSMgr_Water_ConstVol(vp_ptr, spth);
	}
      } else {
	if (inasaIG ||  ishomateIG || isimpleIG) {
	  throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
	} else if (inasaCV || ishomateCV ||  isimpleCV) {
	  vpss = new VPSSMgr_General(vp_ptr, spth);
	} else {
	  vpss = new VPSSMgr_Water_HKFT(vp_ptr, spth);
	}
      }
    }
    if (vpss == 0) {
      if (inasaCV || ishomateCV || isimpleCV) {
	if (!inasaIG && !ishomateIG && !isimpleIG && !itpx && !ihptx && !iother) {
	  vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
	}
      }
    }
    if (vpss == 0) {
      vpss = new VPSSMgr_General(vp_ptr, spth);
    }
    return vpss;
  }
Example #2
0
bool importPhase(XML_Node& phase, ThermoPhase* th,
                 SpeciesThermoFactory* spfactory)
{
    // Check the the supplied XML node in fact represents a phase.
    if (phase.name() != "phase") {
        throw CanteraError("importPhase",
                           "Current const XML_Node named, " + phase.name() +
                           ", is not a phase element.");
    }

    /*
     * In this section of code, we get the reference to the
     * phase xml tree within the ThermoPhase object. Then,
     * we clear it and fill it with the current information that
     * we are about to use to construct the object. We will then
     * be able to resurrect the information later by calling xml().
     */
    th->setXMLdata(phase);

    // set the id attribute of the phase to the 'id' attribute in the XML tree.
    th->setID(phase.id());
    th->setName(phase.id());

    // Number of spatial dimensions. Defaults to 3 (bulk phase)
    if (phase.hasAttrib("dim")) {
        int idim = intValue(phase["dim"]);
        if (idim < 1 || idim > 3)
            throw CanteraError("importPhase",
                               "phase, " + th->id() +
                               ", has unphysical number of dimensions: " + phase["dim"]);
        th->setNDim(idim);
    } else {
        th->setNDim(3);     // default
    }

    // Set equation of state parameters. The parameters are
    // specific to each subclass of ThermoPhase, so this is done
    // by method setParametersFromXML in each subclass.
    const XML_Node& eos = phase.child("thermo");
    if (phase.hasChild("thermo")) {
        th->setParametersFromXML(eos);
    } else {
        throw CanteraError("importPhase",
                           " phase, " + th->id() +
                           ", XML_Node does not have a \"thermo\" XML_Node");
    }

    VPStandardStateTP* vpss_ptr = 0;
    int ssConvention = th->standardStateConvention();
    if (ssConvention == cSS_CONVENTION_VPSS) {
        vpss_ptr = dynamic_cast <VPStandardStateTP*>(th);
        if (vpss_ptr == 0) {
            throw CanteraError("importPhase",
                               "phase, " + th->id() + ", was VPSS, but dynamic cast failed");
        }
    }

    // if no species thermo factory was supplied, use the default one.
    if (!spfactory) {
        spfactory = SpeciesThermoFactory::factory();
    }

    /***************************************************************
     * Add the elements.
     ***************************************************************/
    if (ssConvention != cSS_CONVENTION_SLAVE) {
        installElements(*th, phase);
    }

    /***************************************************************
     * Add the species.
     *
     * Species definitions may be imported from multiple
     * sources. For each one, a speciesArray element must be
     * present.
     ***************************************************************/
    vector<XML_Node*> sparrays;
    phase.getChildren("speciesArray", sparrays);
    if (ssConvention != cSS_CONVENTION_SLAVE) {
        if (sparrays.empty()) {
            throw CanteraError("importPhase",
                               "phase, " + th->id() + ", has zero \"speciesArray\" XML nodes.\n"
                               + " There must be at least one speciesArray nodes "
                               "with one or more species");
        }
    }
    vector<XML_Node*> dbases;
    vector_int sprule(sparrays.size(),0);

    // loop over the speciesArray elements
    for (size_t jsp = 0; jsp < sparrays.size(); jsp++) {

        const XML_Node& speciesArray = *sparrays[jsp];

        // If the speciesArray element has a child element
        //
        //   <skip element="undeclared">
        //
        // then set sprule[jsp] to 1, so that any species with an undeclared
        // element will be quietly skipped when importing species. Additionally,
        // if the skip node has the following attribute:
        //
        // <skip species="duplicate">
        //
        // then duplicate species names will not cause Cantera to throw an
        // exception. Instead, the duplicate entry will be discarded.
        if (speciesArray.hasChild("skip")) {
            const XML_Node& sk = speciesArray.child("skip");
            string eskip = sk["element"];
            if (eskip == "undeclared") {
                sprule[jsp] = 1;
            }
            string dskip = sk["species"];
            if (dskip == "duplicate") {
                sprule[jsp] += 10;
            }
        }

        // Get a pointer to the node containing the species
        // definitions for the species declared in this
        // speciesArray element. This may be in the local file
        // containing the phase element, or may be in another
        // file.
        XML_Node* db = get_XML_Node(speciesArray["datasrc"], &phase.root());
        if (db == 0) {
            throw CanteraError("importPhase()",
                               " Can not find XML node for species database: "
                               + speciesArray["datasrc"]);
        }

        // add this node to the list of species database nodes.
        dbases.push_back(db);
    }

    // Now, collect all the species names and all the XML_Node * pointers
    // for those species in a single vector. This is where we decide what
    // species are to be included in the phase.
    // The logic is complicated enough that we put it in a separate routine.
    std::vector<XML_Node*>  spDataNodeList;
    std::vector<std::string> spNamesList;
    std::vector<int> spRuleList;
    formSpeciesXMLNodeList(spDataNodeList, spNamesList, spRuleList,
                           sparrays, dbases, sprule);

    // Decide whether the the phase has a variable pressure ss or not
    SpeciesThermo* spth = 0;
    VPSSMgr* vp_spth = 0;
    if (ssConvention == cSS_CONVENTION_TEMPERATURE) {
        // Create a new species thermo manager.  Function
        // 'newSpeciesThermoMgr' looks at the species in the database
        // to see what thermodynamic property parameterizations are
        // used, and selects a class that can handle the
        // parameterizations found.
        spth = newSpeciesThermoMgr(spDataNodeList);

        // install it in the phase object
        th->setSpeciesThermo(spth);
    } else if (ssConvention == cSS_CONVENTION_SLAVE) {
        /*
         * No species thermo manager for this type
         */
    } else if (ssConvention == cSS_CONVENTION_VPSS) {
        vp_spth = newVPSSMgr(vpss_ptr, &phase, spDataNodeList);
        vpss_ptr->setVPSSMgr(vp_spth);
        spth = vp_spth->SpeciesThermoMgr();
        th->setSpeciesThermo(spth);
    } else {
        throw CanteraError("importPhase()", "unknown convention");
    }


    size_t k = 0;

    size_t nsp = spDataNodeList.size();
    if (ssConvention == cSS_CONVENTION_SLAVE) {
        if (nsp > 0) {
            throw CanteraError("importPhase()", "For Slave standard states, number of species must be zero: "
                               + int2str(nsp));
        }
    }
    for (size_t i = 0; i < nsp; i++) {
        XML_Node* s = spDataNodeList[i];
        AssertTrace(s != 0);
        bool ok = installSpecies(k, *s, *th, spth, spRuleList[i],
                                 &phase, vp_spth, spfactory);
        if (ok) {
            th->saveSpeciesData(k, s);
            ++k;
        }
    }

    if (ssConvention == cSS_CONVENTION_SLAVE) {
        th->installSlavePhases(&phase);
    }

    // Done adding species. Perform any required subclass-specific
    // initialization.
    th->initThermo();

    // Perform any required subclass-specific initialization
    // that requires the XML phase object
    std::string id = "";
    th->initThermoXML(phase, id);

    return true;
}