antioch-0.4.0
chem_mixture_unit.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // Antioch - A Gas Dynamics Thermochemistry Library
5 //
6 // Copyright (C) 2014-2016 Paul T. Bauman, Benjamin S. Kirk,
7 // Sylvain Plessis, Roy H. Stonger
8 //
9 // Copyright (C) 2013 The PECOS Development Team
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the Version 2.1 GNU Lesser General
13 // Public License as published by the Free Software Foundation.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
23 // Boston, MA 02110-1301 USA
24 //
25 //-----------------------------------------------------------------------el-
26 //
27 // $Id$
28 //
29 //--------------------------------------------------------------------------
30 //--------------------------------------------------------------------------
31 
32 // C++
33 #include <cmath>
34 #include <iomanip>
35 #include <limits>
36 #include <vector>
37 
38 // Antioch
39 #include "antioch/vector_utils.h"
40 
44 
45 template <typename Scalar>
46 int test_species( const unsigned int species,
47  const std::vector<Antioch::ChemicalSpecies<Scalar>*>& chemical_species,
48  const std::string& species_name,
49  Scalar molar_mass, Scalar gas_constant, Scalar formation_enthalpy,
50  Scalar n_tr_dofs, int charge,
51  const Scalar tol )
52 {
53 
54  int return_flag = 0;
55 
56  const Antioch::ChemicalSpecies<Scalar>& chem_species = *(chemical_species[species]);
57 
58  if( chem_species.species() != species_name )
59  {
60  std::cerr << "Error: Name mismatch for "<< species_name << std::endl
61  << "name = " << chem_species.species() << std::endl;
62  return_flag = 1;
63  }
64 
65  if( std::abs(chem_species.molar_mass() - molar_mass)/molar_mass > tol )
66  {
67  std::cerr << "Error: Molar mass mismatch for "<< species_name << std::endl
68  << "molar mass = " << chem_species.molar_mass() << std::endl;
69  return_flag = 1;
70  }
71 
72  if( std::abs(chem_species.gas_constant() - gas_constant)/gas_constant > tol )
73  {
74  std::cerr << "Error: Gas constant mismatch for "<< species_name << std::endl
75  << "gas constant = " << chem_species.gas_constant() << std::endl;
76  return_flag = 1;
77  }
78 
79  if( std::abs(chem_species.formation_enthalpy() - formation_enthalpy)/formation_enthalpy > tol )
80  {
81  std::cerr << "Error: Formation enthalpy mismatch for "<< species_name << std::endl
82  << "formation enthalpy = " << chem_species.formation_enthalpy() << std::endl;
83  return_flag = 1;
84  }
85 
86  if( chem_species.n_tr_dofs() != n_tr_dofs )
87  {
88  std::cerr << "Error: Number translational DoFs mismatch for "<< species_name << std::endl
89  << "n_tr_dofs = " << chem_species.n_tr_dofs() << std::endl;
90  return_flag = 1;
91  }
92 
93  if( chem_species.charge() != charge )
94  {
95  std::cerr << "Error: Charge mismatch for "<< species_name << std::endl
96  << "charge = " << chem_species.charge() << std::endl;
97  return_flag = 1;
98  }
99 
100  return return_flag;
101 }
102 
103 
104 template <typename Scalar>
105 int tester()
106 {
107  using std::abs;
108 
109  std::vector<std::string> species_str_list;
110  const unsigned int n_species = 5;
111  species_str_list.reserve(n_species);
112  species_str_list.push_back( "N2" );
113  species_str_list.push_back( "O2" );
114  species_str_list.push_back( "N" );
115  species_str_list.push_back( "O" );
116  species_str_list.push_back( "NO" );
117 
118  const Scalar Mm_N = 14.008e-3L;
119  const Scalar Mm_O = 16.000e-3L;
120  const Scalar Mm_N2 = 2.L * Mm_N;
121  const Scalar Mm_O2 = 2.L * Mm_O;
122  const Scalar Mm_NO = Mm_N + Mm_O;
123 
124  Antioch::ChemicalMixture<Scalar> chem_mixture( species_str_list );
125  // testing default
126  Antioch::ChemicalMixture<Scalar> default_mixture;
127  const unsigned int iN2 = default_mixture.species_name_map().at("N2");
128  const unsigned int iO2 = default_mixture.species_name_map().at("O2");
129  const unsigned int iNO = default_mixture.species_name_map().at("NO");
130  const unsigned int iO = default_mixture.species_name_map().at("O");
131  const unsigned int iN = default_mixture.species_name_map().at("N");
132 
133  const std::map<std::string,Antioch::Species>& species_name_map = chem_mixture.species_name_map();
134  const std::map<Antioch::Species,std::string>& species_inverse_name_map = chem_mixture.species_inverse_name_map();
135  const std::vector<Antioch::ChemicalSpecies<Scalar>*>& chemical_species = chem_mixture.chemical_species();
136  const std::vector<Antioch::Species> species_list = chem_mixture.species_list();
137  const std::vector<Antioch::ChemicalSpecies<Scalar>*>& default_species = default_mixture.chemical_species();
138 
139  int return_flag = 0;
140  const Scalar tol = (std::numeric_limits<Scalar>::epsilon() * 10 < 5e-17)?5e-17:
141  std::numeric_limits<Scalar>::epsilon() * 10;
142 
143  // Check name map consistency
144  for( unsigned int i = 0; i < n_species; i++ )
145  {
146  if( species_name_map.find( species_str_list[i] )->second != species_list[i] )
147  {
148  std::cerr << "Error: species name map and species list ordering mismatch" << std::endl
149  << "species_name_map = " << species_name_map.find( species_str_list[i] )->second
150  << ", species_list = " << species_list[i] << std::endl;
151  return_flag = 1;
152  }
153  }
154 
155  // Check inverse name map consistency
156  for( unsigned int i = 0; i < n_species; i++ )
157  {
158  if( species_inverse_name_map.find( species_list[i] )->second != species_str_list[i] )
159  {
160  std::cerr << "Error: species inverse name map and species list ordering mismatch" << std::endl
161  << "species_inverse_name_map = " << species_inverse_name_map.find( species_list[i] )->second
162  << ", species_str_list = " << species_str_list[i] << std::endl;
163  return_flag = 1;
164  }
165  }
166 
167  // Check N2 properties
168  {
169  unsigned int index = 0;
170  Scalar molar_mass = Mm_N2;
171  if( std::abs(molar_mass - chem_mixture.M(index))/molar_mass > tol ||
172  std::abs(molar_mass - default_mixture.M(iN2))/molar_mass > tol)
173  {
174  std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
175  << "molar mass = " << chem_mixture.M(index) << std::endl
176  << "molar mass (default mixture) = " << default_mixture.M(iN2) << std::endl;
177  return_flag = 1;
178  }
179  return_flag = return_flag ||
180  test_species( index, chemical_species, "N2", molar_mass,
181  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
182  Scalar(0.0), Scalar(2.5), Scalar(0), tol) ||
183  test_species( iN2, default_species, "N2", molar_mass,
184  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
185  Scalar(0.0), Scalar(2.5), Scalar(0), tol);
186  }
187 
188  // Check O2 properties
189  {
190  unsigned int index = 1;
191  Scalar molar_mass = Mm_O2;
192  if( std::abs(molar_mass - chem_mixture.M(index)) > tol ||
193  std::abs(molar_mass - default_mixture.M(iO2))/molar_mass > tol)
194  {
195  std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
196  << "molar mass = " << chem_mixture.M(index) << std::endl
197  << "molar mass (default mixture) = " << default_mixture.M(iO2) << std::endl;
198  return_flag = 1;
199  }
200  return_flag = return_flag ||
201  test_species( index, chemical_species, "O2", molar_mass,
202  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
203  Scalar(0.0), Scalar(2.5), Scalar(0), tol) ||
204  test_species( iO2, default_species, "O2", molar_mass,
205  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
206  Scalar(0.0), Scalar(2.5), Scalar(0), tol);
207  }
208 
209  // Check N properties
210  {
211  unsigned int index = 2;
212  Scalar molar_mass = Mm_N;
213  if( std::abs(molar_mass - chem_mixture.M(index)) > tol ||
214  std::abs(molar_mass - default_mixture.M(iN))/molar_mass > tol)
215  {
216  std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
217  << "molar mass = " << chem_mixture.M(index) << std::endl
218  << "molar mass (default mixture) = " << default_mixture.M(iN) << std::endl;
219  return_flag = 1;
220  }
221  return_flag = return_flag ||
222  test_species( index, chemical_species, "N", molar_mass,
223  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
224  Scalar(3.3621610000e7), Scalar(1.5), Scalar(0), tol) ||
225  test_species( iN, default_species, "N", molar_mass,
226  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
227  Scalar(3.3621610000e7), Scalar(1.5), Scalar(0), tol);
228  }
229 
230  // Check O properties
231  {
232  unsigned int index = 3;
233  Scalar molar_mass = Mm_O;
234  if( std::abs(molar_mass - chem_mixture.M(index)) > tol ||
235  std::abs(molar_mass - default_mixture.M(iO)) > tol )
236  {
237  std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
238  << "molar mass = " << chem_mixture.M(index) << std::endl
239  << "molar mass (default mixture) = " << default_mixture.M(iO) << std::endl;
240  return_flag = 1;
241  }
242  return_flag = return_flag ||
243  test_species( index, chemical_species, "O", molar_mass,
244  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
245  Scalar(1.5420000000e7), Scalar(1.5), Scalar(0), tol) ||
246  test_species( iO, default_species, "O", molar_mass,
247  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
248  Scalar(1.5420000000e7), Scalar(1.5), Scalar(0), tol);
249  }
250 
251  // Check NO properties
252  {
253  unsigned int index = 4;
254  Scalar molar_mass = Mm_NO;
255  if( std::abs(molar_mass - chem_mixture.M(index)) > tol ||
256  std::abs(molar_mass - default_mixture.M(iNO)) > tol )
257  {
258  std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
259  << "molar mass = " << chem_mixture.M(index) << std::endl
260  << "molar mass (default mixture) = " << default_mixture.M(iNO) << std::endl;
261  return_flag = 1;
262  }
263  return_flag = return_flag ||
264  test_species( index, chemical_species, "NO", molar_mass,
265  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
266  Scalar(2.9961230000e6), Scalar(2.5), Scalar(0), tol) ||
267  test_species( iNO, default_species, "NO", molar_mass,
268  Scalar(Antioch::Constants::R_universal<Scalar>()/molar_mass),
269  Scalar(2.9961230000e6), Scalar(2.5), Scalar(0), tol);
270  }
271 
272  std::vector<Scalar> mass_fractions( 5, 0.2L );
273 
274  Scalar R_exact = Antioch::Constants::R_universal<Scalar>()*( 0.2L/Mm_N2 + 0.2L/Mm_O2 + 0.2L/Mm_N + 0.2L/Mm_O + 0.2L/Mm_NO );
275  Scalar M_exact = 1.0L/( 0.2L*( 1.0L/Mm_N2 + 1.0L/Mm_O2 + 1.0L/Mm_N + 1.0L/Mm_O + 1.0L/Mm_NO) );
276 
277  std::vector<Scalar> X_exact(5, 0.0L);
278  X_exact[0] = 0.2L*M_exact/Mm_N2;
279  X_exact[1] = 0.2L*M_exact/Mm_O2;
280  X_exact[2] = 0.2L*M_exact/Mm_N;
281  X_exact[3] = 0.2L*M_exact/Mm_O;
282  X_exact[4] = 0.2L*M_exact/Mm_NO;
283 
284  if( abs( (chem_mixture.R(mass_fractions) - R_exact)/R_exact) > tol )
285  {
286  std::cerr << "Error: Mismatch in mixture gas constant." << std::endl
287  << std::setprecision(16) << std::scientific
288  << "R = " << chem_mixture.R(mass_fractions) << std::endl
289  << "R_exact = " << R_exact << std::endl;
290  return_flag = 1;
291  }
292 
293  if( abs( (chem_mixture.M(mass_fractions) - M_exact)/M_exact ) > tol )
294  {
295  std::cerr << "Error: Mismatch in mixture molar mass." << std::endl
296  << std::setprecision(16) << std::scientific
297  << "M = " << chem_mixture.M(mass_fractions) << std::endl
298  << "M_exact = " << M_exact << std::endl;
299  return_flag = 1;
300  }
301 
302  std::vector<Scalar> X(5, 0);
303  chem_mixture.X( chem_mixture.M(mass_fractions), mass_fractions, X );
304  for( unsigned int s = 0; s < 5; s++ )
305  {
306  if( abs( (X[s] - X_exact[s])/X_exact[s]) > tol )
307  {
308  std::cerr << "Error: Mismatch in mole fraction for species " << s << std::endl
309  << std::setprecision(16) << std::scientific
310  << "X = " << X[s] << std::endl
311  << "X_exact = " << X_exact[s] << std::endl;
312  return_flag = 1;
313  }
314  }
315 
316  return return_flag;
317 }
318 
319 
320 int main()
321 {
322  return (tester<double>() ||
323  tester<long double>() ||
324  tester<float>());
325 }
CoeffType formation_enthalpy() const
Returns formation enthalpy in units of [J/kg].
CoeffType R(const unsigned int s) const
Gas constant for species s in [J/kg-K].
const std::vector< Species > & species_list() const
const std::string & species() const
Returns a descriptive name for this species.
CoeffType M(const unsigned int s) const
Molecular weight (molar mass) for species s in kg/mol.
int test_species(const unsigned int species, const std::vector< Antioch::ChemicalSpecies< Scalar > * > &chemical_species, const std::string &species_name, Scalar molar_mass, Scalar gas_constant, Scalar formation_enthalpy, Scalar n_tr_dofs, int charge, const Scalar tol)
const std::map< std::string, Species > & species_name_map() const
Class to encapsulate data for each chemical species.
const std::map< Species, std::string > & species_inverse_name_map() const
int charge() const
Returns electrical charge number.
CoeffType n_tr_dofs() const
Returns number of translational degrees of freedom.
CoeffType gas_constant() const
Returns the species ideal gas constant in [J/kg-K].
Class storing chemical mixture properties.
int tester()
CoeffType molar_mass() const
Returns the molar mass in (kg/mol)
const std::vector< ChemicalSpecies< CoeffType > * > & chemical_species() const
int main()

Generated on Thu Jul 7 2016 11:09:46 for antioch-0.4.0 by  doxygen 1.8.8