/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . Application chemFoam Description Solver for chemistry problems, designed for use on single cell cases to provide comparison against other chemistry solvers, that uses a single cell mesh, and fields created from the initial conditions. \*---------------------------------------------------------------------------*/ #include #include #include "fvCFD.H" #include "psiReactionThermo.H" #include "psiChemistryModel.H" #include "chemistrySolver.H" #include "OFstream.H" #include "thermoPhysicsTypes.H" #include "basicMultiComponentMixture.H" #include "cellModeller.H" #include "diffusivityModel.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // class LogWriter { OFstream &post_; label errorCount_; label testCount_; scalar relTol_; scalar relError (scalar x, scalar x0) { return (x - x0) / x0; } bool exceedTolerence (scalar rError) { return rError > relTol_ || rError < -relTol_; } public: LogWriter ( OFstream &post , scalar relTol=(10.0/100.) ) : post_(post), errorCount_(0), testCount_(0), relTol_(relTol) {} label numErrors() {return errorCount_;} label numTests() {return testCount_;} bool operator() ( word name, scalar T, scalar ofVal, scalar ctVal ) { if (exceedTolerence(relError(ofVal, ctVal))) { Info << name << ", T = " << T << " relative error = " << (100. * relError(ofVal, ctVal)) << " %"<< endl; errorCount_++; } testCount_++; post_ << T << token::TAB << name << token::TAB << ofVal << token::TAB << ctVal << token::TAB << 100*(relError(ofVal, ctVal)) << endl; return (exceedTolerence(relError(ofVal, ctVal))); } }; int main(int argc, char *argv[]) { argList::noParallel(); argList::addOption ( "relTol", "relTol", "Relative tolerence between Cantera and OpenFOAM calculated values" ); #define CREATE_MESH createSingleCellMesh.H #define NO_CONTROL #include "postProcess.H" #include "setRootCase.H" #include "createTime.H" #include "createSingleCellMesh.H" #include "createFields.H" #include "createFieldRefs.H" #include "readInitialConditions.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // scalar relTol = args.optionLookupOrDefault("relTol", 0.1); LogWriter logWriter (post, relTol); Info<< "\nCreate Cantera object\n" << endl; Cantera::IdealGasMix gas_ ("gri30.xml", "gri30_mix"); Cantera::Transport *tr_ = Cantera::newTransportMgr("Mix", &gas_); label nCanteraSp_ = gas_.nSpecies(); Info<< "\nCreate temperature space\n" << endl; scalarField T(Tn, 0.0); forAll (T, i) { T[i] = i * (Tu - Tl) / scalar(T.size()) + Tl; } // initialize composition array scalarField XY(nCanteraSp_, 0.0); forAll(thermo.composition().species(), i) { XY[i] = Y[i][0]; } Info<< "\nTemperature Loop\n" << endl; forAll(T, i) { // OpenFOAM diffusivity model scalar h0 = 0.0; forAll(Y, k) { h0 += XY[k]*specieData[k].Hs(p[0], T[i]); } thermo.he() = dimensionedScalar("h", dimEnergy/dimMass, h0); thermo.correct(); diff.correct(); scalarField DijO (diff.Dbinary(thermo.T()[0], p[0], XY)); // Cantera gas transport gas_.setState_TPY(thermo.T()[0], p[0], XY.data()); scalarField Dc (composition.species().size(), 0.0); scalarField Dij (composition.species().size()*composition.species().size(), 0.0); const scalar relTol = 1.0e-15; // check for singular case (Xi = 1) label idxFracOne = -1; scalar sumX = sum(XY); forAll (XY, k) { if ((sumX-XY[k])/sumX < relTol) { idxFracOne = k; break; } } tr_->getBinaryDiffCoeffs(nCanteraSp_, Dij.data()); if (idxFracOne < 0) { tr_->getMixDiffCoeffsMass(Dc.data()); } else { forAll(Dc, k) { Dc[k] = Dij[nCanteraSp_*idxFracOne+k]; } } scalarField kSp (diff.kpure(thermo.T()[0], p[0], XY)); scalarField muSpO (diff.mupure(thermo.T()[0], p[0], XY)); scalarField muSpC (kSp); tr_->getSpeciesViscosities(muSpC.data()); forAll(thermo.composition().species(), k) { logWriter ( thermo.composition().species()[k], thermo.T()[0], diff.D(k)[0], Dc[k] ) ; } forAll(thermo.composition().species(), k) { forAll(thermo.composition().species(), j) { logWriter ( thermo.composition().species()[k] + "=>" + thermo.composition().species()[j], thermo.T()[0], DijO[nCanteraSp_*k+j], Dij[nCanteraSp_*k+j] ) ; } } logWriter ( "mu", thermo.T()[0], diff.mu()[0], tr_->viscosity() ) ; forAll(thermo.composition().species(), k) { logWriter ( "mu_"+thermo.composition().species()[k], thermo.T()[0], muSpO[k], muSpC[k] ) ; } logWriter ( "k", thermo.T()[0], diff.k()[0], tr_->thermalConductivity() ) ; forAll(thermo.composition().species(), k) { scalarField YY(XY); YY = 0.0; YY[k] = 1.0; gas_.setState_TPY(thermo.T()[0], p[0], YY.data()); logWriter ( "k_"+thermo.composition().species()[k], thermo.T()[0], kSp[k], tr_->thermalConductivity() ) ; } } Info << logWriter.numErrors() << " / " << logWriter.numTests() << " End" << nl << endl; if (logWriter.numErrors() == 0) { return 0; } else { return -1; } } // ************************************************************************* //