GRINS-0.6.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-2015 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 
37 //libMesh
38 #include "libmesh/dirichlet_boundaries.h"
39 #include "libmesh/dof_map.h"
40 #include "libmesh/fe_base.h"
41 #include "libmesh/fe_interface.h"
42 #include "libmesh/mesh_function.h"
43 #include "libmesh/serial_mesh.h"
44 #include "libmesh/edge_edge2.h"
45 #include "libmesh/mesh_generation.h"
46 #include "libmesh/linear_implicit_system.h"
47 #include "libmesh/gmv_io.h"
48 #include "libmesh/exact_solution.h"
49 
50 // GRVY
51 #ifdef GRINS_HAVE_GRVY
52 #include "grvy.h"
53 #endif
54 
55 void test_error_norm( libMesh::ExactSolution& exact_sol,
56  const std::string& system_name,
57  const std::string& var,
58  const std::string& norm,
59  const double tol,
60  int& return_flag );
61 
63 {
64 public:
65 
66  TurbulentBCFactory(libMesh::MeshFunction* _turbulent_bc_values)
68  turbulent_bc_values(_turbulent_bc_values)
69  { return; };
70 
71  ~TurbulentBCFactory(){return;};
72 
73  std::multimap< GRINS::PhysicsName, GRINS::DBCContainer > build_dirichlet( );
74 
75 private:
76  // A pointer to a TurbulentBdyFunction object that build_dirichlet can use to set bcs
77  libMesh::MeshFunction* turbulent_bc_values;
78 };
79 
80 // Class to construct the Dirichlet boundary object and operator for the inlet u velocity and nu profiles
81 class TurbulentBdyFunctionU : public libMesh::FunctionBase<libMesh::Number>
82 {
83 public:
84  TurbulentBdyFunctionU (libMesh::MeshFunction* _turbulent_bc_values) :
85  turbulent_bc_values(_turbulent_bc_values)
86  { this->_initialized = true; }
87 
88  virtual libMesh::Number operator() (const libMesh::Point&, const libMesh::Real = 0)
89  { libmesh_not_implemented(); }
90 
91  virtual void operator() (const libMesh::Point& p,
92  const libMesh::Real t,
93  libMesh::DenseVector<libMesh::Number>& output)
94  {
95  output.resize(1);
96  output.zero();
97 
98  // Since the turbulent_bc_values object has a solution from a 1-d problem, we have to zero out the y coordinate of p
99  libMesh::Point p_copy(p);
100  // 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
101  p_copy(0) = p_copy(1);
102  p_copy(1)= 0.0;
103  // Also, the 1-d solution provided is actually a symmetry solution, so we have to make the following map
104  // x_GRINS < 0.5 => x_meshfunction = 2*x_GRINS , x_GRINS >= 0.5 => x_GRINS = 1 - x_GRINS, x_meshfunction = 2*x_GRINS
105  if(p_copy(0) > 0.5)
106  {
107  p_copy(0) = 1 - p_copy(0);
108  }
109  p_copy(0) = 2*p_copy(0);
110 
111  libMesh::DenseVector<libMesh::Number> u_nu_values;
112  turbulent_bc_values->operator()(p_copy, t, u_nu_values);
113 
114  output(0) = u_nu_values(0)/21.995539;
115  }
116 
117  virtual libMesh::AutoPtr<libMesh::FunctionBase<libMesh::Number> > clone() const
118  { return libMesh::AutoPtr<libMesh::FunctionBase<libMesh::Number> > (new TurbulentBdyFunctionU(turbulent_bc_values)); }
119 
120 private:
121  libMesh::MeshFunction* turbulent_bc_values;
122 };
123 
124 // Class to construct the Dirichlet boundary object and operator for the inlet u velocity and nu profiles
125 class TurbulentBdyFunctionNu : public libMesh::FunctionBase<libMesh::Number>
126 {
127 public:
128  TurbulentBdyFunctionNu (libMesh::MeshFunction* _turbulent_bc_values) :
129  turbulent_bc_values(_turbulent_bc_values)
130  { this->_initialized = true; }
131 
132  virtual libMesh::Number operator() (const libMesh::Point&, const libMesh::Real = 0)
133  { libmesh_not_implemented(); }
134 
135  virtual void operator() (const libMesh::Point& p,
136  const libMesh::Real t,
137  libMesh::DenseVector<libMesh::Number>& output)
138  {
139  output.resize(1);
140  output.zero();
141 
142  // Since the turbulent_bc_values object has a solution from a 1-d problem, we have to zero out the y coordinate of p
143  libMesh::Point p_copy(p);
144  // 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
145  p_copy(0) = p_copy(1);
146  p_copy(1)= 0.0;
147  // Also, the 1-d solution provided is actually a symmetry solution, so we have to make the following map
148  // x_GRINS < 0.5 => x_meshfunction = 2*x_GRINS , x_GRINS >= 0.5 => x_GRINS = 1 - x_GRINS, x_meshfunction = 2*x_GRINS
149  if(p_copy(0) > 0.5)
150  {
151  p_copy(0) = 1 - p_copy(0);
152  }
153  p_copy(0) = 2*p_copy(0);
154 
155  libMesh::DenseVector<libMesh::Number> u_nu_values;
156  turbulent_bc_values->operator()(p_copy, t, u_nu_values);
157 
158  output(0) = u_nu_values(1)/(2.0*21.995539);
159  }
160 
161  virtual libMesh::AutoPtr<libMesh::FunctionBase<libMesh::Number> > clone() const
162  { return libMesh::AutoPtr<libMesh::FunctionBase<libMesh::Number> > (new TurbulentBdyFunctionNu(turbulent_bc_values)); }
163 
164 private:
165  libMesh::MeshFunction* turbulent_bc_values;
166 };
167 
168 
169 int main(int argc, char* argv[])
170 {
171 
172 #ifdef GRINS_USE_GRVY_TIMERS
173  GRVY::GRVY_Timer_Class grvy_timer;
174  grvy_timer.Init("GRINS Timer");
175 #endif
176 
177  // Check command line count.
178  if( argc < 2 )
179  {
180  // TODO: Need more consistent error handling.
181  std::cerr << "Error: Must specify libMesh input file." << std::endl;
182  exit(1); // TODO: something more sophisticated for parallel runs?
183  }
184 
185  // libMesh input file should be first argument
186  std::string libMesh_input_filename = argv[1];
187 
188  // Create our GetPot object.
189  GetPot libMesh_inputfile( libMesh_input_filename );
190 
191 #ifdef GRINS_USE_GRVY_TIMERS
192  grvy_timer.BeginTimer("Initialize Solver");
193 #endif
194 
195  // Initialize libMesh library.
196  libMesh::LibMeshInit libmesh_init(argc, argv);
197 
198  // Build a 1-d turbulent_bc_system to get the bc data from files
199  libMesh::SerialMesh mesh(libmesh_init.comm());
200 
201  GetPot command_line(argc,argv);
202 
203  std::string oned_mesh = command_line("mesh-1d", "DIE!");
204  mesh.read(oned_mesh);
205 
206  // And an EquationSystems to run on it
207  libMesh::EquationSystems equation_systems (mesh);
208 
209  std::string oned_data = command_line("data-1d", "DIE!");
210  equation_systems.read(oned_data, libMesh::XdrMODE::READ,
211  libMesh::EquationSystems::READ_HEADER |
212  libMesh::EquationSystems::READ_DATA |
213  libMesh::EquationSystems::READ_ADDITIONAL_DATA);
214 
215  // Get a reference to the system so that we can call update() on it
216  libMesh::System & turbulent_bc_system = equation_systems.get_system<libMesh::System>("flow");
217 
218  // We need to call update to put system in a consistent state
219  // with the solution that was read in
220  turbulent_bc_system.update();
221 
222  // Print information about the system to the screen.
223  equation_systems.print_info();
224 
225  // Prepare a global solution and a MeshFunction of the Turbulent system
226  libMesh::AutoPtr<libMesh::MeshFunction> turbulent_bc_values;
227 
228  libMesh::AutoPtr<libMesh::NumericVector<libMesh::Number> > turbulent_bc_soln = libMesh::NumericVector<libMesh::Number>::build(equation_systems.comm());
229 
230  std::vector<libMesh::Number> flow_soln;
231 
232  turbulent_bc_system.update_global_solution(flow_soln);
233 
234  turbulent_bc_soln->init(turbulent_bc_system.solution->size(), true, libMesh::SERIAL);
235 
236  (*turbulent_bc_soln) = flow_soln;
237 
238  std::vector<unsigned int>turbulent_bc_system_variables;
239  turbulent_bc_system_variables.push_back(0);
240  turbulent_bc_system_variables.push_back(1);
241 
242  turbulent_bc_values = libMesh::AutoPtr<libMesh::MeshFunction>
243  (new libMesh::MeshFunction(equation_systems,
244  *turbulent_bc_soln,
245  turbulent_bc_system.get_dof_map(),
246  turbulent_bc_system_variables ));
247 
248  turbulent_bc_values->init();
249 
250  GRINS::SimulationBuilder sim_builder;
251 
252  std::tr1::shared_ptr<TurbulentBCFactory> bc_factory( new TurbulentBCFactory(turbulent_bc_values.get()) );
253 
254  sim_builder.attach_bc_factory(bc_factory);
255 
256  GRINS::Simulation grins( libMesh_inputfile,
257  sim_builder,
258  libmesh_init.comm() );
259 
260 #ifdef GRINS_USE_GRVY_TIMERS
261  grvy_timer.EndTimer("Initialize Solver");
262 
263  // Attach GRVY timer to solver
264  grins.attach_grvy_timer( &grvy_timer );
265 #endif
266 
267  // Solve
268  grins.run();
269 
270 // Get equation systems to create ExactSolution object
271  std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system();
272 
273  // Create Exact solution object and attach exact solution quantities
274  //libMesh::ExactSolution exact_sol(*es);
275 
276  // Create Exact solution object and attach exact solution quantities
277  libMesh::ExactSolution exact_sol(*es);
278 
279  libMesh::EquationSystems es_ref( es->get_mesh() );
280 
281  // Filename of file where comparison solution is stashed
282  std::string solution_file = command_line("soln-data", "DIE!");
283  es_ref.read( solution_file );
284 
285  exact_sol.attach_reference_solution( &es_ref );
286 
287  // Now grab the variables for which we want to compare
288  unsigned int n_vars = command_line.vector_variable_size("vars");
289  std::vector<std::string> vars(n_vars);
290  for( unsigned int v = 0; v < n_vars; v++ )
291  {
292  vars[v] = command_line("vars", "DIE!", v);
293  }
294 
295  // Now grab the norms to compute for each variable error
296  unsigned int n_norms = command_line.vector_variable_size("norms");
297  std::vector<std::string> norms(n_norms);
298  for( unsigned int n = 0; n < n_norms; n++ )
299  {
300  norms[n] = command_line("norms", "DIE!", n);
301  if( norms[n] != std::string("L2") &&
302  norms[n] != std::string("H1") )
303  {
304  std::cerr << "ERROR: Invalid norm input " << norms[n] << std::endl
305  << " Valid values are: L2" << std::endl
306  << " H1" << std::endl;
307  }
308  }
309 
310  const std::string& system_name = grins.get_multiphysics_system_name();
311 
312  // Now compute error for each variable
313  for( unsigned int v = 0; v < n_vars; v++ )
314  {
315  exact_sol.compute_error(system_name, vars[v]);
316  }
317 
318  int return_flag = 0;
319 
320  double tol = command_line("tol", 1.0e-10);
321 
322  // Now test error for each variable, for each norm
323  for( unsigned int v = 0; v < n_vars; v++ )
324  {
325  for( unsigned int n = 0; n < n_norms; n++ )
326  {
327  test_error_norm( exact_sol, system_name, vars[v], norms[n], tol, return_flag );
328  }
329  }
330 
331  return return_flag;
332 }
333 
334 void test_error_norm( libMesh::ExactSolution& exact_sol,
335  const std::string& system_name,
336  const std::string& var,
337  const std::string& norm,
338  const double tol,
339  int& return_flag )
340 {
341  // We don't set return_flag unless we are setting it 1
342  // since this function gets called multiple times and we don't
343  // want to overwrite a previous "fail" (return_flag = 1) with
344  // a "pass" (return_flag = 0)
345 
346  double error = 0.0;
347 
348  std::cout << "==========================================================" << std::endl
349  << "Checking variable " << var << " using error norm " << norm << " with tol " << tol << "...";
350 
351  if( norm == std::string("L2") )
352  {
353  error = exact_sol.l2_error(system_name, var);
354  }
355  else if( norm == std::string("H1") )
356  {
357  error = exact_sol.h1_error(system_name, var);
358  }
359  else
360  {
361  std::cerr << "ERROR: Invalid norm " << norm << std::endl;
362  exit(1);
363  }
364 
365  if( error > tol )
366  {
367  return_flag = 1;
368 
369  std::cerr << "Tolerance exceeded for generic regression test!" << std::endl
370  << "tolerance = " << tol << std::endl
371  << "norm of error = " << error << std::endl
372  << "norm type = " << norm << std::endl
373  << "var = " << var << std::endl;
374  }
375  else
376  {
377  std::cout << "PASSED!" << std::endl
378  << "==========================================================" << std::endl;
379  }
380 
381  return;
382 }
383 
384 
385 std::multimap< GRINS::PhysicsName, GRINS::DBCContainer > TurbulentBCFactory::build_dirichlet( )
386 {
387  std::tr1::shared_ptr<libMesh::FunctionBase<libMesh::Number> > turbulent_inlet_u( new TurbulentBdyFunctionU(this->turbulent_bc_values) );
388 
389  std::tr1::shared_ptr<libMesh::FunctionBase<libMesh::Number> > turbulent_inlet_nu( new TurbulentBdyFunctionNu(this->turbulent_bc_values) );
390 
391  GRINS::DBCContainer cont_u;
392  cont_u.add_var_name( "u" );
393  cont_u.add_bc_id( 3 );
394 
395  cont_u.set_func( turbulent_inlet_u );
396 
397  GRINS::DBCContainer cont_nu;
398  cont_nu.add_var_name( "nu" );
399  cont_nu.add_bc_id( 3 );
400 
401  cont_nu.set_func( turbulent_inlet_nu );
402 
403  std::multimap< GRINS::PhysicsName, GRINS::DBCContainer > mymap;
404 
405  mymap.insert( std::pair<GRINS::PhysicsName, GRINS::DBCContainer >(GRINS::incompressible_navier_stokes, cont_u) );
406 
407  mymap.insert( std::pair<GRINS::PhysicsName, GRINS::DBCContainer >(GRINS::spalart_allmaras, cont_nu) );
408 
409  return mymap;
410 }
const PhysicsName incompressible_navier_stokes
Object for constructing boundary condition function objects.
Definition: bc_factory.h:50
Simple helper class to setup general Dirichlet boundary conditions.
Definition: dbc_container.h:49
libMesh::MeshFunction * turbulent_bc_values
libMesh::MeshFunction * turbulent_bc_values
const PhysicsName spalart_allmaras
std::multimap< GRINS::PhysicsName, GRINS::DBCContainer > build_dirichlet()
Builds all required libMesh::DirichletBoundary objects and adds them to DofMap.
void add_var_name(const GRINS::VariableName &var)
Add variables that are constrained by the Dirichlet bc.
Definition: dbc_container.C:46
TurbulentBdyFunctionU(libMesh::MeshFunction *_turbulent_bc_values)
GRINS namespace.
libMesh::MeshFunction * turbulent_bc_values
virtual libMesh::Number operator()(const libMesh::Point &, const libMesh::Real=0)
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)
TurbulentBdyFunctionNu(libMesh::MeshFunction *_turbulent_bc_values)
void add_bc_id(const GRINS::BoundaryID bc_id)
Add boundary id's for which this Dirichlet bc is to be applied.
Definition: dbc_container.C:52
virtual libMesh::AutoPtr< libMesh::FunctionBase< libMesh::Number > > clone() const
void set_func(std::tr1::shared_ptr< libMesh::FunctionBase< libMesh::Number > > func)
Add the Dirichlet bc functor.
Definition: dbc_container.C:58
void attach_bc_factory(std::tr1::shared_ptr< BoundaryConditionsFactory > bc_factory)
virtual libMesh::AutoPtr< libMesh::FunctionBase< libMesh::Number > > clone() const
int main(int argc, char *argv[])
TurbulentBCFactory(libMesh::MeshFunction *_turbulent_bc_values)
virtual libMesh::Number operator()(const libMesh::Point &, const libMesh::Real=0)

Generated on Mon Jun 22 2015 21:32:20 for GRINS-0.6.0 by  doxygen 1.8.9.1