void PrescribedMoleFractionsDirichletOldStyleBCFactory::
  convert_mole_fracs_and_add_to_func
  (const GetPot& input, const std::vector<libMesh::Number>& species_mole_fracs,
   const SpeciesMassFractionsVariable& species_fe_var,
   libMesh::CompositeFunction<libMesh::Number>& composite_func) const
  {
    const std::string& material = species_fe_var.material();

    /*! \todo We should have a ChemsitryWarehouse or something to just
              grab this from one place instead of rebuilding. */
    ChemistryType chem(input,material);

    const unsigned int n_vars = species_mole_fracs.size();
    // Compute M
    libMesh::Real M = 0.0;
    for( unsigned int s = 0; s < n_vars; s++ )
      M += species_mole_fracs[s]*chem.M(s);

    // Convert mole fractions to mass fractions and add to function
    for( unsigned int s = 0; s < n_vars; s++ )
      {
        libMesh::Number species_mass_fracs =species_mole_fracs[s]*chem.M(s)/M;

        std::vector<VariableIndex> var_idx(1,species_fe_var.species(s));

        libMesh::ConstFunction<libMesh::Number> const_func(species_mass_fracs);
        composite_func.attach_subfunction(const_func,var_idx);
      }
  }
Ejemplo n.º 2
0
int main(int argc, char* argv[])
{
  MPI_Init(&argc, &argv);
  
  Int i, j;
  Int ierr = 0;
  std::stringstream ss;
  Real TGiven;
  Real* rhoi;
  Real* wdot;
  Real* molfrac;

  if(argc != 3){
    std::cerr << "USAGE: " << argv[0] << " casename Temperature(K)" << std::endl;
    return(1);
  }
  
  //setup parameter file so we can read reference states, etc.
  std::vector<Param<double>*> paramList;
  SolutionOrdering<Real> operations;
  TemporalControl<double> temporalControl;
  std::string casestring = argv[1];
  size_t pos = casestring.rfind('/');
  std::string pathname;
  if(pos != std::string::npos){
    pathname = casestring.substr(0, pos+1);
    casestring = casestring.substr(pos);
  }
  else{
    pathname = "./";
  }
  if(ReadParamFile(paramList, casestring, pathname)){
    return (-1);
  }
  if(operations.Read(casestring, pathname)){
    return (-1);
  }
  if(temporalControl.Read(casestring, pathname)){
    return (-1);
  }

  //only use the first solution space defined in param file
  Param<double> param = *paramList.front();

  //read temperature for production rates from command line
  ss << argv[2];
  ss >> TGiven;

  //read reaction file
  ChemModel<double> chem(param.casestring, param.chemDB);

  rhoi = new Real[chem.nspecies];
  wdot = new Real[chem.nspecies];
  molfrac = new Real[chem.nspecies];

  //using massfraction information available from param file if there
  //print out standard state conditions using chemistry
  if(param.molefractions.size() == chem.nspecies){
    //convert to massfractions
    double* molfrac = (double*)alloca(sizeof(double)*chem.nspecies);
    double* massfrac = (double*)alloca(sizeof(double)*chem.nspecies); 
    for(int i = 0; i < chem.nspecies; ++i){
      molfrac[i] = param.molefractions[i];
    }
    chem.MoleFractionToMassFraction(molfrac, massfrac);
    param.massfractions.resize(chem.nspecies);
    for(int i = 0; i < chem.nspecies; ++i){
      param.massfractions[i] = massfrac[i];
    }
  }
  
  if(param.massfractions.size() == chem.nspecies){
    for(i = 0; i < chem.nspecies; i++){
      std::cout << "rho[" << chem.species[i].symbol << "]: " 
		<< param.massfractions[i]*param.ref_density << " kg/m^3" << std::endl;
    }
  }
  else{
    std::cerr << "Number of species defined in param file does not match chem model" << std::endl;
    return(-1);
  }

  //compute rho and R, store massfractions
  double rho = 0.0;
  double R = 0.0;
  double X[chem.nspecies]; //massfraction
  if(param.massfractions.size() == chem.nspecies){
    for(i = 0; i < chem.nspecies; i++){
      X[i] = param.massfractions[i];
      rhoi[i] = param.massfractions[i]*param.ref_density;
      rho += rhoi[i];
      R += chem.species[i].R*(rhoi[i]);
    }
  }
  //R is dimensional after this
  R /= rho;
  double P = chem.GetP(rhoi, TGiven);
  double gamma = 0.0;
  double cv = 0.0;
  double cp = 0.0;
  double hi[chem.nspecies];
  if(param.massfractions.size() != chem.nspecies){
    std::cerr << "Number of species defined in param file does not match chem model" << std::endl;
    return(-1);
  }
  int Tlevels = (int)3500/100.0;
  std::cout << std::endl;
  std::cout << "Temp(K)" << "\t" << std::setw(10) << "Cv(J/kg.K)"
	    << "\t" << std::setw(8) << "Cp(J/kg.K)"
	    << "\t" << std::setw(8) << "Cp/R"
	    << "\t" << std::setw(8) << "H(J/kg)"
	    << "\t" << std::setw(8) << "h/RT"
	    << "\t" << std::setw(8) << "mu(Pa.s)"
	    << "\t" << std::setw(8) << "k(W/m.K)" << std::endl;
  std::cout << "----------------------------------------------------------------------------------------------------------------------" << std::endl;
  for(j = 0; j < Tlevels; j++){
    double Ti = (double)(j*100.0 + 100.0);
    double cp = chem.GetCp(rhoi, Ti);
    double cv = chem.GetCv(rhoi, Ti);
    double h = chem.GetSpecificEnthalpy(X, Ti, hi);
    double mu = chem.GetViscosity(rhoi, Ti);
    double k = chem.GetThermalConductivity(rhoi, Ti);
    std::cout << Ti
	      << "\t" << std::setw(10) << cv
	      << "\t" << std::setw(10) << cp
	      << "\t" << std::setw(10) << cp/R
	      << "\t" << std::setw(10) << h
	      << "\t" << std::setw(10) << h/R/Ti
	      << "\t" << std::setw(10) << mu
	      << "\t" << std::setw(10) << k << std::endl;
  }
  std::cout << std::endl;
  cv = chem.GetCv(rhoi, TGiven);
  cp = chem.GetCp(rhoi, TGiven);
  gamma = cp/cv;
  
  //compute mol fractions and MW_mix
  double MWmix = 0.0;
  std::cout << "\nMole fractions" << std::endl;
  std::cout << "========================= " << std::endl;
  double massfrac[chem.nspecies];
  for(int i = 0; i < chem.nspecies; ++i){
    massfrac[i] = param.massfractions[i];
  }
  chem.MassFractionToMoleFraction(massfrac, molfrac);
  for(int i = 0; i < chem.nspecies; ++i){
    MWmix += molfrac[i] * chem.species[i].MW;
    std::cout << "xi[" << chem.species[i].symbol << "]: " << molfrac[i] << std::endl;
  }
  std::cout << "\nMass fractions" << std::endl;
  std::cout << "========================= " << std::endl;
  for(int i = 0; i < chem.nspecies; ++i){
    std::cout << "Yi[" << chem.species[i].symbol << "]: " << param.massfractions[i] << std::endl;
  }
  std::cout << std::endl;

  std::cout << "Mixture properties at " << TGiven << " (K)" << std::endl;
  std::cout << "=======================================" << std::endl;

  std::cout << "rho: " << rho << " kg/m^3" << std::endl;
  std::cout << "Rmix: " << R << " J/kg.K" << std::endl;
  std::cout << "Static pressure (EOS only): " << P << " Pa" << std::endl;
  std::cout << "cvmix: " << cv << " (J/kg.K)" << std::endl;
  std::cout << "cpmix: " << cp << " (J/kg.K)" << std::endl;
  std::cout << "mwmix: " << MWmix << " (kg/mol)" << std::endl;
  std::cout << "gammamix: " << gamma << std::endl;
  std::cout << "Thermal conductivity: " << chem.GetThermalConductivity(rhoi, TGiven) << " (W/m.K)" << std::endl;
  std::cout << "Viscosity: " << chem.GetThermalConductivity(rhoi, TGiven) << " (Pa.s)" << std::endl;
  double c = sqrt(gamma*R*TGiven);
  std::cout << "c (speed of sound): " << c << " m/s" << std::endl;
  double u = param.flowdir[0]*param.GetVelocity(1)*param.ref_velocity;
  double v = param.flowdir[1]*param.GetVelocity(1)*param.ref_velocity;
  double w = param.flowdir[2]*param.GetVelocity(1)*param.ref_velocity;
  double v2 = u*u + v*v + w*w;
  std::cout << "U: " << u  << " m/s" << std::endl;
  std::cout << "V: " << v  << " m/s" << std::endl;
  std::cout << "W: " << w  << " m/s" << std::endl;
  std::cout << "Mach: " << sqrt(v2/(c*c)) << std::endl;
  double Ht = rho*chem.GetSpecificEnthalpy(X, TGiven, hi) + 0.5*rho*v2;
  double Et = rho*chem.GetSpecificEnthalpy(X, TGiven, hi) - P + 0.5*rho*v2;
  std::cout << "Total enthalpy: " << Ht/1000.0 << " (kJ)" << std::endl;
  std::cout << "Total energy: " << Et/1000.0 <<  " (kJ)" << std::endl;
  std::cout << "Total internal energy: " << (Et - 0.5*rho*v2)/1000.0 <<  " (kJ)" << std::endl;
  
  std::cout << "Total pressure (gamma-1.0 formula): " << ((gamma - 1.0)*(Et - 0.5*rho*v2)/param.ref_enthalpy)*
    param.ref_pressure << " Pa" << std::endl;
  std::cout << "Total temperature (gamma-1.0 formula): " << TGiven*(1.0  + (gamma-1.0)/2.0*(v2/(c*c))) << " (K) " << std::endl;
    
  std::cout << "\nAt given temperature of " << TGiven << "K production rates are: " << std::endl;
  std::cout << "===================================================" << std::endl;
  chem.GetMassProductionRates(rhoi, TGiven, wdot);
  for(i = 0; i < chem.nspecies; i++){
    std::cout << chem.species[i].symbol << ": " << wdot[i] << " kg/(m^3 s)" << std::endl;
  }
  
  Real sum = 0.0;
  for(i = 0; i < chem.nspecies; i++){
    sum += wdot[i];
  }
  std::cout << "Mass blanance: " << sum << " kg/(m^3 s)" << std::endl;

  std::cout << "\nDerivatives at given temp: " << TGiven << std::endl;
  std::cout << "===================================================" << std::endl;
  double* dEtdRhoi = new double[chem.nspecies];
  double Pt = chem.GetP(rhoi, TGiven);
  double dEtdP = chem.dEtdP_dEtdRhoi(rhoi, TGiven, Pt, v2, dEtdRhoi);
  std::cout << "dEtdP: " << dEtdP << std::endl;
  for(Int i = 0; i < chem.nspecies; i++){
    std::cout << "dEtdrho[" << i << "]: " << dEtdRhoi[i] << std::endl;
  }

#if 0
  //temporal loop to compute change in makeup over time
  double dt = 0.0001;
  double volume = 1.0; //m^3
  Real* source = new Real[chem.nspecies];
  Real* Y = new Real[chem.nspecies];
  P = Pt;
  Real tol = 1.0e-12;
  Real T = TGiven;
  for(i = 0; i < 20; ++i){
    std::cout << dt*i << " ----------------------------------------------" << std::endl;
    std::cout << "Temp: " << T << std::endl;
    chem.GetMassProductionRates(rhoi, T, wdot);
    for(int is = 0; is < chem.nspecies; ++is){
      source[is] = wdot[is]*volume*dt;
      std::cout << "s: " << source[is] << std::endl;
    }

    //update the masses/densities given the source term (production/destruction)
    rho = 0.0;
    R = 0.0;
    for(int is = 0; is < chem.nspecies; ++is){
      Real mass = rhoi[is]*volume + source[is];
      rhoi[is] = mass/volume;
      rho += rhoi[is];
      R += rhoi[is]*chem.species[is].R;
    }
    std::cout << "Rho: " << rho << std::endl;
    // R is dimensional after this
    R /= rho;
    for(int is = 0; is < chem.nspecies; ++is){
      Y[is] = rhoi[is]/rho;
      std::cout << "y: " << Y[is] << std::endl;
    }
    
    int j = 0;
    Int maxit = 30;
    Real dT = 0.0;
    //todo: check if this is correct
    Real res = Et - 0.5*rho*v2;
    for(j = 0; j < maxit; j++){
      Real Tp = T + 1.0e-8;
      Real H = rho*(chem.GetSpecificEnthalpy(Y, T, hi));
      Real Hp = rho*(chem.GetSpecificEnthalpy(Y, Tp, hi));
      Real P = chem.eos->GetP(R, rho, T);
      Real Pp = chem.eos->GetP(R, rho, Tp);
      Real E = H - P;
      Real Ep = Hp - Pp;
      Real zpoint = res - E;
      Real zpointp = res - Ep;
      Real dzdT = (zpointp - zpoint)/(Tp - T);
      dT = -zpoint/dzdT;
      T += dT;
      if (real(CAbs(dT)) < real(tol)) break;
    }

    if(j == maxit){
      std::cerr << "WARNING: Newton iteration did not converge on a temperature in ConservativeToNative()" 
		<< std::endl;
      std::cerr << "Last dT = " << dT << std::endl;
    }
    
  }
  delete [] source;
  delete [] Y;
#endif
  
  delete [] dEtdRhoi;
  delete [] rhoi;
  delete [] wdot;
  delete [] molfrac;

  return(ierr);
}
Ejemplo n.º 3
0
  void MoleFractionsDirichletBCFactory::add_mole_frac_to_mass_frac(const GetPot& input,
                                                                   const std::string& section,
                                                                   const std::set<std::string>& vars_found,
                                                                   const std::string& material,
                                                                   const SpeciesMassFractionsVariable& species_fe_var,
                                                                   libMesh::CompositeFunction<libMesh::Number>& composite_func,
                                                                   std::set<std::string>& vars_added) const
  {
    unsigned int n_vars_found = vars_found.size();

    // Parse in all the species mole fracs that are in the input (it is assumed non-specified are 0)
    std::vector<libMesh::Number> species_mole_fracs(n_vars_found);
    libMesh::Number invalid_num = std::numeric_limits<libMesh::Number>::max();
    {
      unsigned int count = 0;
      for(std::set<std::string>::const_iterator var = vars_found.begin();
          var != vars_found.end(); ++var )
        {
          species_mole_fracs[count] = input(section+"/"+(*var),invalid_num);
          count++;
        }
    }

    // Make sure mole fracs sum to 1
    libMesh::Number sum = 0.0;
    for(unsigned int v = 0; v < n_vars_found; v++ )
      sum += species_mole_fracs[v];

    libMesh::Number tol = std::numeric_limits<libMesh::Number>::epsilon()*10;
    if( std::abs(sum-1.0) > tol )
      libmesh_error_msg("ERROR: Mole fractions do not sum to 1! Found sum = "+StringUtilities::T_to_string<libMesh::Number>(sum));

    // Extract species names
    std::vector<std::string> species_names(n_vars_found);
    {
      unsigned int count = 0;
      for(std::set<std::string>::const_iterator var = vars_found.begin();
          var != vars_found.end(); ++var )
        {
          std::vector<std::string> split_name;
          // vars_found should have the form "X_<species name>"
          StringUtilities::split_string((*var),"_",split_name);
          libmesh_assert_equal_to(split_name[0],std::string("X"));
          libmesh_assert_equal_to(split_name.size(),2);
          species_names[count] = split_name[1];
          count++;
        }
    }

    // Now convert to mass frac and add to composite function
    /*! \todo We should have a ChemsitryWarehouse or something to just grab this from one place
      instead of rebuilding. */
    ChemistryType chem(input,material);

    libMesh::Real M = 0.0;
    for(unsigned int v = 0; v < n_vars_found; v++ )
      {
        unsigned int s = chem.species_index(species_names[v]);
        M += species_mole_fracs[v]*chem.M(s);
      }

    const std::string& prefix = species_fe_var.prefix();

    for(unsigned int v = 0; v < n_vars_found; v++ )
      {
        // Finish computing species mass fraction
        unsigned int s = chem.species_index(species_names[v]);
        libMesh::Number species_mass_fracs = species_mole_fracs[v]*chem.M(s)/M;

        // Add the function
        std::vector<VariableIndex> var_idx(1,species_fe_var.species(s));
        libMesh::ConstFunction<libMesh::Number> const_func(species_mass_fracs);
        composite_func.attach_subfunction(const_func,var_idx);

        // Log that we added this variable
        vars_added.insert(prefix+species_names[v]);
      }
  }