Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
probeDiff.C
Go to the documentation of this file.
1 /* *******************************************************************
2  * Rocstar Simulation Suite *
3  * Copyright@2015, Illinois Rocstar LLC. All rights reserved. *
4  * *
5  * Illinois Rocstar LLC *
6  * Champaign, IL *
7  * www.illinoisrocstar.com *
8  * sales@illinoisrocstar.com *
9  * *
10  * License: See LICENSE file in top level of distribution package or *
11  * http://opensource.org/licenses/NCSA *
12  *********************************************************************/
13 /* *******************************************************************
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
21  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
22  *********************************************************************/
23 // This program compares two Rocflu/Rocflo probe files in some time interval
24 // by reporting the L2 norm of the pressure difference.
25 //
26 // The L2 norm of the error is computed as:
27 // SQRT(INTEGRAL((P1 - P2)^2))
28 //
29 // and average energy normalization is computed as:
30 // SQRT((INTEGRAL(P1))^2 + (INTEGRAL(P2))^2)
31 //
32 // Compile it with c++ -O3 probDiff.C -o probediff
33 //
34 #include <iostream>
35 #include <string>
36 #include <vector>
37 #include <fstream>
38 #include <sstream>
39 
40 
41 // This routine determines and returns the value of the probe data
42 // at time t. It also returns the indices of the interval, (n0,n1),
43 // where time t lives. It starts at index 'start' to keep it from
44 // having to search the entire curve with every call.
45 double
46 determine_probe_value(std::vector<std::pair<double, double> > &probe,
47  int &n0, int &n1, double t, int start)
48 {
49  double TOL = 1e-20;
50  int n = start;
51  if(probe[n].first > t && !(std::fabs(probe[n].first - t) <= TOL)){
52  std::cerr << "Interval error!" << std::endl;
53  exit(1);
54  }
55  while(n < probe.size() && probe[n].first < t &&
56  !(std::fabs(probe[n].first - t) <= TOL))
57  n++;
58  if(n >= probe.size()){
59  std::cerr << "Ran off the end of the probe data!" << std::endl;
60  exit(1);
61  }
62  if(std::fabs(probe[n].first - t) <= TOL){
63  n0 = n;
64  n1 = n + 1;
65  }
66  else{
67  n1 = n;
68  n0 = n - 1;
69  }
70 
71  // This little check will account for probe hiccups that
72  // sometimes happen where we will get multiple entries
73  // for a single time.
74  double dt = probe[n1].first - probe[n0].first;
75  if(dt < 0 || (std::fabs(dt) <= TOL))
76  n1++;
77 
78  // Return the linearly interpolated probe value at time t
79  double slope = (probe[n1].second - probe[n0].second)/
80  (probe[n1].first - probe[n0].first);
81  return(probe[n0].second + slope*(t - probe[n0].first));
82 }
83 
84 int
85 main(int argc,char *argv[])
86 {
87 
88  // This is all the necessary argument parsing and file reading
89  std::vector<std::string> args;
90  int nn = 0;
91  while(argv[nn])
92  args.push_back(std::string(argv[nn++]));
93  std::string program_name(args[0]);
94 
95  if(argc < 3){
96  std::cerr << "Usage: " << program_name << " [-t0 time0] [-t1 time1] "
97  << "<probe file 1> <probe file 2>" << std::endl;
98  exit(0);
99  }
100 
101  bool minset = false;
102  bool maxset = false;
103  double t0 = 0.0;
104  double t1 = 10000000.0;
105 
106  std::string timeopt;
107  std::vector<std::string>::iterator ai = args.begin();
108  while(ai != args.end() && !minset){
109  if(*ai == "-t0"){
110  ai++;
111  if(ai == args.end()){
112  std::cerr << program_name << ": Expected argument after -t0 option."
113  << std::endl;
114  exit(1);
115  }
116  timeopt = *ai;
117  std::istringstream Istr(timeopt);
118  // This removes whitespace from the argument
119  Istr >> timeopt;
120  Istr.clear();
121  Istr.str(timeopt);
122  Istr >> t0;
123  if(t0 < 0.0){
124  std::cerr << program_name << ": Invalid value for t0 option, "
125  << t0 << "." << std::endl;
126  exit(1);
127  }
128  minset = true;
129  }
130  else
131  ai++;
132  }
133  ai = args.begin();
134  while(ai != args.end() && !maxset){
135  if(*ai == "-t1"){
136  ai++;
137  if(ai == args.end()){
138  std::cerr << program_name << ": Expected argument after -t1 option."
139  << std::endl;
140  exit(1);
141  }
142  timeopt = *ai;
143  // This removes whitespace from the argument
144  std::istringstream Istr(timeopt);
145  Istr >> timeopt;
146  Istr.clear();
147  Istr.str(timeopt);
148  Istr >> t1;
149  if(t1 < 0.0){
150  std::cerr << program_name << ": Invalid value for t1 option, "
151  << t1 << "." << std::endl;
152  exit(1);
153  }
154  maxset = true;
155  }
156  else
157  ai++;
158  }
159  if((t1 - t0) < 0.0){
160  std::cerr << program_name << ": Invalid time interval, " << t0 << " - "
161  << t1 << std::endl;
162  exit(1);
163  }
164  int acount = 1;
165  while(acount < argc && args[acount][0] == '-'){
166  acount++;
167  acount++;
168  }
169  if(acount >= argc){
170  std::cerr << "Usage: " << program_name << " [-t0 time0] [-t1 time1] "
171  << "<probe file 1> <probe file 2>" << std::endl;
172  exit(1);
173  }
174  std::string probe1_file(args[acount++]);
175  if(acount >= argc){
176  std::cerr << "Usage: " << program_name << " [-t0 time0] [-t1 time1] "
177  << "<probe file 1> <probe file 2>" << std::endl;
178  exit(1);
179  }
180  std::string probe2_file(args[acount]);
181 
182  std::ifstream Inf1;
183  std::ifstream Inf2;
184 
185  Inf1.open(probe1_file.c_str());
186  if(!Inf1){
187  std::cerr << program_name << ": Unable to open probe file, " << probe1_file
188  << "." << std::endl;
189  exit(1);
190  }
191  Inf2.open(probe2_file.c_str());
192  if(!Inf2){
193  std::cerr << program_name << ": Unable to open probe file, " << probe2_file
194  << "." << std::endl;
195  exit(1);
196  }
197  std::vector<std::pair<double,double> > probe1;
198  std::vector<std::pair<double,double> > probe2;
199  int n = 0;
200  double dum;
201  std::cout << program_name << ": Reading probe 1 ..." << std::flush;
202  while(!Inf1.eof()){
203  std::pair<double,double> inpair;
204  Inf1 >> inpair.first >> dum >> dum >> dum >> dum >> inpair.second
205  >> dum;
206  probe1.push_back(inpair);
207  n++;
208  }
209  n--;
210  probe1.pop_back();
211  Inf1.close();
212  std::cout << "... done" << std::endl
213  << program_name << ": Probe1(" << n << "): (" << probe1[0].first
214  << ", " << probe1[0].second << ") - (" << probe1[n-1].first
215  << ", " << probe1[n-1].second << ")" << std::endl;
216  n = 0;
217  std::cout << program_name << ": Reading probe 2 ...";
218  while(!Inf2.eof()){
219  std::pair<double,double> inpair;
220  Inf2 >> inpair.first >> dum >> dum >> dum >> dum >> inpair.second
221  >> dum;
222  probe2.push_back(inpair);
223  n++;
224  }
225 
226  // The stupid thing reads too many - not sure why it does this,
227  // but the next two lines fix the problem
228  n--;
229  probe2.pop_back();
230  Inf2.close();
231 
232  int n1 = probe1.size();
233  int n2 = probe2.size();
234  double probe_tmin = (probe1[0].first < probe2[0].first ?
235  probe2[0].first : probe1[0].first);
236  double probe_tmax = (probe1[n1-1].first > probe2[n2-1].first ?
237  probe2[n2-1].first : probe1[n1-1].first);
238  std::cout << "... done" << std::endl
239  << program_name << ": Probe2(" << n << "): (" << probe2[0].first
240  << ", " << probe2[0].second << ") - (" << probe2[n-1].first
241  << ", " << probe2[n-1].second << ")" << std::endl;
242  if(minset && (probe1[0].first > t0 || probe2[0].first > t0))
243  std::cout << program_name << ": t0(" << t0 << ") is less than the "
244  << " earliest common probe time: " << probe_tmin
245  << ", resetting." << std::endl;
246  if(t0 < probe_tmin)
247  t0 = probe_tmin;
248  if(maxset && (probe1[n1-1].first < t1 || probe2[n2-1].first < t1))
249  std::cout << program_name << ": t1(" << t1 << ") is greater than the "
250  << " latest common probe time: " << probe_tmax << ", resetting."
251  << std::endl;
252  if(t1 > probe_tmax)
253  t1 = probe_tmax;
254  std::cout << program_name << ": Comparing probes in time interval (" << t0
255  << ", " << t1 << ")" << std::endl;
256 
257  // Now we have two probe data arrays. Each array entry is a pair of doubles
258  // with the time and pressure respectively. Time to compare them.
259  //
260  // Loop from t0 to t1
261  int n10 = 0;
262  int n11 = 0;
263  int n20 = 0;
264  int n21 = 0;
265  double integral = 0.0;
266  double normal1 = 0.0;
267  double normal2 = 0.0;
268  double ti = t0;
269  double infnorm = 0.0;
270 
271  // Find both probe values by linear interpolation at t0
272  double pp10 = determine_probe_value(probe1,n10,n11,ti,0);
273  double pp20 = determine_probe_value(probe2,n20,n21,ti,0);
274  double tf = ti;
275 
276  while(tf < t1){
277 
278  // Set tf to be the next time we have a known value on
279  // either curve.
280  tf = ((probe1[n11].first < probe2[n21].first) &&
281  (probe1[n11].first > ti) ? probe1[n11].first :
282  probe2[n21].first);
283 
284  // Big problem if tf = ti Note: this can actually be okay in
285  // exceptional cases, but we are dealing with those in the
286  // determine_probe_value routine so that when we get to this
287  // point, if tf = ti, we have to fail.
288  if(tf == ti){
289  std::cerr << program_name << ": Encountered 0 interval. "
290  << "Cannot proceed." << std::endl
291  << "Here's some debugging information:" << std::endl
292  << "Getting probe 1 data. (" << n10 << "," << n11
293  << "," << tf << "," << probe1[n10].first << ")"
294  << std::flush << std::endl;
295  double pp11 = determine_probe_value(probe1,n10,n11,tf,n10);
296  std::cerr << "Got probe 1 data. (" << n10 << "," << n11
297  << "," << tf << "," << probe1[n10].first << ")"
298  << std::flush << std::endl
299  << "Getting probe 2 data. (" << n20 << "," << n21
300  << "," << tf << "," << probe2[n20].first << ")"
301  << std::flush << std::endl;
302  double pp21 = determine_probe_value(probe2,n20,n21,tf,n20);
303  std::cerr << "Got probe 2 data. (" << n20 << "," << n21
304  << "," << tf << "," << probe2[n20].first << ")"
305  << std::flush << std::endl
306  << "probe1(" << n10 << "," << n11 << ")["
307  << probe1[n11].first << "]" << std::endl
308  << "probe2(" << n20 << "," << n21 << ")["
309  << probe2[n21].first << "]" << std::endl;
310  exit(1);
311  }
312 
313  // Reset the tf if it exceeds the maximum time in our interval
314  if(tf > t1) tf = t1;
315 
316  // Determine the probe values at tf by linear interpolation
317  double pp11 = determine_probe_value(probe1,n10,n11,tf,n10);
318  double pp21 = determine_probe_value(probe2,n20,n21,tf,n20);
319 
320  // Evaluate the integrated functions exactly as integrated lines
321  // on this dt interval
322  double dt = tf - ti;
323  double dp1 = pp10 - pp11;
324  double dp2 = pp20 - pp21;
325  double A1 = dp1/dt;
326  double A2 = dp2/dt;
327  double p12 = pp10 - pp20;
328  double A12 = A1 - A2;
329 
330  // Integral(f - g) for infinity norm
331  double infterm = (p12*dt + A12*dt*dt/2.0);
332  if(std::fabs(infterm) > std::fabs(infnorm))
333  infnorm = infterm;
334 
335  // Integral(f) and Integral(g) for normalization
336  normal1 += (pp10*dt + A1*dt*dt/2.0);
337  normal2 += (pp20*dt + A2*dt*dt/2.0);
338 
339  // Integral((f-g)^2) for L2
340  integral += (p12*p12*dt + p12*A12*dt*dt + A12*A12*dt*dt*dt/3.0);
341 
342  // Update our place along the curves before continuing
343  ti = tf;
344  pp10 = pp11;
345  pp20 = pp21;
346  }
347 
348  // L2 norm integral
349  integral = std::sqrt(integral);
350 
351  // Normalization (not sure if this is the way to go)
352  double normal = std::sqrt(normal1*normal1+normal2*normal2);
353 
354  std::cout.precision(12);
355  std::cout << program_name << ": Error Integral = "
356  << std::scientific << integral << std::endl
357  << program_name << ": Probe 1 Area = "
358  << std::scientific << normal1 << std::endl
359  << program_name << ": Probe 2 Area = "
360  << std::scientific << normal2 << std::endl
361  << program_name << ": Max Error = "
362  << std::scientific << infnorm << std::endl
363  << program_name << ": Normalized Errors:" << std::endl
364  << program_name << ": L2 = "
365  << std::scientific << integral/normal << std::endl
366  << program_name << ": LINF = "
367  << std::scientific << infnorm/normal << std::endl;
368  exit(0);
369 }
370 
371 
372 
373 
374 
375 
double sqrt(double d)
Definition: double.h:73
const double TOL
Definition: GeoPrimitives.H:17
const NT & n
int main(int argc, char *argv[])
Definition: blastest.C:94
double determine_probe_value(std::vector< std::pair< double, double > > &probe, int &n0, int &n1, double t, int start)
Definition: probeDiff.C:46