GRINS-0.8.0
spectroscopic_absorption_test.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // GRINS - General Reacting Incompressible Navier-Stokes
5 //
6 // Copyright (C) 2014-2017 Paul T. Bauman, Roy H. Stogner
7 // Copyright (C) 2010-2013 The PECOS Development Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the Version 2.1 GNU Lesser General
11 // Public License as published by the Free Software Foundation.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
21 // Boston, MA 02110-1301 USA
22 //
23 //-----------------------------------------------------------------------el-
24 
25 #include "grins_config.h"
26 
27 #ifdef GRINS_HAVE_CPPUNIT
28 
29 #ifdef GRINS_HAVE_ANTIOCH
30 
31 #include <libmesh/ignore_warnings.h>
32 #include <cppunit/extensions/HelperMacros.h>
33 #include <cppunit/TestCase.h>
34 #include <libmesh/restore_warnings.h>
35 
36 #include "test_comm.h"
37 #include "grins_test_paths.h"
38 
40 
41 // GRINS
42 #include "grins/math_constants.h"
43 #include "grins/grins_enums.h"
45 #include "grins/simulation.h"
47 #include "grins/single_variable.h"
51 
52 // libMesh
53 #include "libmesh/parsed_function.h"
54 
55 // Ignore warnings from auto_ptr in CPPUNIT_TEST_SUITE_END()
56 #include <libmesh/ignore_warnings.h>
57 
58 namespace GRINSTesting
59 {
60  class SpectroscopicAbsorptionTest : public CppUnit::TestCase
61  {
62  public:
69 
70  public:
71 
72  void tearDown()
73  {
74  // Clear out the VariableWarehouse so it doesn't interfere with other tests.
76  }
77 
80  {
81  const std::string filename = std::string(GRINS_TEST_UNIT_INPUT_SRCDIR)+"/spectroscopic_absorption_qoi.in";
82  libMesh::Real calc_answer = 0.520403290868787;
83 
84  this->run_test(filename,calc_answer);
85  }
86 
89  {
90  const std::string filename = std::string(GRINS_TEST_UNIT_INPUT_SRCDIR)+"/spectroscopic_absorption_qoi_fine.in";
91  libMesh::Real calc_answer = 0.520403290868787; // same physical conditions as single_elem_mesh, so answer should not change
92 
93  this->run_test(filename,calc_answer);
94  }
95 
96  void param_derivs()
97  {
98  const std::string filename = std::string(GRINS_TEST_UNIT_INPUT_SRCDIR)+"/spectroscopic_absorption_qoi.in";
99  this->init_sim(filename);
100 
101  std::string material = "TestMaterial";
102  std::string hitran_data = "./test_data/CO2_data.dat";
103  std::string hitran_partition = "./test_data/CO2_partition_function.dat";
104  libMesh::Real T_min = 290.0,
105  T_max = 310.0,
106  T_step = 0.01;
107  GRINS::SharedPtr<GRINS::HITRAN> hitran( new GRINS::HITRAN(hitran_data,hitran_partition,T_min,T_max,T_step) );
108 
109  std::string species = "CO2";
110  libMesh::Real thermo_pressure = 5066.25;
111  libMesh::Real nu_desired = 3682.7649;
112  libMesh::Real nu_min = 3682.69;
113  libMesh::Real nu_max = 3682.8;
114  GRINS::ChemistryBuilder chem_builder;
115  libMesh::UniquePtr<GRINS::AntiochChemistry> chem_ptr;
116  chem_builder.build_chemistry(*(_input.get()),material,chem_ptr);
117  GRINS::SharedPtr<GRINS::AntiochChemistry> chem(chem_ptr.release());
118  GRINS::SharedPtr<AbsorptionCoeffTesting<GRINS::AntiochChemistry> > absorb = new AbsorptionCoeffTesting<GRINS::AntiochChemistry>(chem,hitran,nu_min,nu_max,nu_desired,species,thermo_pressure);
119 
120  libMesh::Real T = 300.0;
121  libMesh::Real P = 5066.25;
122 
123  std::vector<libMesh::Real> Y = {0.0763662233, 0.9236337767};
124 
125  for (unsigned int i=0; i<33; ++i)
126  {
127  this->T_param_derivatives(absorb,T,P,Y,i);
128  this->P_param_derivatives(absorb,T,P,Y,i);
129  this->Y_param_derivatives(absorb,T,P,Y,i);
130  }
131  }
132 
134  {
135  const std::string filename = std::string(GRINS_TEST_UNIT_INPUT_SRCDIR)+"/spectroscopic_absorption_qoi.in";
136 
137  // run the Simulation once to ensure everything is initialized and populated
138  this->init_sim(filename);
139  _sim->run();
140 
141  GRINS::MultiphysicsSystem * system = _sim->get_multiphysics_system();
142  GRINS::AssemblyContext * context = libMesh::cast_ptr<GRINS::AssemblyContext*>(system->build_context().release());
143  system->init_context(*context);
144  context->pre_fe_reinit(*system,system->get_mesh().elem_ptr(0));
145 
146  libMesh::QoISet qs;
147  qs.add_index(0);
148 
149  libMesh::DifferentiableQoI * qoi = system->get_qoi();
150  qoi->element_qoi_derivative(*context,qs);
151 
152  this->T_elem_derivative(system,context);
153  this->P_elem_derivative(system,context);
154  this->Y_elem_derivative(system,context);
155  }
156 
157  private:
158  GRINS::SharedPtr<GRINS::Simulation> _sim;
159  GRINS::SharedPtr<GetPot> _input;
160 
162  void run_test(const std::string filename, libMesh::Real calc_answer)
163  {
164  this->init_sim(filename);
165 
166  _sim->run();
167 
168  CPPUNIT_ASSERT_DOUBLES_EQUAL( calc_answer, _sim->get_qoi_value(0),libMesh::TOLERANCE );
169  }
170 
172  void init_sim(const std::string & filename)
173  {
174  _input.reset(new GetPot(filename));
175 
176  const char * const argv = "unit_driver";
177  GetPot empty_command_line( (const int)1,&argv );
178  GRINS::SimulationBuilder sim_builder;
179 
180  _sim = new GRINS::Simulation(*_input,
181  empty_command_line,
182  sim_builder,
183  *TestCommWorld );
184  }
185 
186  void T_param_derivatives(GRINS::SharedPtr<AbsorptionCoeffTesting<GRINS::AntiochChemistry> >absorb, libMesh::Real T, libMesh::Real P, std::vector<libMesh::Real> & Y, unsigned int i)
187  {
188  libMesh::Real delta = 1.0e-6;
189 
190  std::vector<libMesh::Real> T_analytic;
191  T_analytic.push_back(absorb->dS_dT(T,P,i));
192  T_analytic.push_back(absorb->d_nuC_dT(T,P,Y,i));
193  T_analytic.push_back(absorb->d_nuD_dT(T,P,i));
194  T_analytic.push_back(absorb->d_voigt_a_dT(T,P,Y,i));
195  T_analytic.push_back(absorb->d_voigt_w_dT(T,P,i));
196  T_analytic.push_back(absorb->d_voigt_dT(T,P,Y,i));
197  T_analytic.push_back(absorb->d_kv_dT(T,P,Y,i));
198 
199  std::vector<libMesh::Real> fd_plus;
200  fd_plus.push_back(absorb->Sw(T+delta,P,i));
201  fd_plus.push_back(absorb->nu_C(T+delta,P,Y,i));
202  fd_plus.push_back(absorb->nu_D(T+delta,P,i));
203  fd_plus.push_back(absorb->voigt_a(T+delta,P,Y,i));
204  fd_plus.push_back(absorb->voigt_w(T+delta,P,i));
205  fd_plus.push_back(absorb->voigt(T+delta,P,Y,i));
206  fd_plus.push_back(absorb->kv(T+delta,P,Y,i));
207 
208  std::vector<libMesh::Real> fd_minus;
209  fd_minus.push_back(absorb->Sw(T-delta,P,i));
210  fd_minus.push_back(absorb->nu_C(T-delta,P,Y,i));
211  fd_minus.push_back(absorb->nu_D(T-delta,P,i));
212  fd_minus.push_back(absorb->voigt_a(T-delta,P,Y,i));
213  fd_minus.push_back(absorb->voigt_w(T-delta,P,i));
214  fd_minus.push_back(absorb->voigt(T-delta,P,Y,i));
215  fd_minus.push_back(absorb->kv(T-delta,P,Y,i));
216 
217  check_param_derivatives(T_analytic,fd_plus,fd_minus,delta);
218  }
219 
220  void P_param_derivatives(GRINS::SharedPtr<AbsorptionCoeffTesting<GRINS::AntiochChemistry> >absorb, libMesh::Real T, libMesh::Real P, std::vector<libMesh::Real> & Y, unsigned int i)
221  {
222  libMesh::Real delta = 1.0e-3;
223 
224  std::vector<libMesh::Real> P_analytic;
225  P_analytic.push_back(absorb->dS_dP(T,P,i));
226  P_analytic.push_back(absorb->d_nuC_dP(T,Y,i));
227  P_analytic.push_back(absorb->d_nuD_dP(T,i));
228  P_analytic.push_back(absorb->d_voigt_a_dP(T,P,Y,i));
229  P_analytic.push_back(absorb->d_voigt_w_dP(T,P,i));
230  P_analytic.push_back(absorb->d_voigt_dP(T,P,Y,i));
231  P_analytic.push_back(absorb->d_kv_dP(T,P,Y,i));
232 
233  std::vector<libMesh::Real> fd_plus;
234  fd_plus.push_back(absorb->Sw(T,P+delta,i));
235  fd_plus.push_back(absorb->nu_C(T,P+delta,Y,i));
236  fd_plus.push_back(absorb->nu_D(T,P+delta,i));
237  fd_plus.push_back(absorb->voigt_a(T,P+delta,Y,i));
238  fd_plus.push_back(absorb->voigt_w(T,P+delta,i));
239  fd_plus.push_back(absorb->voigt(T,P+delta,Y,i));
240  fd_plus.push_back(absorb->kv(T,P+delta,Y,i));
241 
242  std::vector<libMesh::Real> fd_minus;
243  fd_minus.push_back(absorb->Sw(T,P-delta,i));
244  fd_minus.push_back(absorb->nu_C(T,P-delta,Y,i));
245  fd_minus.push_back(absorb->nu_D(T,P-delta,i));
246  fd_minus.push_back(absorb->voigt_a(T,P-delta,Y,i));
247  fd_minus.push_back(absorb->voigt_w(T,P-delta,i));
248  fd_minus.push_back(absorb->voigt(T,P-delta,Y,i));
249  fd_minus.push_back(absorb->kv(T,P-delta,Y,i));
250 
251  check_param_derivatives(P_analytic,fd_plus,fd_minus,delta);
252  }
253 
254  void Y_param_derivatives(GRINS::SharedPtr<AbsorptionCoeffTesting<GRINS::AntiochChemistry> >absorb, libMesh::Real T, libMesh::Real P, std::vector<libMesh::Real> & Y, unsigned int i)
255  {
256  libMesh::Real delta = 1.0e-8;
257 
258  libMesh::Real y_base = Y[0];
259  std::vector<libMesh::Real> Y_analytic;
260  Y_analytic.push_back(absorb->dX_dY(Y));
261  Y_analytic.push_back(absorb->d_nuC_dY(T,P,Y,i));
262  Y_analytic.push_back(absorb->d_voigt_a_dY(T,P,Y,i));
263  Y_analytic.push_back(absorb->d_voigt_dY(T,P,Y,i));
264  Y_analytic.push_back(absorb->d_kv_dY(T,P,Y,i));
265 
266  std::vector<libMesh::Real> fd_plus;
267  Y[0] = y_base + delta;
268  fd_plus.push_back(absorb->_chemistry->X(absorb->_species_idx,absorb->_chemistry->M_mix(Y),Y[absorb->_species_idx]));
269  fd_plus.push_back(absorb->nu_C(T,P,Y,i));
270  fd_plus.push_back(absorb->voigt_a(T,P,Y,i));
271  fd_plus.push_back(absorb->voigt(T,P,Y,i));
272  fd_plus.push_back(absorb->kv(T,P,Y,i));
273 
274  std::vector<libMesh::Real> fd_minus;
275  Y[0] = y_base - delta;
276  fd_minus.push_back(absorb->_chemistry->X(absorb->_species_idx,absorb->_chemistry->M_mix(Y),Y[absorb->_species_idx]));
277  fd_minus.push_back(absorb->nu_C(T,P,Y,i));
278  fd_minus.push_back(absorb->voigt_a(T,P,Y,i));
279  fd_minus.push_back(absorb->voigt(T,P,Y,i));
280  fd_minus.push_back(absorb->kv(T,P,Y,i));
281 
282  Y[0] = y_base;
283 
284  check_param_derivatives(Y_analytic,fd_plus,fd_minus,delta);
285  }
286 
287  void check_param_derivatives(std::vector<libMesh::Real> & analytic, std::vector<libMesh::Real> & fd_plus, std::vector<libMesh::Real> & fd_minus, libMesh::Real delta)
288  {
289  for (unsigned int d=0; d<analytic.size(); ++d)
290  {
291  libMesh::Real f_analytic = analytic[d];
292  libMesh::Real fd_approx = (fd_plus[d] - fd_minus[d])/(2.0*delta);
293 
294  CPPUNIT_ASSERT_DOUBLES_EQUAL(fd_approx,f_analytic,libMesh::TOLERANCE);
295  }
296  }
297 
299  {
300  GRINS::PrimitiveTempFEVariables T_var( GRINS::GRINSPrivate::VariableWarehouse::get_variable_subclass<GRINS::PrimitiveTempFEVariables>("Temperature") );
301  libMesh::Real delta = 1e-6;
302  test_var_elem_derivs(system,context,T_var.T(),delta);
303  }
304 
306  {
307  GRINS::PressureFEVariable P_var( GRINS::GRINSPrivate::VariableWarehouse::get_variable_subclass<GRINS::PressureFEVariable>("Pressure") );
308  libMesh::Real delta = 1e-3;
309  test_var_elem_derivs(system,context,P_var.p(),delta);
310  }
311 
313  {
314  GRINS::SpeciesMassFractionsVariable Y_var( GRINS::GRINSPrivate::VariableWarehouse::get_variable_subclass<GRINS::SpeciesMassFractionsVariable>("SpeciesMassFractions") );
315  libMesh::Real delta = 1e-8;
316  test_var_elem_derivs(system,context,Y_var.species(0),delta);
317  }
318 
319  void test_var_elem_derivs(GRINS::MultiphysicsSystem * system, GRINS::AssemblyContext * context, unsigned int var_index, libMesh::Real delta)
320  {
321  libMesh::DifferentiableQoI * qoi = system->get_qoi();
322  libMesh::Number & qoi_value = context->get_qois()[0];
323  qoi_value = 0.0;
324 
325  libMesh::QoISet qs;
326  qs.add_index(0);
327 
328  libMesh::DenseSubVector<libMesh::Number> deriv = context->get_qoi_derivatives(0,var_index);
329  libMesh::DenseSubVector<libMesh::Number> & solution = context->get_elem_solution(var_index);
330 
331  for (unsigned int d=0; d<solution.size(); ++d)
332  {
333  libMesh::Number soln = solution.el(d);
334 
335  solution(d) = soln+delta;
336  qoi->element_qoi(*context,qs);
337  libMesh::Number qoi_p1 = qoi_value;
338  qoi_value = 0.0;
339 
340  solution(d) = soln-delta;
341  qoi->element_qoi(*context,qs);
342  libMesh::Number qoi_m1= qoi_value;
343  qoi_value = 0.0;
344 
345  solution(d) = soln;
346 
347  libMesh::Real fd_approx = (qoi_p1 - qoi_m1)/(2.0*delta);
348 
349  CPPUNIT_ASSERT_DOUBLES_EQUAL(fd_approx,deriv(d),libMesh::TOLERANCE);
350  }
351  }
352 
353  };
354 
355  CPPUNIT_TEST_SUITE_REGISTRATION( SpectroscopicAbsorptionTest );
356 
357 } // end namespace GRINSTesting
358 
359 #endif // GRINS_HAVE_ANTIOCH
360 #endif // GRINS_HAVE_CPPUNIT
CPPUNIT_TEST_SUITE_REGISTRATION(AntiochAirNASA9ThermoTest)
void Y_param_derivatives(GRINS::SharedPtr< AbsorptionCoeffTesting< GRINS::AntiochChemistry > >absorb, libMesh::Real T, libMesh::Real P, std::vector< libMesh::Real > &Y, unsigned int i)
VariableIndex species(unsigned int species) const
VariableIndex T() const
void P_param_derivatives(GRINS::SharedPtr< AbsorptionCoeffTesting< GRINS::AntiochChemistry > >absorb, libMesh::Real T, libMesh::Real P, std::vector< libMesh::Real > &Y, unsigned int i)
libMesh::Parallel::Communicator * TestCommWorld
Definition: unit_driver.C:70
void test_var_elem_derivs(GRINS::MultiphysicsSystem *system, GRINS::AssemblyContext *context, unsigned int var_index, libMesh::Real delta)
void run_test(const std::string filename, libMesh::Real calc_answer)
Run the test on a given input file and calculated answer.
void check_param_derivatives(std::vector< libMesh::Real > &analytic, std::vector< libMesh::Real > &fd_plus, std::vector< libMesh::Real > &fd_minus, libMesh::Real delta)
VariableIndex p() const
void T_param_derivatives(GRINS::SharedPtr< AbsorptionCoeffTesting< GRINS::AntiochChemistry > >absorb, libMesh::Real T, libMesh::Real P, std::vector< libMesh::Real > &Y, unsigned int i)
void T_elem_derivative(GRINS::MultiphysicsSystem *system, GRINS::AssemblyContext *context)
virtual libMesh::UniquePtr< libMesh::DiffContext > build_context()
Override FEMSystem::build_context in order to use our own AssemblyContext.
HITRAN interface object.
Definition: hitran.h:58
Interface with libMesh for solving Multiphysics problems.
void build_chemistry(const GetPot &input, const std::string &material, libMesh::UniquePtr< ChemistryType > &chem_ptr)
void P_elem_derivative(GRINS::MultiphysicsSystem *system, GRINS::AssemblyContext *context)
static void clear()
Clears the var_map()
void single_elem_mesh()
Single QUAD4 elem, uniform T,P,Y.
void Y_elem_derivative(GRINS::MultiphysicsSystem *system, GRINS::AssemblyContext *context)
virtual void init_context(libMesh::DiffContext &context)
Context initialization. Calls each physics implementation of init_context()
void init_sim(const std::string &filename)
Initialize the GetPot and Simulation class objects.
CPPUNIT_TEST_SUITE(SpectroscopicAbsorptionTest)

Generated on Tue Dec 19 2017 12:47:29 for GRINS-0.8.0 by  doxygen 1.8.9.1