GRINS-0.7.0
test_turbulent_channel.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // GRINS - General Reacting Incompressible Navier-Stokes
5 //
6 // Copyright (C) 2014-2016 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 
26 #include "grins_config.h"
27 
28 #include <iostream>
29 
30 // GRINS
31 #include "grins/mesh_builder.h"
32 #include "grins/simulation.h"
34 #include "grins/multiphysics_sys.h"
36 #include "grins/var_typedefs.h"
37 
38 //libMesh
39 #include "libmesh/dirichlet_boundaries.h"
40 #include "libmesh/dof_map.h"
41 #include "libmesh/fe_base.h"
42 #include "libmesh/fe_interface.h"
43 #include "libmesh/mesh_function.h"
44 #include "libmesh/serial_mesh.h"
45 #include "libmesh/edge_edge2.h"
46 #include "libmesh/mesh_generation.h"
47 #include "libmesh/linear_implicit_system.h"
48 #include "libmesh/gmv_io.h"
49 #include "libmesh/exact_solution.h"
50 #include "libmesh/zero_function.h"
51 #include "libmesh/composite_function.h"
52 #include "libmesh/zero_function.h"
53 
54 // GRVY
55 #ifdef GRINS_HAVE_GRVY
56 #include "grvy.h"
57 #endif
58 
59 namespace GRINS
60 {
61  class MultiphysicsSystem;
62 }
63 
64 void test_error_norm( libMesh::ExactSolution& exact_sol,
65  const std::string& system_name,
66  const std::string& var,
67  const std::string& norm,
68  const double tol,
69  int& return_flag );
70 
71 namespace GRINSTesting
72 {
73 
74  class TurbBoundFuncBase : public libMesh::FunctionBase<libMesh::Number>
75  {
76  public:
77  TurbBoundFuncBase (libMesh::MeshFunction* turbulent_bc_values)
78  : _turbulent_bc_values(turbulent_bc_values)
79  { this->_initialized = true; }
80 
81  virtual libMesh::Number operator() (const libMesh::Point&, const libMesh::Real = 0)
82  { libmesh_not_implemented(); }
83 
84  virtual libMesh::Number compute_final_value( const libMesh::DenseVector<libMesh::Number>& u_nu_values ) =0;
85 
86  virtual void operator() (const libMesh::Point& p,
87  const libMesh::Real t,
88  libMesh::DenseVector<libMesh::Number>& output)
89  {
90  output.resize(1);
91  output.zero();
92 
93  // Since the turbulent_bc_values object has a solution from a 1-d problem, we have to zero out the y coordinate of p
94  libMesh::Point p_copy(p);
95  // Also, the 1-d solution provided is on the domain [0, 1] on the x axis and we need to map this to the corresponding point on the y axis
96  p_copy(0) = p_copy(1);
97  p_copy(1)= 0.0;
98  // Also, the 1-d solution provided is actually a symmetry solution, so we have to make the following map
99  // x_GRINS < 0.5 => x_meshfunction = 2*x_GRINS , x_GRINS >= 0.5 => x_GRINS = 1 - x_GRINS, x_meshfunction = 2*x_GRINS
100  if(p_copy(0) > 0.5)
101  {
102  p_copy(0) = 1 - p_copy(0);
103  }
104  p_copy(0) = 2*p_copy(0);
105 
106  libMesh::DenseVector<libMesh::Number> u_nu_values;
107  _turbulent_bc_values->operator()(p_copy, t, u_nu_values);
108 
109  output(0) = this->compute_final_value(u_nu_values);
110  }
111 
112  protected:
113 
114  libMesh::MeshFunction* _turbulent_bc_values;
115 
116  };
117 
118  // Class to construct the Dirichlet boundary object and operator for the inlet u velocity and nu profiles
120  {
121  public:
122  TurbulentBdyFunctionU (libMesh::MeshFunction* turbulent_bc_values)
123  : TurbBoundFuncBase(turbulent_bc_values)
124  {}
125 
126  virtual libMesh::Number compute_final_value( const libMesh::DenseVector<libMesh::Number>& u_nu_values )
127  { return u_nu_values(0)/21.995539; }
128 
129  virtual libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> > clone() const
130  { return libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> > (new TurbulentBdyFunctionU(_turbulent_bc_values)); }
131  };
132 
133  // Class to construct the Dirichlet boundary object and operator for the inlet u velocity and nu profiles
135  {
136  public:
137  TurbulentBdyFunctionNu (libMesh::MeshFunction* turbulent_bc_values)
138  : TurbBoundFuncBase(turbulent_bc_values)
139  {}
140 
141  virtual libMesh::Number compute_final_value( const libMesh::DenseVector<libMesh::Number>& u_nu_values )
142  { return u_nu_values(1)/(2.0*21.995539); }
143 
144  virtual libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> > clone() const
145  { return libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> > (new TurbulentBdyFunctionNu(_turbulent_bc_values)); }
146 
147  };
148 
149  class SATurbBCFactoryBase : public GRINS::DirichletBCFactoryFunctionBase<libMesh::FunctionBase<libMesh::Number> >
150  {
151  public:
152  SATurbBCFactoryBase( const std::string& bc_type_name )
153  : DirichletBCFactoryFunctionBase<libMesh::FunctionBase<libMesh::Number> >(bc_type_name)
154  {}
155 
156  static void set_turb_bc_values( libMesh::MeshFunction* turbulent_bc_values )
157  { _turbulent_bc_values = turbulent_bc_values; }
158 
159  protected:
160 
161  static libMesh::MeshFunction* _turbulent_bc_values;
162  };
163 
164  libMesh::MeshFunction* SATurbBCFactoryBase::_turbulent_bc_values = NULL;
165 
167  {
168  public:
169 
170  SATurbUBCFactory( const std::string& bc_type_name )
171  : SATurbBCFactoryBase(bc_type_name)
172  {}
173 
174  protected:
175 
176  virtual libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> >
177  build_func( const GetPot& /*input*/,
179  std::vector<std::string>& var_names,
180  const std::string& /*section*/ )
181  {
182  libmesh_assert_equal_to(var_names.size(), 2);
183  libmesh_assert_equal_to(var_names[0], std::string("u"));
184  libmesh_assert_equal_to(var_names[1], std::string("v"));
185 
186  libMesh::UniquePtr<libMesh::CompositeFunction<libMesh::Number> >
187  composite_func( new libMesh::CompositeFunction<libMesh::Number> );
188 
189  libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> >
191 
192  std::vector<GRINS::VariableIndex> vars(1);
193  vars[0] = system.variable_number(var_names[0]);
194  composite_func->attach_subfunction(*bound_func, vars);
195 
196  vars[0] = system.variable_number(var_names[1]);
197  composite_func->attach_subfunction(libMesh::ZeroFunction<libMesh::Number>(), vars);
198 
199  return libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> >( composite_func.release() );
200  }
201  };
202 
204  {
205  public:
206 
207  SATurbNuBCFactory( const std::string& bc_type_name )
208  : SATurbBCFactoryBase(bc_type_name)
209  {}
210 
211  protected:
212 
213  virtual libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> >
214  build_func( const GetPot& /*input*/,
216  std::vector<std::string>& var_names,
217  const std::string& /*section*/ )
218  {
219  libmesh_assert_equal_to(var_names.size(), 1);
220  libmesh_assert_equal_to(var_names[0], std::string("nu"));
221 
222  libMesh::UniquePtr<libMesh::CompositeFunction<libMesh::Number> >
223  composite_func( new libMesh::CompositeFunction<libMesh::Number> );
224 
225  libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> >
226  bound_func( new TurbulentBdyFunctionNu(_turbulent_bc_values) );
227 
228  std::vector<GRINS::VariableIndex> vars(1);
229  vars[0] = system.variable_number(var_names[0]);
230  composite_func->attach_subfunction(*bound_func, vars);
231 
232  return libMesh::UniquePtr<libMesh::FunctionBase<libMesh::Number> >( composite_func.release() );
233  }
234  };
235 
236  SATurbUBCFactory grins_factory_testing_turb_u_bc("testing_turb_u");
237  SATurbNuBCFactory grins_factory_testing_turb_nu_bc("testing_turb_nu");
238 
239 } // end namespace GRINSTesting
240 
241 int main(int argc, char* argv[])
242 {
243 
244 #ifdef GRINS_USE_GRVY_TIMERS
245  GRVY::GRVY_Timer_Class grvy_timer;
246  grvy_timer.Init("GRINS Timer");
247 #endif
248 
249  // Check command line count.
250  if( argc < 2 )
251  {
252  // TODO: Need more consistent error handling.
253  std::cerr << "Error: Must specify libMesh input file." << std::endl;
254  exit(1); // TODO: something more sophisticated for parallel runs?
255  }
256 
257  // libMesh input file should be first argument
258  std::string libMesh_input_filename = argv[1];
259 
260  // Create our GetPot object.
261  GetPot libMesh_inputfile( libMesh_input_filename );
262 
263 #ifdef GRINS_USE_GRVY_TIMERS
264  grvy_timer.BeginTimer("Initialize Solver");
265 #endif
266 
267  // Initialize libMesh library.
268  libMesh::LibMeshInit libmesh_init(argc, argv);
269 
270  // Build a 1-d turbulent_bc_system to get the bc data from files
271  libMesh::SerialMesh mesh(libmesh_init.comm());
272 
273  GetPot command_line(argc,argv);
274 
275  std::string oned_mesh = command_line("mesh-1d", "DIE!");
276  mesh.read(oned_mesh);
277 
278  // And an EquationSystems to run on it
279  libMesh::EquationSystems equation_systems (mesh);
280 
281  std::string oned_data = command_line("data-1d", "DIE!");
282  equation_systems.read(oned_data, libMesh::XdrMODE::READ,
283  libMesh::EquationSystems::READ_HEADER |
284  libMesh::EquationSystems::READ_DATA |
285  libMesh::EquationSystems::READ_ADDITIONAL_DATA);
286 
287  // Get a reference to the system so that we can call update() on it
288  libMesh::System & turbulent_bc_system = equation_systems.get_system<libMesh::System>("flow");
289 
290  // We need to call update to put system in a consistent state
291  // with the solution that was read in
292  turbulent_bc_system.update();
293 
294  // Print information about the system to the screen.
295  equation_systems.print_info();
296 
297  // Prepare a global solution and a MeshFunction of the Turbulent system
298  libMesh::UniquePtr<libMesh::MeshFunction> turbulent_bc_values;
299 
300  libMesh::UniquePtr<libMesh::NumericVector<libMesh::Number> > turbulent_bc_soln = libMesh::NumericVector<libMesh::Number>::build(equation_systems.comm());
301 
302  std::vector<libMesh::Number> flow_soln;
303 
304  turbulent_bc_system.update_global_solution(flow_soln);
305 
306  turbulent_bc_soln->init(turbulent_bc_system.solution->size(), true, libMesh::SERIAL);
307 
308  (*turbulent_bc_soln) = flow_soln;
309 
310  std::vector<unsigned int>turbulent_bc_system_variables;
311  turbulent_bc_system_variables.push_back(0);
312  turbulent_bc_system_variables.push_back(1);
313 
314  turbulent_bc_values = libMesh::UniquePtr<libMesh::MeshFunction>
315  (new libMesh::MeshFunction(equation_systems,
316  *turbulent_bc_soln,
317  turbulent_bc_system.get_dof_map(),
318  turbulent_bc_system_variables ));
319 
320  turbulent_bc_values->init();
321 
322  GRINSTesting::SATurbBCFactoryBase::set_turb_bc_values( turbulent_bc_values.get() );
323 
324  GRINS::SimulationBuilder sim_builder;
325 
326  GRINS::Simulation grins( libMesh_inputfile,
327  sim_builder,
328  libmesh_init.comm() );
329 
330 #ifdef GRINS_USE_GRVY_TIMERS
331  grvy_timer.EndTimer("Initialize Solver");
332 
333  // Attach GRVY timer to solver
334  grins.attach_grvy_timer( &grvy_timer );
335 #endif
336 
337  // Solve
338  grins.run();
339 
340 // Get equation systems to create ExactSolution object
341  GRINS::SharedPtr<libMesh::EquationSystems> es = grins.get_equation_system();
342 
343  // Create Exact solution object and attach exact solution quantities
344  //libMesh::ExactSolution exact_sol(*es);
345 
346  // Create Exact solution object and attach exact solution quantities
347  libMesh::ExactSolution exact_sol(*es);
348 
349  libMesh::EquationSystems es_ref( es->get_mesh() );
350 
351  // Filename of file where comparison solution is stashed
352  std::string solution_file = command_line("soln-data", "DIE!");
353  es_ref.read( solution_file, libMesh::XdrMODE::DECODE,
354  libMesh::EquationSystems::READ_HEADER |
355  libMesh::EquationSystems::READ_DATA |
356  libMesh::EquationSystems::READ_ADDITIONAL_DATA);
357 
358  exact_sol.attach_reference_solution( &es_ref );
359 
360  // Now grab the variables for which we want to compare
361  unsigned int n_vars = command_line.vector_variable_size("vars");
362  std::vector<std::string> vars(n_vars);
363  for( unsigned int v = 0; v < n_vars; v++ )
364  {
365  vars[v] = command_line("vars", "DIE!", v);
366  }
367 
368  // Now grab the norms to compute for each variable error
369  unsigned int n_norms = command_line.vector_variable_size("norms");
370  std::vector<std::string> norms(n_norms);
371  for( unsigned int n = 0; n < n_norms; n++ )
372  {
373  norms[n] = command_line("norms", "DIE!", n);
374  if( norms[n] != std::string("L2") &&
375  norms[n] != std::string("H1") )
376  {
377  std::cerr << "ERROR: Invalid norm input " << norms[n] << std::endl
378  << " Valid values are: L2" << std::endl
379  << " H1" << std::endl;
380  }
381  }
382 
383  const std::string& system_name = grins.get_multiphysics_system_name();
384 
385  // Now compute error for each variable
386  for( unsigned int v = 0; v < n_vars; v++ )
387  {
388  exact_sol.compute_error(system_name, vars[v]);
389  }
390 
391  int return_flag = 0;
392 
393  double tol = command_line("tol", 1.0e-10);
394 
395  // Now test error for each variable, for each norm
396  for( unsigned int v = 0; v < n_vars; v++ )
397  {
398  for( unsigned int n = 0; n < n_norms; n++ )
399  {
400  test_error_norm( exact_sol, system_name, vars[v], norms[n], tol, return_flag );
401  }
402  }
403 
404  return return_flag;
405 }
406 
407 void test_error_norm( libMesh::ExactSolution& exact_sol,
408  const std::string& system_name,
409  const std::string& var,
410  const std::string& norm,
411  const double tol,
412  int& return_flag )
413 {
414  // We don't set return_flag unless we are setting it 1
415  // since this function gets called multiple times and we don't
416  // want to overwrite a previous "fail" (return_flag = 1) with
417  // a "pass" (return_flag = 0)
418 
419  double error = 0.0;
420 
421  std::cout << "==========================================================" << std::endl
422  << "Checking variable " << var << " using error norm " << norm << " with tol " << tol << "...";
423 
424  if( norm == std::string("L2") )
425  {
426  error = exact_sol.l2_error(system_name, var);
427  }
428  else if( norm == std::string("H1") )
429  {
430  error = exact_sol.h1_error(system_name, var);
431  }
432  else
433  {
434  std::cerr << "ERROR: Invalid norm " << norm << std::endl;
435  exit(1);
436  }
437 
438  if( error > tol )
439  {
440  return_flag = 1;
441 
442  std::cerr << "Tolerance exceeded for generic regression test!" << std::endl
443  << "tolerance = " << tol << std::endl
444  << "norm of error = " << error << std::endl
445  << "norm type = " << norm << std::endl
446  << "var = " << var << std::endl;
447  }
448  else
449  {
450  std::cout << "PASSED!" << std::endl
451  << "==========================================================" << std::endl;
452  }
453 
454  return;
455 }
SATurbBCFactoryBase(const std::string &bc_type_name)
SATurbUBCFactory grins_factory_testing_turb_u_bc("testing_turb_u")
TurbBoundFuncBase(libMesh::MeshFunction *turbulent_bc_values)
virtual libMesh::UniquePtr< libMesh::FunctionBase< libMesh::Number > > build_func(const GetPot &, GRINS::MultiphysicsSystem &system, std::vector< std::string > &var_names, const std::string &)
Builds the FunctionBase object for boundary condition.
SATurbNuBCFactory grins_factory_testing_turb_nu_bc("testing_turb_nu")
virtual libMesh::UniquePtr< libMesh::FunctionBase< libMesh::Number > > clone() const
libMesh::MeshFunction * _turbulent_bc_values
virtual libMesh::UniquePtr< libMesh::FunctionBase< libMesh::Number > > build_func(const GetPot &, GRINS::MultiphysicsSystem &system, std::vector< std::string > &var_names, const std::string &)
Builds the FunctionBase object for boundary condition.
virtual libMesh::Number operator()(const libMesh::Point &, const libMesh::Real=0)
virtual libMesh::UniquePtr< libMesh::FunctionBase< libMesh::Number > > clone() const
virtual libMesh::Number compute_final_value(const libMesh::DenseVector< libMesh::Number > &u_nu_values)
static libMesh::MeshFunction * _turbulent_bc_values
GRINS namespace.
SATurbNuBCFactory(const std::string &bc_type_name)
TurbulentBdyFunctionU(libMesh::MeshFunction *turbulent_bc_values)
void test_error_norm(libMesh::ExactSolution &exact_sol, const std::string &system_name, const std::string &var, const std::string &norm, const double tol, int &return_flag)
virtual libMesh::Number compute_final_value(const libMesh::DenseVector< libMesh::Number > &u_nu_values)=0
Interface with libMesh for solving Multiphysics problems.
static void set_turb_bc_values(libMesh::MeshFunction *turbulent_bc_values)
TurbulentBdyFunctionNu(libMesh::MeshFunction *turbulent_bc_values)
SATurbUBCFactory(const std::string &bc_type_name)
int main(int argc, char *argv[])
virtual libMesh::Number compute_final_value(const libMesh::DenseVector< libMesh::Number > &u_nu_values)

Generated on Thu Jun 2 2016 21:52:28 for GRINS-0.7.0 by  doxygen 1.8.10