GRINS-0.8.0
regression_testing_app.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 // GRINS
28 #include "grins/mesh_builder.h"
29 #include "grins/simulation.h"
31 #include "grins/multiphysics_sys.h"
32 #include "grins/string_utils.h"
33 
34 //libMesh
35 #include "libmesh/exact_solution.h"
36 
37 void test_error_norm( libMesh::ExactSolution& exact_sol,
38  const std::string& system_name,
39  const std::string& var,
40  const std::string& norm,
41  const double tol,
42  int& return_flag );
43 
44 void parse_qoi_data( const std::vector<std::string> & qoi_names,
45  const GetPot & command_line,
46  std::vector<libMesh::Real> & qoi_data_values,
47  std::vector<libMesh::Real> & qoi_gold_values );
48 
49 int main(int argc, char* argv[])
50 {
51  GetPot command_line(argc,argv);
52 
53  if( !command_line.have_variable("input") )
54  {
55  std::cerr << "ERROR: Must specify input file on command line with input=<file>." << std::endl;
56  exit(1);
57  }
58 
59  if( !command_line.have_variable("soln-data") )
60  {
61  std::cerr << "ERROR: Must specify solution data on command line with soln-data=<file>." << std::endl;
62  exit(1);
63  }
64 
65  if( !command_line.have_variable("gold-data") )
66  {
67  std::cerr << "ERROR: Must specify gold data on command line with gold-data=<file>." << std::endl;
68  exit(1);
69  }
70 
71  if( !command_line.have_variable("vars") )
72  {
73  std::cerr << "ERROR: Must specify variables on command line with vars='var1 var2'" << std::endl;
74  exit(1);
75  }
76 
77  if( !command_line.have_variable("norms") )
78  {
79  std::cerr << "ERROR: Must specify error norms on command line with norms='L2 H1'" << std::endl;
80  exit(1);
81  }
82 
83  if( !command_line.have_variable("tol") )
84  {
85  std::cerr << "ERROR: Must specify test tolerance on command line with tol=<tol>" << std::endl;
86  exit(1);
87  }
88 
89  if( command_line.have_variable("gold-qoi-names") && !command_line.have_variable("qoi-data") )
90  {
91  std::cerr << "ERROR: Must specify QoI data file on command line with qoi-data=<file>" << std::endl;
92  exit(1);
93  }
94 
95  if( command_line.have_variable("gold-qoi-names") && !command_line.have_variable("gold-qoi-values") )
96  {
97  std::cerr << std::string("ERROR: Must specify QoI gold values on command line with gold-qoi-values='qoi1 qoi2'")+
98  std::string(" in the same order as given in gold-qoi-names") << std::endl;
99  exit(1);
100  }
101 
102  if( command_line.have_variable("gold-qoi-names") )
103  {
104  // Make sure there are the same number of values as names
105  unsigned int n_qoi_names = command_line.vector_variable_size("gold-qoi-names");
106  unsigned int n_qoi_values = command_line.vector_variable_size("gold-qoi-values");
107 
108  if( n_qoi_names != n_qoi_values )
109  {
110  std::cerr << "ERROR: Must have the same number of gold-qoi-names and gold-qoi-values!" << std::endl;
111  exit(1);
112  }
113 
114 
115  }
116 
117  // Now grab the variables for which we want to compare
118  unsigned int n_vars = command_line.vector_variable_size("vars");
119  std::vector<std::string> vars(n_vars);
120  for( unsigned int v = 0; v < n_vars; v++ )
121  vars[v] = command_line("vars", "DIE!", v);
122 
123  // Now grab the norms to compute for each variable error
124  unsigned int n_norms = command_line.vector_variable_size("norms");
125  std::vector<std::string> norms(n_norms);
126  for( unsigned int n = 0; n < n_norms; n++ )
127  {
128  norms[n] = command_line("norms", "DIE!", n);
129  if( norms[n] != std::string("L2") &&
130  norms[n] != std::string("H1") )
131  {
132  std::cerr << "ERROR: Invalid norm input " << norms[n] << std::endl
133  << " Valid values are: L2" << std::endl
134  << " H1" << std::endl;
135  }
136  }
137 
138  // Parse QoI information
139  std::vector<std::string> qoi_names;
140  std::vector<libMesh::Real> qoi_data_values;
141  std::vector<libMesh::Real> qoi_gold_values;
142 
143  if( command_line.have_variable("gold-qoi-names") )
144  {
145  unsigned int n_qoi_names = command_line.vector_variable_size("gold-qoi-names");
146  qoi_names.reserve(n_qoi_names);
147  for( unsigned int i = 0; i < n_qoi_names; i++ )
148  qoi_names.push_back( command_line("gold-qoi-names", "DIE!") );
149 
150 
151  parse_qoi_data( qoi_names, command_line, qoi_data_values, qoi_gold_values );
152  }
153 
154  std::string input_filename = command_line("input", "DIE!");
155 
156  {
157  std::ifstream i(input_filename.c_str());
158  if (!i)
159  {
160  std::cerr << "Error: Could not read from libMesh input file "
161  << input_filename << std::endl;
162  exit(1);
163  }
164  }
165 
166  // Create our GetPot object.
167  GetPot input( input_filename );
168 
169  // But allow command line options to override the file
170  input.parse_command_line(argc, argv);
171 
172  // Don't flag our command-line-specific variables as UFOs later
173  input.have_variable("input");
174  input.have_variable("soln-data");
175  input.have_variable("gold-data");
176  input.have_variable("vars");
177  input.have_variable("norms");
178  input.have_variable("tol");
179  input.have_variable("gold-qoi-names");
180  input.have_variable("qoi-data");
181  input.have_variable("gold-qoi-values");
182 
183  // Initialize libMesh library.
184  libMesh::LibMeshInit libmesh_init(argc, argv);
185 
186  GRINS::MeshBuilder mesh_builder;
187  GRINS::SharedPtr<libMesh::UnstructuredMesh> mesh = mesh_builder.build(input,libmesh_init.comm());
188 
189  libMesh::EquationSystems es(*mesh);
190 
191  // This needs to match the read counter-part in GRINS::Simulation
192  std::string soln_data = command_line("soln-data", "DIE!" );
193 
194  {
195  std::ifstream i(soln_data.c_str());
196  if (!i)
197  {
198  std::cerr << "Error: Could not read from soln_data file "
199  << soln_data << std::endl;
200  exit(1);
201  }
202  }
203 
204  es.read(soln_data,
205  libMesh::EquationSystems::READ_HEADER |
206  libMesh::EquationSystems::READ_DATA |
207  libMesh::EquationSystems::READ_ADDITIONAL_DATA);
208 
209  std::string system_name = "GRINS-TEST";
210 
211  // Now build up the gold data
212  libMesh::EquationSystems es_ref(*mesh);
213 
214  // Filename of file where comparison solution is stashed
215  std::string gold_file = command_line("gold-data", "DIE!");
216  es_ref.read( gold_file );
217 
218  // Create Exact solution object and attach exact solution quantities
219  libMesh::ExactSolution exact_sol(es);
220  exact_sol.attach_reference_solution( &es_ref );
221 
222  // Now compute error for each variable
223  for( unsigned int v = 0; v < n_vars; v++ )
224  exact_sol.compute_error(system_name, vars[v]);
225 
226  int return_flag = 0;
227 
228  double tol = command_line("tol", 1.0e-10);
229 
230  // Now test error for each variable, for each norm
231  for( unsigned int v = 0; v < n_vars; v++ )
232  for( unsigned int n = 0; n < n_norms; n++ )
233  test_error_norm( exact_sol, system_name, vars[v], norms[n], tol, return_flag );
234 
235  // Compare QoI values
236  unsigned int n_qois = qoi_names.size();
237 
238  for( unsigned int n = 0; n < n_qois; n++ )
239  {
240 
241  std::cout << "==========================================================" << std::endl
242  << "Checking qoi " << qoi_names[n] << " with tol " << tol << "...";
243 
244  libMesh::Number gold_qoi = qoi_gold_values[n];
245 
246  libMesh::Number computed_qoi = qoi_data_values[n];
247 
248  double error = computed_qoi - gold_qoi;
249 
250  if (std::abs(error) > tol)
251  {
252  std::cerr << "Tolerance exceeded for generic regression test!" << std::endl
253  << "tolerance = " << tol << std::endl
254  << "error = " << error << std::endl
255  << "qoi index = " << n << std::endl;
256  return_flag = 1;
257  }
258  else
259  std::cout << "PASSED!" << std::endl
260  << "==========================================================" << std::endl;
261 
262  }
263 
264 
265  return return_flag;
266 }
267 
268 void test_error_norm( libMesh::ExactSolution& exact_sol,
269  const std::string& system_name,
270  const std::string& var,
271  const std::string& norm,
272  const double tol,
273  int& return_flag )
274 {
275  // We don't set return_flag unless we are setting it 1
276  // since this function gets called multiple times and we don't
277  // want to overwrite a previous "fail" (return_flag = 1) with
278  // a "pass" (return_flag = 0)
279 
280  double error = 0.0;
281 
282  std::cout << "==========================================================" << std::endl
283  << "Checking variable " << var << " using error norm " << norm << " with tol " << tol << "...";
284 
285  if( norm == std::string("L2") )
286  {
287  error = exact_sol.l2_error(system_name, var);
288  }
289  else if( norm == std::string("H1") )
290  {
291  error = exact_sol.h1_error(system_name, var);
292  }
293  else
294  {
295  std::cerr << "ERROR: Invalid norm " << norm << std::endl;
296  exit(1);
297  }
298 
299  if( error > tol )
300  {
301  return_flag = 1;
302 
303  std::cerr << "Tolerance exceeded for generic regression test!" << std::endl
304  << "tolerance = " << tol << std::endl
305  << "norm of error = " << error << std::endl
306  << "norm type = " << norm << std::endl
307  << "var = " << var << std::endl;
308  }
309  else
310  {
311  std::cout << "PASSED!" << std::endl
312  << "==========================================================" << std::endl;
313  }
314 }
315 
316 void parse_qoi_data( const std::vector<std::string> & qoi_names,
317  const GetPot & command_line,
318  std::vector<libMesh::Real> & qoi_data_values,
319  std::vector<libMesh::Real> & qoi_gold_values )
320 {
321  std::string qoi_data_filename = command_line("qoi-data", "nofile!");
322 
323  std::ifstream qoi_input( qoi_data_filename );
324  if( !qoi_input.good() )
325  {
326  std::cerr << "ERROR: Could not open "+qoi_data_filename << std::endl;
327  exit(1);
328  }
329 
330  unsigned int n_qois = qoi_names.size();
331  qoi_data_values.resize(n_qois);
332  qoi_gold_values.resize(n_qois);
333 
334  // Grab the first line of the file
335  std::string line;
336  std::getline( qoi_input, line );
337 
338  while( !qoi_input.eof() )
339  {
340  std::vector<std::string> tokens;
341  GRINS::StringUtilities::split_string( line, " =", tokens );
342 
343  std::string qoi_name = tokens[0];
344  libMesh::Real qoi_value = GRINS::StringUtilities::string_to_T<libMesh::Real>(tokens[1]);
345 
346  // Figure out the index in the qoi_names vector
347  int idx = std::find(qoi_names.begin(), qoi_names.end(), qoi_name) - qoi_names.begin();
348  if( idx < (int)qoi_names.size() )
349  qoi_data_values[idx] = qoi_value;
350 
351  // Grab the next line. If we hit the end of the file, this will flip the eofbit.
352  std::getline( qoi_input, line );
353  }
354 
355  qoi_input.close();
356 }
void parse_qoi_data(const std::vector< std::string > &qoi_names, const GetPot &command_line, std::vector< libMesh::Real > &qoi_data_values, std::vector< libMesh::Real > &qoi_gold_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)
SharedPtr< libMesh::UnstructuredMesh > build(const GetPot &input, const libMesh::Parallel::Communicator &comm LIBMESH_CAN_DEFAULT_TO_COMMWORLD)
Builds the libMesh::Mesh according to input options.
Definition: mesh_builder.C:46
void split_string(const std::string &input, const std::string &delimiter, std::vector< std::string > &results)
Definition: string_utils.C:31
int main(int argc, char *argv[])

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