PlasCom2  1.0
XPACC Multi-physics simluation application
TestViscousRHS.C
Go to the documentation of this file.
1 #include "Testing.H"
2 #include "Simulation.H"
3 #include "RKTestFixtures.H"
4 #include "EulerRHS.H"
5 #include "Stencil.H"
6 #include "PCPPCommUtil.H"
7 #include "PCPPReport.H"
8 #include "PCPPIntervalUtils.H"
9 #include "TestFixtures.H"
10 #include "ViscidTestFixtures.H"
11 #include "EulerTestFixtures.H"
12 #include "EulerUtil.H"
13 #include "ViscidUtil.H"
14 #include <iomanip>
15 
17 
19 
20 void TestViscidKernels(ix::test::results &serialUnitResults)
21 {
22 
24 
25  std::cout << "TestViscidKernels.." << std::endl;
26 
27  // multi-dimension test results
28  std::vector<bool> dimComputeDV(2,false);
29  std::vector<bool> dimComputeTV(2,false);
30  std::vector<bool> dimComputeStressTensor(2,false);
31  std::vector<bool> dimComputeHeatFlux(2,false);
32  std::vector<bool> dimComputeDV2(2,true);
33  std::vector<bool> dimComputeTEF(2,true);
34 
35  //std::vector<bool> dimUniformGridMetric(2,false);
36  //std::vector<bool> dimViscidRHS(2,false);
37  std::vector<bool> dimViscidUniformFlux(2,true);
38 
39  // -- Set up the grid --
40  for(int nDim = 2;nDim <= 3;nDim++){
41  grid_t testGrid;
42  int numDim = nDim;
43  std::vector<double> &realGridExtent(testGrid.PhysicalExtent());
44  realGridExtent.resize(numDim*2,0.0);
45  for(int iDim = 0;iDim < numDim;iDim++)
46  realGridExtent[iDim*2 + 1] = 1.0;
47 
48  std::vector<size_t> &numNodes(testGrid.GridSizes());
49  numNodes.resize(numDim);
50  numNodes[0] = 11;
51  numNodes[1] = 101;
52  if(numDim == 3)
53  numNodes[2] = 1001;
54 
55  // numNodes[0] = 4;
56  // numNodes[1] = 4;
57  // numNodes[2] = 4;
58 
59  size_t numNodesDomain = 1;
60  size_t numCellsDomain = 1;
61  std::vector<double> dX(numDim,0.0);
62  std::vector<double> gridMetric(numDim,0.0);
63  std::vector<double> gridJacobian(1,1.0);
64  int gridType = 0; // choose uniform rectangular metric
65 
66  for(int iDim = 0;iDim < numDim;iDim++){
67  numNodesDomain *= numNodes[iDim];
68  numCellsDomain *= (numNodes[iDim]-1);
69  dX[iDim] = (realGridExtent[iDim*2+1] - realGridExtent[iDim*2])/(numNodes[iDim]-1);
70  gridMetric[iDim] = 1.0/dX[iDim];
71  gridJacobian[0] *= gridMetric[iDim];
72  }
73  testGrid.SetGridSpacings(dX);
74  if(testGrid.Finalize()){
75  std::cout << "Grid finalization failed." << std::endl;
76  return;
77  }
78 
79  std::vector<size_t> bufferInterval;
80  testGrid.PartitionBufferInterval().Flatten(bufferInterval);
81 
82  double a = 1.0;
83  double t = 1.0;
84  double gamma = 1.4;
85  double specGasConst = 1.0;
86  double dt = 1.0;
87  double cfl = 1.0;
88  std::vector<double> vVec(numDim,0.0);
89  vVec[0] = 1.0;
90  vVec[1] = -1.0;
91  if(numDim == 3) vVec[2] = 2.0;
92  double v = vVec[0];
93 
94  // in non-dimensional, ideal gas, P=rho*R*T (R=1)
95  double pressure = 1.0;
96  double density = 1.2;
97  double temperature = pressure/density/specGasConst;
98 
99  std::vector<double> expectedRhoM1(numNodesDomain,1.0/density);
100  std::vector<double> expectedFlux((numDim+2)*numNodesDomain,0.0);
101  std::vector<double> expectedPressure(numNodesDomain,pressure);
102  std::vector<double> expectedTemperature(numNodesDomain,temperature);
103  std::vector<double> expectedVHat(numDim*numNodesDomain,0.0);
104  std::vector<double> expectedVelocity(numDim*numNodesDomain,0.0);
105  std::vector<double> expectedInternalEnergy(numNodesDomain,pressure/(gamma-1.0));
106  std::vector<double> expectedRHS((numDim+2)*numNodesDomain,0.0);
107 
108  std::vector<double> ke(numNodesDomain,0.0);
109  std::vector<double> rho(numNodesDomain,density);
110  // calculated below
111  std::vector<double> rhoV(numDim*numNodesDomain,0.0);
112  std::vector<double> rhoE(numNodesDomain,0.0);
113  // dX = <.1,.01,.001>
114  // Velocity = <1.0,-1.0,0>
115  // rhoV = 1.0 * Velocity
116  // vHat = Velocity/dX
117  for(int iDim = 0;iDim < numDim;iDim++){
118  for(int iPoint = 0;iPoint < numNodesDomain;iPoint++){
119  rhoV[iDim*numNodesDomain + iPoint] = rho[iPoint]*vVec[iDim];
120  ke[iPoint] += .5*rho[iPoint]*vVec[iDim]*vVec[iDim];
121  expectedVelocity[iDim*numNodesDomain+iPoint] = vVec[iDim];
122  expectedVHat[iDim*numNodesDomain+iPoint] = vVec[iDim]/dX[iDim];
123  }
124  }
125  // rhoE = [1.0/(gamma-1.0) + .5*rhoV*Velocity]
126  for(int iPoint = 0;iPoint < numNodesDomain;iPoint++){
127  //rhoE[iPoint] = 1.0/(gamma-1.0) + ke[iPoint];
128  rhoE[iPoint] = expectedPressure[iPoint]/(gamma-1.0)+ ke[iPoint];
129  }
130 
131  std::vector<double> T(numNodesDomain,0.0);
132  std::vector<double> p(numNodesDomain,0.0);
133  std::vector<double> rhom1(numNodesDomain,0.0);
134  std::vector<double> velocity(numDim*numNodesDomain,-.1);
135  std::vector<double> internalEnergy(numNodesDomain,0.);
136 
137  std::vector<double *> vBuffers(numDim,(double *)NULL);
138  for(int iDim = 0;iDim < numDim;iDim++)
139  vBuffers[iDim] = &velocity[iDim*numNodesDomain];
140 
141  bool computeDVWorks = true;
142 
143  T.resize(0);
144  p.resize(0);
145  velocity.resize(0);
146  rhom1.resize(0);
147  T.resize(numNodesDomain,0.0);
148  p.resize(numNodesDomain,0.0);
149  velocity.resize(numDim*numNodesDomain,-.1);
150  rhom1.resize(numNodesDomain,0.0);
151 
152  std::vector<double *> myStateBuffers(numDim+2,NULL);
153  myStateBuffers[0] = &rho[0];
154  for(int iDim = 0;iDim < numDim;iDim++)
155  myStateBuffers[iDim+1] = &rhoV[iDim*numNodesDomain];
156  myStateBuffers[numDim+1] = &rhoE[0];
157 
158  std::vector<double *> myDVBuffers(4+numDim,NULL);
159  myDVBuffers[0] = &p[0];
160  myDVBuffers[1] = &T[0];
161  myDVBuffers[2] = &rhom1[0];
162 
163  for(int iDim = 0;iDim < numDim;iDim++){
164  vBuffers[iDim] = &velocity[iDim*numNodesDomain];
165  myDVBuffers[3+iDim] = vBuffers[iDim];
166  }
167  myDVBuffers[numDim+3] = &internalEnergy[0];
168 
169  pcpp::IndexIntervalType bufferExtent;
170  bufferExtent.InitSimple(numNodes);
171 
172  // setup a new equation of state object for this grid
173  eos::perfect_gas myEOS;
174  //myEOS.InitializeBufferExtents(bufferExtent,numNodes);
175  myEOS.SetupPressureBuffer(&p[0]);
176  myEOS.SetupTemperatureBuffer(&T[0]);
177  myEOS.SetupSpecificVolumeBuffer(&rhom1[0]);
178  myEOS.SetupInternalEnergyBuffer(&internalEnergy[0]);
179 
180  myEOS.SetSpecificGasConstant(specGasConst);
181  myEOS.SetGamma(gamma);
182 
183  if(myEOS.InitializeMaterialProperties()){
184  std::cout << "Failed to initialize EOS" << std::endl;
185  }
186 
187  if(euler::util::ComputeDVBuffer(bufferExtent,numNodes,myStateBuffers,myDVBuffers))
188  {
189  std::cout << "ComputeDVBuffer failed." << std::endl;
190  }
191 
192  // now calculate the pressure and temperature
193  if(myEOS.ComputePressureBuffer(bufferExtent,numNodes)) {
194  std::cout << "ComputePressure failed." << std::endl;
195  }
196 
197  if(myEOS.ComputeTemperatureBuffer(bufferExtent,numNodes)) {
198  std::cout << "ComputeTemperature failed." << std::endl;
199  }
200 
201  bool printPressure=true;
202  bool printTemperature=true;
203  bool printVelocity=true;
204  bool printVolume=true;
205  for(int iNode = 0;iNode < numNodesDomain;iNode++){
206  if(std::abs(p[iNode] - expectedPressure[iNode]) > 1e-15){
207  computeDVWorks = false;
208  if(printPressure) {
209  std::cout << "In ComputeDVTest, Expected pressure=" << expectedPressure[iNode]
210  << " got pressure=" << p[iNode] << " at iNode=" << iNode << std::endl;
211  std::cout << "No further error messages will be generated for pressure" << std::endl;
212  printPressure=false;
213  }
214  }
215  if(std::abs(T[iNode] - expectedTemperature[iNode]) > 1e-15){
216  computeDVWorks = false;
217  if(printTemperature) {
218  std::cout << "In ComputeDVTest, Expected temperature=" << expectedTemperature[iNode]
219  << " got temperature=" << T[iNode] << " at iNode=" << iNode << std::endl;
220  std::cout << "No further error messages will be generated for temperature" << std::endl;
221  printTemperature=false;
222  }
223  }
224  if(std::abs(rhom1[iNode] - expectedRhoM1[iNode]) > 1e-15){
225  computeDVWorks = false;
226  if(printVolume) {
227  std::cout << "In ComputeDVTest, Expected volume=" << expectedRhoM1[iNode]
228  << " got volume=" << rhom1[iNode] << " at iNode=" << iNode << std::endl;
229  std::cout << "No further error messages will be generated for volume" << std::endl;
230  printVolume=false;
231  }
232  }
233  for(int iDim = 0;iDim < numDim;iDim++){
234  if(std::abs(velocity[iDim*numNodesDomain+iNode] -
235  expectedVelocity[iDim*numNodesDomain+iNode]) > 1e-15){
236  computeDVWorks = false;
237  if(printVelocity) {
238  std::cout << "In ComputeDVTest, Expected velocity=" << expectedVelocity[iNode]
239  << " got velocity=" << velocity[iNode] << " at iNode="
240  << iNode << " iDim=" << iDim << std::endl;
241  std::cout << "No further error messages will be generated for velocity" << std::endl;
242  printVelocity=false;
243  }
244  }
245  }
246  }
247 
248  //
249  // test calculation of the transport coefficients
250  //
251  std::cout << "Running tests for "<<numDim<<"D ComputeTV" << std::endl;
252 
253  std::vector<double> mu(numNodesDomain,0.0);
254  std::vector<double> lambda(numNodesDomain,0.0);
255  std::vector<double> kappa(numNodesDomain,0.0);
256 
257  std::vector<double *> myTVBuffers(3,NULL);
258  myTVBuffers[0] = &mu[0];
259  myTVBuffers[1] = &lambda[0];
260  myTVBuffers[2] = &kappa[0];
261 
262 
263  double power = 0.666;
264  double beta = 5;
265  double bulkViscFac = 2;
266  double Cp = gamma/(gamma-1);
267  double Pr = 0.75;
268  double tempMu = beta*pow(expectedTemperature[0],power);
269  double tempLambda = (bulkViscFac - 2.0/3.0)*tempMu;
270  double tempKappa = Cp*tempMu/Pr;
271  std::vector<double> expectedMu(numNodesDomain,tempMu);
272  std::vector<double> expectedLambda(numNodesDomain,tempLambda);
273  std::vector<double> expectedKappa(numNodesDomain,tempKappa);
274  bool computeTVWorks=true;
275  bool muFailed = false;
276  bool lambdaFailed = false;
277  bool kappaFailed = false;
278 
280  bufferExtent,numNodes,myDVBuffers[1],myTVBuffers,beta,power,bulkViscFac,Cp,Pr))
281  {
282  std::cout << "ComputeTVBuffer failed." << std::endl;
283  }
284 
285  bool printMu = true;
286  bool printLambda = true;
287  bool printKappa = true;
288  double error = 1;
289  for(int iNode = 0;iNode < numNodesDomain;iNode++){
290  error = std::abs((mu[iNode] - expectedMu[iNode])/expectedMu[iNode]);
291  if(error > 1e-15){
292  computeTVWorks = false;
293  muFailed = true;
294  if(printMu) {
295  std::cout << "In ComputeTvTest, Expected mu=" << expectedMu[iNode]
296  << " got mu=" << mu[iNode] << " at iNode=" << iNode << std::endl;
297  std::cout << "Temperature was " << T[iNode] << std::endl;
298  std::cout << "No further error messages will be generated for mu" << std::endl;
299  printMu=false;
300  }
301  }
302  error = std::abs((lambda[iNode] - expectedLambda[iNode])/expectedLambda[iNode]);
303  if(error > 1e-15){
304  computeTVWorks = false;
305  lambdaFailed = true;
306  if(printLambda) {
307  std::cout << "In ComputeTvTest, Expected lambda=" << expectedLambda[iNode]
308  << " got lambda=" << lambda[iNode] << " at iNode=" << iNode << std::endl;
309  std::cout << "Temperature was " << T[iNode] << std::endl;
310  std::cout << "No further error messages will be generated for lambda" << std::endl;
311  printLambda=false;
312  }
313  }
314  error = std::abs((kappa[iNode] - expectedKappa[iNode])/expectedKappa[iNode]);
315  if(error > 1e-15){
316  computeTVWorks = false;
317  kappaFailed = true;
318  if(printKappa) {
319  std::cout << "In ComputeTvTest, Expected kappa=" << expectedKappa[iNode]
320  << " got kappa=" << kappa[iNode] << " at iNode=" << iNode << std::endl;
321  std::cout << "Temperature was " << T[iNode] << std::endl;
322  std::cout << "No further error messages will be generated for kappa" << std::endl;
323  printKappa=false;
324  }
325  }
326  }
327 
328  dimComputeTV[numDim-2] = computeTVWorks;
329  if(muFailed){
330  std::cout << "Mu failed" << std::endl;
331  }
332  if(lambdaFailed){
333  std::cout << "Lambda failed" << std::endl;
334  }
335  if(kappaFailed){
336  std::cout << "Kappa failed" << std::endl;
337  }
338 
339  std::cout << "Done running tests for "<<numDim<<"D ComputeTV" << std::endl;
340  std::cout << "Running tests for "<<numDim<<"D ComputeStressTensor" << std::endl;
341 
342  // build a velocity gradient so we can test the calculation of the stress tensor
343  // in 3D...
344  // | du/dx dv/dx dw/dx | | [1..1] [2..2] [3..3]
345  // | du/dy dv/dy dw/dy | = | [4..4] [5..5] [6..6]
346  // | du/dz dv/dz dw/dz | | [7..7] [8..8] [9..9]
347  std::vector<double *> myVelGradBuffer(numDim,NULL);
348  for(int i=0;i<numDim;i++){
349  myVelGradBuffer[i] = new double [numDim*numNodesDomain];
350  for(int j=0;j<numDim;j++){
351  int offset=j*numNodesDomain;
352  double value = static_cast<double>(i*numDim+j+1);
353  for(int k=0;k<numNodesDomain;k++){
354  //if(k==0){
355  //std::cout << "i, j, velGrad" << i << " " << j << " " << value << std::endl;
356  //}
357  myVelGradBuffer[i][offset+k]=value;
358  }
359  }
360  }
361 
362  // calculate the stress tensor
363  // the stress tensor is symmetric and stored in memory like (in 3D)
364  // [ {tau11} {tau12} {tau13} {tau22} {tau23} {tau33} ]
365  // myTauBuffer has pointers into memory for all numDim^2 components
366  // [ {tau11} {tau12} {tau13} {tau22} {tau23} {tau33} ]
367  std::vector<double *> myTauBuffer(numDim*numDim,NULL);
368  std::vector<double> myTau(numDim*(numDim+1)*numNodesDomain/2,0);
369  size_t bufferIndex = 0;
370  for(int i=0;i<numDim;i++){
371  for(int j=0;j<numDim;j++){
372  int index = i*numDim + j;
373  if (i <= j){
374  myTauBuffer[index] = &myTau[bufferIndex];
375  bufferIndex += numNodesDomain;
376  } else {
377  myTauBuffer[index] = myTauBuffer[j*numDim+i];
378  }
379  }
380  }
381 
382  double Re = 100.;
383  if(viscid::util::ComputeTauBuffer(bufferExtent, numNodes, gridType, gridMetric, gridJacobian, Re,
384  myTVBuffers, myVelGradBuffer, myTauBuffer)){
385  std::cout << "Calculation of the stress tensor failed" << std::endl;
386  }
387 
388  // Construct the expected stress tensor
389  // tau_ij = mu/Re * (dv_i/dx_j+dv_j/dx_i) + lambda/Re * (dv_k/dx_k) delta_ij
390  // Re = 100, mu and lambda set above from T=3.5
391  // gridmetrics are applied by ComputeStressTensor, so account for this here
392  std::vector<double> tauExpected;
393 
394  if(numDim == 2){
395  tauExpected.push_back(tempMu/Re*(1*gridMetric[0]+1*gridMetric[0])
396  + tempLambda/Re*(1*gridMetric[0]+4*gridMetric[1])); //tau_11
397  tauExpected.push_back(tempMu/Re*(2*gridMetric[0]+3*gridMetric[1])); //tau_12
398  tauExpected.push_back(tempMu/Re*(2*gridMetric[0]+3*gridMetric[1])); //tau_21 = tau_12
399  tauExpected.push_back(tempMu/Re*(4*gridMetric[1]+4*gridMetric[1])
400  + tempLambda/Re*(1*gridMetric[0]+4*gridMetric[1])); //tau_22
401 
402 
403 
404  } else {
405 
406  // | du/dxi dv/dxi dw/dxi | | [1..1] [2..2] [3..3]
407  // | du/deta dv/deta dw/deta | = | [4..4] [5..5] [6..6]
408  // | du/dzeta dv/dzeta dw/dzeta | | [7..7] [8..8] [9..9]
409  // dxidx = metric[0]
410  // detady = metric[1]
411  // dzetadz = metric[2]
412 
413  tauExpected.push_back(tempMu/Re*(1*gridMetric[0]+1*gridMetric[0])
414  + tempLambda/Re*(1*gridMetric[0]+5*gridMetric[1]+9*gridMetric[2])); //tau_11
415  tauExpected.push_back(tempMu/Re*(2*gridMetric[0]+4*gridMetric[1])); //tau_12
416  tauExpected.push_back(tempMu/Re*(3*gridMetric[0]+7*gridMetric[2])); //tau_13
417  tauExpected.push_back(tempMu/Re*(2*gridMetric[0]+4*gridMetric[1])); //tau_21 = tau12
418  tauExpected.push_back(tempMu/Re*(5*gridMetric[1]+5*gridMetric[1])
419  + tempLambda/Re*(1*gridMetric[0]+5*gridMetric[1]+9*gridMetric[2])); //tau_22
420  tauExpected.push_back(tempMu/Re*(6*gridMetric[1]+8*gridMetric[2])); //tau_23
421  tauExpected.push_back(tempMu/Re*(3*gridMetric[0]+7*gridMetric[2])); //tau_31 = tau13
422  tauExpected.push_back(tempMu/Re*(6*gridMetric[1]+8*gridMetric[2])); //tau_32 = tau23
423  tauExpected.push_back(tempMu/Re*(9*gridMetric[2]+9*gridMetric[2])
424  + tempLambda/Re*(1*gridMetric[0]+5*gridMetric[1]+9*gridMetric[2])); //tau_33
425  }
426 
427  for(int i=0;i<tauExpected.size();i++){
428  tauExpected[i] *= gridJacobian[0];
429  }
430 
431  // Compare expected against actual
432  bool tauFailed=false;
433  bool computeTauWorks=true;
434  for(int i=0;i<numDim*numDim;i++){
435  bool printTau=true;
436  for(int iNode = 0;iNode < numNodesDomain;iNode++){
437  double error = std::abs((myTauBuffer[i][iNode] - tauExpected[i])/tauExpected[i]);
438  if(error > 1e-15){
439  computeTauWorks = false;
440  tauFailed = true;
441  if(printTau) {
442  std::cout << "In ComputeTauTest, Expected tau[" << i << "]=" << tauExpected[i]
443  << " got tau=" << myTauBuffer[i][iNode] << " at iNode=" << iNode
444  << " error=" << error << std::endl;
445  std::cout << "No further error messages will be generated for this tau index"
446  << std::endl;
447  printTau=false;
448  }
449  }
450  }
451  }
452  dimComputeStressTensor[numDim-2] = computeTauWorks;
453  if(tauFailed){
454  std::cout << "Tau failed" << std::endl;
455  }
456  std::cout << "Done running tests for "<<numDim<<"D ComputeStressTensor" << std::endl;
457 
458  std::cout << "Running tests for "<<numDim<<"D ComputeHeatFlux" << std::endl;
459 
460  // build a temperature gradient so we can test the calculation of the heat flux vector
461  // in 3D...
462  // | dT/dx dT/dy dT/dz | | [1..1] [2..2] [3..3]
463  std::vector<double *> myTempGradBuffer(numDim,NULL);
464  std::vector<double> myTempGrad(numDim*numNodesDomain,0);
465  for(int i=0;i<numDim;i++){
466  myTempGradBuffer[i] = &myTempGrad[i*numNodesDomain];
467  double value = static_cast<double>(i+1);
468  for(int k=0;k<numNodesDomain;k++){
469  myTempGradBuffer[i][k]=value;
470  }
471  }
472 
473  // calculate the heat flux vector
474  std::vector<double *> myHeatFluxBuffer(numDim,NULL);
475  std::vector<double> myHeatFlux(numDim*numNodesDomain,0);
476  for(int i=0;i<numDim;i++){
477  myHeatFluxBuffer[i] = &myHeatFlux[i*numNodesDomain];
478  }
479 
480  if(viscid::util::ComputeHeatFluxBuffer(bufferExtent, numNodes, gridType,gridMetric,
481  gridJacobian, Re, myTVBuffers, myTempGradBuffer,
482  myHeatFluxBuffer)){
483  std::cout << "Calculation of the heat flux vector failed" << std::endl;
484  }
485 
486  // Construct the expected heat flux vector
487  // q_i = mu/Re/Pr * (dT/dx_i)
488  // Re = 100, Pr = 0.75, mu and lambda set above from T=3.5
489  // gridmetrics are applied by ComputeHeatFlux, so account for this here
490  std::vector<double> heatFluxExpected;
491  for(int iDim = 0;iDim < numDim;iDim++)
492  heatFluxExpected.push_back(Cp*tempMu/Pr/Re*(iDim+1)*gridMetric[iDim]*gridJacobian[0]);
493 
494  // Compare expected against actual
495  bool heatFluxFailed=false;
496  bool computeHeatFluxWorks=true;
497  for(int i=0;i<numDim;i++){
498  bool printHeatFlux=true;
499  for(int iNode = 0;iNode < numNodesDomain;iNode++){
500  double error = std::abs((myHeatFluxBuffer[i][iNode] - heatFluxExpected[i])/
501  heatFluxExpected[i]);
502  if(error > 1e-15){
503  computeHeatFluxWorks = false;
504  heatFluxFailed = true;
505  if(printHeatFlux) {
506  std::cout << "In ComputeHeatFluxTest, Expected heatFlux[" << i << "]="
507  << heatFluxExpected[i]
508  << " got heatFlux=" << myHeatFluxBuffer[i][iNode] << " at iNode="
509  << iNode << " error=" << error << std::endl;
510  std::cout << "No further error messages will be generated for this q index"
511  << std::endl;
512  printHeatFlux=false;
513  }
514  }
515  }
516  }
517  dimComputeHeatFlux[numDim-2] = computeHeatFluxWorks;
518  if(heatFluxFailed){
519  std::cout << "Heat flux failed" << std::endl;
520  }
521  std::cout << "Done running tests for " << numDim
522  << "D ComputeHeatFlux" << std::endl;
523 
524  //
525  // now test the computation of the viscous flux terms
526  // This is completely fabricated and non-physical as the velocity
527  // is inconsistent with the velocity gradient.
528  //
529  std::cout << "Running tests for " << numDim
530  << "D viscous flux" << std::endl;
531 
532  std::vector<size_t> fortranBufferInterval(2*numDim,1);
533  for(int iDim = 0;iDim < numDim;iDim++){
534  fortranBufferInterval[2*iDim+1] = bufferInterval[2*iDim+1] + 1;
535  }
536 
537  for(int iDim = 0;iDim < numDim;iDim++){
538  vBuffers[iDim] = &velocity[iDim*numNodesDomain];
539  }
540 
541  // New sequence:
542  // Compute v_i, tau_i_j and -q_i (done above in original test)
543  // Compute the energy flux vector Q_i = (v_j * tau_i_j + q_i)
544  // Use new flux routine (viscidstrongflux1d) to get viscous fluxes:
545  // momentum terms = metric * tau
546  // energy term = metric * Q
547 
548  for(int iDim = 0;iDim < numDim;iDim++){
549  // Compute q_i += (v_j * tau_i_j)
550  for(int iVel = 0;iVel < numDim;iVel++){
551  int tensorIndex = iDim*numDim + iVel;
552  size_t dirOffset = iVel*numNodesDomain;
553 
555  (&numDim,&numNodesDomain,&numNodes[0],&fortranBufferInterval[0],
556  &velocity[dirOffset],myTauBuffer[tensorIndex],myHeatFluxBuffer[iDim]);
557  }
558  }
559 
560  // Check expected v * tau
561  for(int iDim = 0;iDim < numDim;iDim++){
562  bool triggered = false;
563  double expectedValue = 0;
564  for(int iVel = 0;iVel < numDim;iVel++){
565  int tensorIndex = iDim*numDim + iVel;
566  expectedValue += (vVec[iVel] * tauExpected[tensorIndex]);
567  }
568  expectedValue += heatFluxExpected[iDim];
569  for(size_t iPoint = 0;iPoint < numNodesDomain;iPoint++){
570  if((std::abs(myHeatFluxBuffer[iDim][iPoint] - expectedValue)/std::abs(expectedValue)) >
571  1e-12){
572  dimComputeTEF[nDim-2] = false;
573  if(!triggered){
574  std::cout << "Failed in " << (iDim+1) << "/" << numDim
575  << " dimension " << std::endl;
576  std::cout << "TEF(" << iPoint << ") [r,e] = [" << myHeatFluxBuffer[iDim][iPoint]
577  << "," << expectedValue << "]" << std::endl;
578  triggered = true;
579  }
580  }
581  }
582  }
583 
584  for(int iDim = 0;iDim < numDim;iDim++){
585 
586  std::vector<double> viscidFlux(numNodesDomain*(numDim+2),0.0);
587  std::vector<double> expectedFlux((numDim+2)*numNodesDomain,0.0);
588  std::vector<double> scaledTau(numNodesDomain,0.0);
589 
590  for(size_t iPoint = 0;iPoint < numNodesDomain;iPoint++){
591  size_t fOffset = 0;
592 
593  for(int ivDim = 0;ivDim < numDim;ivDim++){
594  size_t iOffset = ivDim*numNodesDomain;
595  fOffset = iOffset + numNodesDomain;
596  size_t vectorOffset = ivDim*numNodesDomain;
597 
598  // momentum
599  int tauIndex=iDim*numDim+ivDim;
600  expectedFlux[iPoint+fOffset] += tauExpected[tauIndex]*gridMetric[iDim];
601 
602  // energy
603  expectedFlux[iPoint+(numDim+1)*numNodesDomain] +=
604  tauExpected[tauIndex]*velocity[vectorOffset+iPoint]*gridMetric[iDim];
605  }
606 
607  // thermal conduction
608  expectedFlux[iPoint+(numDim+1)*numNodesDomain] +=
609  heatFluxExpected[iDim]*gridMetric[iDim];
610 
611  fOffset += numNodesDomain;
612  }
613 
614  int fluxDim = iDim + 1;
615  int tau1=iDim*numDim;
616  int tau2=tau1+1;
617  int tau3=tau2+1;
618 
619  FC_MODULE(viscid,strongflux1d,VISCID,STRONGFLUX1D)
620  (&numDim,&fluxDim,&numNodes[0],&numNodesDomain,&fortranBufferInterval[0],
621  &gridType,&gridMetric[0],&myTau[0],&myHeatFlux[0],&viscidFlux[0]);
622 
623  std::vector<bool> uniformFlux(numDim+2,true);
624  for(int fDim = 0 ;fDim < (numDim+2);fDim++){
625  size_t fOffset = fDim * numNodesDomain;
626  bool triggered = false;
627  for(size_t iPoint = 0;iPoint < numNodesDomain;iPoint++){
628  double error= std::abs((viscidFlux[fOffset+iPoint] - expectedFlux[fOffset+iPoint])/
629  expectedFlux[fOffset+iPoint]);
630  if(error > 1e-10){
631  if(!triggered ){
632  std::cout << "iDim " << iDim << " Flux Dimension " << fDim << std::endl;
633  std::cout << std::scientific << std::setprecision(16)
634  << "\tActual: " << viscidFlux[fOffset+iPoint] << std::endl
635  << "\tExpected: " << expectedFlux[fOffset+iPoint] << std::endl
636  << "\tError: " << error << std::endl;
637  triggered = true;
638  }
639  uniformFlux[fDim] = false;
640  }
641  }
642  }
643  for(int fDim = 0;fDim < (numDim+2);fDim++){
644  if(!uniformFlux[fDim]){
645  dimViscidUniformFlux[numDim-2] = false;
646  std::cout << "uniform flux failed in dim,fdim " << iDim
647  << "," << fDim << std::endl;
648  }
649  }
650  std::cout << "Done running tests for "<<numDim<<"D viscous flux" << std::endl;
651 
652  } // loop over iDim
653  }
654 
655  bool computeDVWorks = true;
656  bool computeTVWorks = true;
657  bool computeStressTensorWorks = true;
658  bool computeHeatFluxWorks = true;
659  bool viscidUniformFluxWorks = true;
660  bool computeTotalEnergyFlux = true;
661  // Make sure these tests worked in 2d and 3d
662  for(int nDim = 2;nDim <= 3;nDim++){
663  // compute DV tests are temporay until I have computeTV working
664  computeDVWorks = computeDVWorks && dimComputeDV2[nDim-2];
665  computeTVWorks = computeTVWorks && dimComputeTV[nDim-2];
666  computeTotalEnergyFlux = computeTotalEnergyFlux && dimComputeTEF[nDim-2];
667  computeStressTensorWorks = computeStressTensorWorks && dimComputeStressTensor[nDim-2];
668  computeHeatFluxWorks = computeHeatFluxWorks && dimComputeHeatFlux[nDim-2];
669  viscidUniformFluxWorks = viscidUniformFluxWorks && dimViscidUniformFlux[nDim-2];
670  }
671 
672  serialUnitResults.UpdateResult("Viscid:Kernels:ComputeTEF",computeTotalEnergyFlux);
673  serialUnitResults.UpdateResult("Viscid:Kernels:DV",computeDVWorks);
674  serialUnitResults.UpdateResult("Viscid:Kernels:TV",computeTVWorks);
675  serialUnitResults.UpdateResult("Viscid:Kernels:StressTensor",computeStressTensorWorks);
676  serialUnitResults.UpdateResult("Viscid:Kernels:HeatFlux",computeHeatFluxWorks);
677  serialUnitResults.UpdateResult("Viscid:Kernels:UniformViscidFlux",viscidUniformFluxWorks);
678 
679 };
690 {
691 
693  const std::string functionName("TestViscidKernelsMetrics");
694 
695  std::cout << "Running " << functionName << std::endl;
696 
697  bool testResult = true;
698 
699  // multi-dimension test results
700  std::vector<bool> dimComputeDV(2,false);
701  std::vector<bool> dimComputeTV(2,false);
702  std::vector<bool> dimComputeStressTensor(2,false);
703  std::vector<bool> dimComputeHeatFlux(2,false);
704  std::vector<bool> dimComputeDV2(2,true);
705  std::vector<bool> dimComputeTEF(2,true);
706 
707  std::vector<bool> dimViscidUniformFlux(2,true);
708 
709  std::vector<bool> metricSuccess(simulation::grid::NUMGRIDTYPES,true);
710 
713  gridType++){
714  std::cout << "Testing viscid kernels with "
715  << (gridType <= simulation::grid::UNIRECT ? " Uniform-rectangular " :
716  gridType == simulation::grid::RECTILINEAR ? " Rectilinear " :
717  " Curvilinear ") << " metrics." << std::endl;
718 
719  // -- Set up the grid --
720  for(int nDim = 2;nDim <= 3;nDim++){
721 
722 
723  std::cout << "Testing viscid kernels in " << nDim << " dimensions." << std::endl;
724  grid_t testGrid;
725  int numDim = nDim;
726 
727  std::vector<double> &realGridExtent(testGrid.PhysicalExtent());
728  realGridExtent.resize(numDim*2,0.0);
729  for(int iDim = 0;iDim < numDim;iDim++)
730  realGridExtent[iDim*2 + 1] = 1.0;
731 
732  std::vector<size_t> &numNodes(testGrid.GridSizes());
733  numNodes.resize(numDim);
734  numNodes[0] = 11;
735  numNodes[1] = 101;
736  if(numDim == 3)
737  numNodes[2] = 1001;
738 
739  size_t numNodesDomain = 1;
740  size_t numCellsDomain = 1;
741  for(int iDim = 0;iDim < numDim;iDim++){
742  numNodesDomain *= numNodes[iDim];
743  numCellsDomain *= (numNodes[iDim]-1);
744  }
745 
746  std::vector<double> dX;
747  std::vector<double> gridMetric;
748  std::vector<double> gridJacobian;
749 
750  if(gridType <= simulation::grid::UNIRECT){
751  dX.resize(numDim,0.0);
752  gridMetric.resize(numDim,0.0);
753  gridJacobian.resize(1,1.0);
754  for(int iDim = 0;iDim < numDim;iDim++){
755  dX[iDim] = (realGridExtent[iDim*2+1] - realGridExtent[iDim*2])/(numNodes[iDim]-1);
756  gridMetric[iDim] = 1.0/dX[iDim];
757  gridJacobian[0] *= gridMetric[iDim];
758  }
759  testGrid.SetGridSpacings(dX);
760  } else if(gridType == simulation::grid::RECTILINEAR){
761  dX.resize(numDim*numNodesDomain,0.0);
762  gridMetric.resize(numDim*numNodesDomain,0.0);
763  gridJacobian.resize(numNodesDomain,1.0);
764  for(int iDim = 0;iDim < numDim;iDim++){
765  size_t dimOffset = iDim*numNodesDomain;
766  for(size_t iPoint = 0;iPoint < numNodesDomain;iPoint++){
767  dX[dimOffset+iPoint] = (realGridExtent[iDim*2+1] - realGridExtent[iDim*2])/(numNodes[iDim]-1);
768  gridMetric[dimOffset+iPoint] = 1.0/dX[dimOffset+iPoint];
769  gridJacobian[iPoint] *= gridMetric[dimOffset+iPoint];
770  }
771  }
772  } else {
773  dX.resize(numDim*numDim*numNodesDomain,0.0);
774  gridMetric.resize(numDim*numDim*numNodesDomain,0.0);
775  gridJacobian.resize(numNodesDomain,0.0);
776  for(int iDim = 0;iDim < numDim;iDim++){
777  size_t iIndex = iDim*numDim;
778  for(int jDim = 0;jDim < numDim;jDim++){
779  size_t ijIndex = iIndex + jDim;
780  size_t metricOffset = ijIndex*numNodesDomain;
781  if(iDim == jDim){
782  for(int iPoint = 0;iPoint < numNodesDomain;iPoint++){
783  dX[metricOffset+iPoint] = (realGridExtent[iDim*2+1] - realGridExtent[iDim*2])/(numNodes[iDim]-1);
784  gridMetric[metricOffset+iPoint] = 1.0/dX[metricOffset+iPoint];
785  gridJacobian[iPoint] *= gridMetric[metricOffset+iPoint];
786  }
787  }
788  }
789  }
790  }
791  if(testGrid.Finalize()){
792  std::cout << "Grid finalization failed." << std::endl;
793  return;
794  }
795 
796  std::vector<size_t> bufferInterval;
797  testGrid.PartitionBufferInterval().Flatten(bufferInterval);
798 
799  double a = 1.0;
800  double t = 1.0;
801  double gamma = 1.4;
802  double specGasConst = 1.0;
803  double dt = 1.0;
804  double cfl = 1.0;
805  std::vector<double> vVec(numDim,0.0);
806  vVec[0] = 1.0;
807  vVec[1] = -1.0;
808  if(numDim == 3) vVec[2] = 2.0;
809  double v = vVec[0];
810 
811  // in non-dimensional, ideal gas, P=rho*R*T (R=1)
812  double pressure = 1.0;
813  double density = 1.2;
814  double temperature = pressure/density/specGasConst;
815 
816  std::vector<double> expectedRhoM1(numNodesDomain,1.0/density);
817  std::vector<double> expectedFlux((numDim+2)*numNodesDomain,0.0);
818  std::vector<double> expectedPressure(numNodesDomain,pressure);
819  std::vector<double> expectedTemperature(numNodesDomain,temperature);
820  std::vector<double> expectedVHat(numDim*numNodesDomain,0.0);
821  std::vector<double> expectedVelocity(numDim*numNodesDomain,0.0);
822  std::vector<double> expectedRHS((numDim+2)*numNodesDomain,0.0);
823 
824  std::vector<double> ke(numNodesDomain,0.0);
825  std::vector<double> rho(numNodesDomain,density);
826  std::vector<double> rhoV(numDim*numNodesDomain,1.0);
827  std::vector<double> rhoE(numNodesDomain,0.0); // calculated below
828  // dX = <.1,.01,.001>
829  // Velocity = <1.0,-1.0,0>
830  // rhoV = 1.0 * Velocity
831  // vHat = V * xiHat
832 
833  for(int iDim = 0;iDim < numDim;iDim++){
834  double dx = dX[iDim];
835  if(gridType == simulation::grid::RECTILINEAR){
836  dx = dX[iDim*numNodesDomain];
837  } else if (gridType == simulation::grid::CURVILINEAR) {
838  dx = dX[iDim*numDim*numNodesDomain];
839  }
840  for(int iPoint = 0;iPoint < numNodesDomain;iPoint++){
841  rhoV[iDim*numNodesDomain + iPoint] = rho[iPoint]*vVec[iDim];
842  ke[iPoint] += .5*rho[iPoint]*vVec[iDim]*vVec[iDim];
843  expectedVelocity[iDim*numNodesDomain+iPoint] = vVec[iDim];
844  expectedVHat[iDim*numNodesDomain+iPoint] = vVec[iDim]/dx;
845  }
846  }
847  // rhoE = [1.0/(gamma-1.0) + .5*rhoV*Velocity]
848  for(int iPoint = 0;iPoint < numNodesDomain;iPoint++){
849  //rhoE[iPoint] = 1.0/(gamma-1.0) + ke[iPoint];
850  rhoE[iPoint] = expectedPressure[iPoint]/(gamma-1.0)+ ke[iPoint];
851  }
852 
853  std::vector<double> T(numNodesDomain,0.0);
854  std::vector<double> p(numNodesDomain,0.0);
855  std::vector<double> rhom1(numNodesDomain,0.0);
856  std::vector<double> velocity(numDim*numNodesDomain,-.1);
857  std::vector<double> internalEnergy(numNodesDomain,0.);
858 
859  std::vector<double *> vBuffers(numDim,(double *)NULL);
860  for(int iDim = 0;iDim < numDim;iDim++)
861  vBuffers[iDim] = &velocity[iDim*numNodesDomain];
862 
863  bool computeDVWorks = true;
864  bool pfailed = false;
865  bool tfailed = false;
866  bool rfailed = false;
867  bool vfailed = false;
868 
869  T.resize(0);
870  p.resize(0);
871  velocity.resize(0);
872  rhom1.resize(0);
873  T.resize(numNodesDomain,0.0);
874  p.resize(numNodesDomain,0.0);
875  velocity.resize(numDim*numNodesDomain,-.1);
876  rhom1.resize(numNodesDomain,0.0);
877 
878  std::vector<double *> myStateBuffers(numDim+2,NULL);
879  myStateBuffers[0] = &rho[0];
880  for(int iDim = 0;iDim < numDim;iDim++)
881  myStateBuffers[iDim+1] = &rhoV[iDim*numNodesDomain];
882  myStateBuffers[numDim+1] = &rhoE[0];
883 
884  std::vector<double *> myDVBuffers(4+numDim,NULL);
885  myDVBuffers[0] = &p[0];
886  myDVBuffers[1] = &T[0];
887  myDVBuffers[2] = &rhom1[0];
888 
889  for(int iDim = 0;iDim < numDim;iDim++){
890  vBuffers[iDim] = &velocity[iDim*numNodesDomain];
891  myDVBuffers[3+iDim] = vBuffers[iDim];
892  }
893  myDVBuffers[numDim+3] = &internalEnergy[0];
894 
895  pcpp::IndexIntervalType bufferExtent;
896  bufferExtent.InitSimple(numNodes);
897 
898  // setup a new equation of state object for this grid
899  eos::perfect_gas myEOS;
900  //myEOS.InitializeBufferExtents(bufferExtent,numNodes);
901  myEOS.SetupPressureBuffer(&p[0]);
902  myEOS.SetupTemperatureBuffer(&T[0]);
903  myEOS.SetupSpecificVolumeBuffer(&rhom1[0]);
904  myEOS.SetupInternalEnergyBuffer(&internalEnergy[0]);
905 
906  myEOS.SetSpecificGasConstant(specGasConst);
907  myEOS.SetGamma(gamma);
908 
909  if(myEOS.InitializeMaterialProperties()){
910  std::cout << "Failed to initialize EOS" << std::endl;
911  }
912 
913  if(euler::util::ComputeDVBuffer(bufferExtent,numNodes,myStateBuffers,myDVBuffers))
914  {
915  std::cout << "ComputeDVBuffer failed." << std::endl;
916  }
917 
918  // now calculate the pressure and temperature
919  if(myEOS.ComputePressureBuffer(bufferExtent,numNodes)) {
920  std::cout << "ComputePressure failed." << std::endl;
921  }
922 
923  if(myEOS.ComputeTemperatureBuffer(bufferExtent,numNodes)) {
924  std::cout << "ComputeTemperature failed." << std::endl;
925  }
926 
927 
928  bool printPressure=true;
929  bool printTemperature=true;
930  bool printVelocity=true;
931  bool printVolume=true;
932  for(int iNode = 0;iNode < numNodesDomain;iNode++){
933  if(std::abs(p[iNode] - expectedPressure[iNode]) > 1e-15){
934  computeDVWorks = false;
935  if(printPressure) {
936  std::cout << "In ComputeDVTest, Expected pressure=" << expectedPressure[iNode]
937  << " got pressure=" << p[iNode] << " at iNode=" << iNode << std::endl;
938  std::cout << "No further error messages will be generated for pressure" << std::endl;
939  printPressure=false;
940  }
941  }
942  if(std::abs(T[iNode] - expectedTemperature[iNode]) > 1e-15){
943  computeDVWorks = false;
944  if(printTemperature) {
945  std::cout << "In ComputeDVTest, Expected temperature=" << expectedTemperature[iNode]
946  << " got temperature=" << T[iNode] << " at iNode=" << iNode << std::endl;
947  std::cout << "No further error messages will be generated for temperature" << std::endl;
948  printTemperature=false;
949  }
950  }
951  if(std::abs(rhom1[iNode] - expectedRhoM1[iNode]) > 1e-15){
952  computeDVWorks = false;
953  if(printVolume) {
954  std::cout << "In ComputeDVTest, Expected volume=" << expectedRhoM1[iNode]
955  << " got volume=" << rhom1[iNode] << " at iNode=" << iNode << std::endl;
956  std::cout << "No further error messages will be generated for volume" << std::endl;
957  printVolume=false;
958  }
959  }
960  for(int iDim = 0;iDim < numDim;iDim++){
961  if(std::abs(velocity[iDim*numNodesDomain+iNode] -
962  expectedVelocity[iDim*numNodesDomain+iNode]) > 1e-15){
963  computeDVWorks = false;
964  if(printVelocity) {
965  std::cout << "In ComputeDVTest, Expected velocity=" << expectedVelocity[iNode]
966  << " got velocity=" << velocity[iNode] << " at iNode="
967  << iNode << " iDim=" << iDim << std::endl;
968  std::cout << "No further error messages will be generated for velocity" << std::endl;
969  printVelocity=false;
970  }
971  }
972  }
973  }
974 
975  dimComputeDV2[numDim-2] = computeDVWorks ;
976 
977  //
978  // test calculation of the transport coefficients
979  //
980  std::cout << "Running tests for "<<numDim<<"D ComputeTV" << std::endl;
981 
982  std::vector<double> mu(numNodesDomain,0.0);
983  std::vector<double> lambda(numNodesDomain,0.0);
984  std::vector<double> kappa(numNodesDomain,0.0);
985 
986  std::vector<double *> myTVBuffers(3,NULL);
987  myTVBuffers[0] = &mu[0];
988  myTVBuffers[1] = &lambda[0];
989  myTVBuffers[2] = &kappa[0];
990 
991 
992  double power = 0.666;
993  double beta = 5;
994  double bulkViscFac = 2;
995  double Cp = gamma/(gamma-1);
996  double Pr = 0.75;
997  double tempMu = beta*pow(expectedTemperature[0],power);
998  double tempLambda = (bulkViscFac - 2.0/3.0)*tempMu;
999  double tempKappa = Cp*tempMu/Pr;
1000  std::vector<double> expectedMu(numNodesDomain,tempMu);
1001  std::vector<double> expectedLambda(numNodesDomain,tempLambda);
1002  std::vector<double> expectedKappa(numNodesDomain,tempKappa);
1003  bool computeTVWorks=true;
1004  bool muFailed = false;
1005  bool lambdaFailed = false;
1006  bool kappaFailed = false;
1007 
1009  bufferExtent,numNodes,myDVBuffers[1],myTVBuffers,beta,power,bulkViscFac,Cp,Pr))
1010  {
1011  std::cout << "ComputeTVBuffer failed." << std::endl;
1012  }
1013 
1014  bool printMu = true;
1015  bool printLambda = true;
1016  bool printKappa = true;
1017  double error = 1;
1018  for(int iNode = 0;iNode < numNodesDomain;iNode++){
1019  error = std::abs((mu[iNode] - expectedMu[iNode])/expectedMu[iNode]);
1020  if(error > 1e-15){
1021  computeTVWorks = false;
1022  muFailed = true;
1023  if(printMu) {
1024  std::cout << "In ComputeTvTest, Expected mu=" << expectedMu[iNode]
1025  << " got mu=" << mu[iNode] << " at iNode=" << iNode << std::endl;
1026  std::cout << "Temperature was " << T[iNode] << std::endl;
1027  std::cout << "No further error messages will be generated for mu" << std::endl;
1028  printMu=false;
1029  }
1030  }
1031  error = std::abs((lambda[iNode] - expectedLambda[iNode])/expectedLambda[iNode]);
1032  if(error > 1e-15){
1033  computeTVWorks = false;
1034  lambdaFailed = true;
1035  if(printLambda) {
1036  std::cout << "In ComputeTvTest, Expected lambda=" << expectedLambda[iNode]
1037  << " got lambda=" << lambda[iNode] << " at iNode=" << iNode << std::endl;
1038  std::cout << "Temperature was " << T[iNode] << std::endl;
1039  std::cout << "No further error messages will be generated for lambda" << std::endl;
1040  printLambda=false;
1041  }
1042  }
1043  error = std::abs((kappa[iNode] - expectedKappa[iNode])/expectedKappa[iNode]);
1044  if(error > 1e-15){
1045  computeTVWorks = false;
1046  kappaFailed = true;
1047  if(printKappa) {
1048  std::cout << "In ComputeTvTest, Expected kappa=" << expectedKappa[iNode]
1049  << " got kappa=" << kappa[iNode] << " at iNode=" << iNode << std::endl;
1050  std::cout << "Temperature was " << T[iNode] << std::endl;
1051  std::cout << "No further error messages will be generated for kappa" << std::endl;
1052  printKappa=false;
1053  }
1054  }
1055  }
1056 
1057  dimComputeTV[numDim-2] = computeTVWorks;
1058  if(muFailed){
1059  std::cout << "Mu failed" << std::endl;
1060  }
1061  if(lambdaFailed){
1062  std::cout << "Lambda failed" << std::endl;
1063  }
1064  if(kappaFailed){
1065  std::cout << "Kappa failed" << std::endl;
1066  }
1067 
1068  std::cout << "Done running tests for "<<numDim<<"D ComputeTV" << std::endl;
1069  std::cout << "Running tests for "<<numDim<<"D ComputeStressTensor" << std::endl;
1070 
1071  // build a velocity gradient so we can test the calculation of the stress tensor
1072  // in 3D...
1073  // | du/dxi dv/dxi dw/dxi | | [1..1] [2..2] [3..3]
1074  // | du/deta dv/deta dw/deta | = | [4..4] [5..5] [6..6]
1075  // | du/dzeta dv/dzeta dw/dzeta | | [7..7] [8..8] [9..9]
1076  std::vector<double *> myVelGradBuffer(numDim,NULL);
1077  for(int i=0;i<numDim;i++){
1078  myVelGradBuffer[i] = new double [numDim*numNodesDomain];
1079  for(int j=0;j<numDim;j++){
1080  int offset=j*numNodesDomain;
1081  double value = static_cast<double>(i*numDim+j+1);
1082  for(int k=0;k<numNodesDomain;k++){
1083  //if(k==0){
1084  //std::cout << "i, j, velGrad" << i << " " << j << " " << value << std::endl;
1085  //}
1086  myVelGradBuffer[i][offset+k]=value;
1087  }
1088  }
1089  }
1090 
1091  // calculate the stress tensor
1092  // the stress tensor is symmetric and stored in memory like (in 3D)
1093  // [ {tau11} {tau12} {tau13} {tau22} {tau23} {tau33} ]
1094  // myTauBuffer has pointers into memory for all numDim^2 components
1095  // [ {tau11} {tau12} {tau13} {tau22} {tau23} {tau33} ]
1096  std::vector<double *> myTauBuffer(numDim*numDim,NULL);
1097  std::vector<double> myTau(numDim*(numDim+1)*numNodesDomain/2,0);
1098  size_t bufferIndex = 0;
1099  for(int i=0;i<numDim;i++){
1100  for(int j=0;j<numDim;j++){
1101  int index = i*numDim + j;
1102  if (i <= j){
1103  myTauBuffer[index] = &myTau[bufferIndex];
1104  bufferIndex += numNodesDomain;
1105  } else {
1106  myTauBuffer[index] = myTauBuffer[j*numDim+i];
1107  }
1108  }
1109  }
1110 
1111  double Re = 100.;
1112  if(viscid::util::ComputeTauBuffer(bufferExtent, numNodes, gridType, gridMetric, gridJacobian, Re,
1113  myTVBuffers, myVelGradBuffer, myTauBuffer)){
1114  std::cout << "Calculation of the stress tensor failed" << std::endl;
1115  }
1116 
1117  // Construct the expected stress tensor
1118  // tau_ij = mu/Re * (dv_i/dx_j+dv_j/dx_i) + lambda/Re * (dv_k/dx_k) delta_ij
1119  // Re = 100, mu and lambda set above from T=3.5
1120  // gridmetrics are applied by ComputeStressTensor, so account for this here
1121  std::vector<double> tauExpected;
1122 
1123  if(numDim == 2){
1124 
1125  double metricX = gridMetric[0];
1126  double metricY = gridMetric[1];
1127 
1128  if(gridType == simulation::grid::RECTILINEAR) {
1129  metricY = gridMetric[numNodesDomain];
1130  } else if (gridType == simulation::grid::CURVILINEAR) {
1131  metricY = gridMetric[3*numNodesDomain];
1132  }
1133 
1134  tauExpected.push_back(tempMu/Re*(1*metricX+1*metricX)
1135  + tempLambda/Re*(1*metricX+4*metricY));//tau_11
1136  tauExpected.push_back(tempMu/Re*(2*metricX+3*metricY)); //tau_12
1137  tauExpected.push_back(tempMu/Re*(2*metricX+3*metricY)); //tau_21 = tau_12
1138  tauExpected.push_back(tempMu/Re*(4*metricY+4*metricY)
1139  + tempLambda/Re*(1*metricX+4*metricY));//tau_22
1140 
1141  } else {
1142 
1143  // | du/dxi dv/dxi dw/dxi | | [1..1] [2..2] [3..3]
1144  // | du/deta dv/deta dw/deta | = | [4..4] [5..5] [6..6]
1145  // | du/dzeta dv/dzeta dw/dzeta | | [7..7] [8..8] [9..9]
1146  // dxidx = metric[0]
1147  // detady = metric[1]
1148  // dzetadz = metric[2]
1149  double metricX = gridMetric[0];
1150  double metricY = gridMetric[1];
1151  double metricZ = gridMetric[2];
1152  if(gridType == simulation::grid::RECTILINEAR){
1153  metricY = gridMetric[numNodesDomain];
1154  metricZ = gridMetric[2*numNodesDomain];
1155  } else if (gridType == simulation::grid::CURVILINEAR){
1156  metricY = gridMetric[4*numNodesDomain];
1157  metricZ = gridMetric[8*numNodesDomain];
1158  }
1159 
1160  tauExpected.push_back(tempMu/Re*(1*metricX+1*metricX)
1161  + tempLambda/Re*(1*metricX+5*metricY+9*metricZ)); //tau_11
1162  tauExpected.push_back(tempMu/Re*(2*metricX+4*metricY)); //tau_12
1163  tauExpected.push_back(tempMu/Re*(3*metricX+7*metricZ)); //tau_13
1164  tauExpected.push_back(tempMu/Re*(2*metricX+4*metricY)); //tau_21 = tau12
1165  tauExpected.push_back(tempMu/Re*(5*metricY+5*metricY)
1166  + tempLambda/Re*(1*metricX+5*metricY+9*metricZ)); //tau_22
1167  tauExpected.push_back(tempMu/Re*(6*metricY+8*metricZ)); //tau_23
1168  tauExpected.push_back(tempMu/Re*(3*metricX+7*metricZ)); //tau_31 = tau13
1169  tauExpected.push_back(tempMu/Re*(6*metricY+8*metricZ)); //tau_32 = tau23
1170  tauExpected.push_back(tempMu/Re*(9*metricZ+9*metricZ)
1171  + tempLambda/Re*(1*metricX+5*metricY+9*metricZ)); //tau_33
1172  }
1173 
1174  for(int i=0;i<tauExpected.size();i++){
1175  tauExpected[i] *= gridJacobian[0];
1176  }
1177 
1178  // Compare expected against actual
1179  bool tauFailed=false;
1180  bool computeTauWorks=true;
1181  for(int i=0;i<numDim*numDim;i++){
1182  bool printTau=true;
1183  for(int iNode = 0;iNode < numNodesDomain;iNode++){
1184  double error = std::abs((myTauBuffer[i][iNode] - tauExpected[i])/tauExpected[i]);
1185  if(error > 1e-15){
1186  computeTauWorks = false;
1187  tauFailed = true;
1188  if(printTau) {
1189  std::cout << "In ComputeTauTest, Expected tau[" << i << "]=" << tauExpected[i]
1190  << " got tau=" << myTauBuffer[i][iNode] << " at iNode=" << iNode
1191  << " error=" << error << std::endl;
1192  std::cout << "No further error messages will be generated for this tau index"
1193  << std::endl;
1194  printTau=false;
1195  }
1196  }
1197  }
1198  }
1199  dimComputeStressTensor[numDim-2] = computeTauWorks;
1200  if(tauFailed){
1201  std::cout << "Tau failed" << std::endl;
1202  }
1203  std::cout << "Done running tests for "<<numDim<<"D ComputeStressTensor" << std::endl;
1204 
1205  std::cout << "Running tests for "<<numDim<<"D ComputeHeatFlux" << std::endl;
1206 
1207  // build a temperature gradient so we can test the calculation of the heat flux vector
1208  // in 3D...
1209  // | dT/d(xi) dT/d(eta) dT/d(zeta) | | [1..1] [2..2] [3..3]
1210  std::vector<double *> myTempGradBuffer(numDim,NULL);
1211  std::vector<double> myTempGrad(numDim*numNodesDomain,0);
1212  for(int i=0;i<numDim;i++){
1213  myTempGradBuffer[i] = &myTempGrad[i*numNodesDomain];
1214  double value = static_cast<double>(i+1);
1215  for(int k=0;k<numNodesDomain;k++){
1216  myTempGradBuffer[i][k]=value;
1217  }
1218  }
1219 
1220  // calculate the heat flux vector
1221  std::vector<double *> myHeatFluxBuffer(numDim,NULL);
1222  std::vector<double> myHeatFlux(numDim*numNodesDomain,0);
1223  for(int i=0;i<numDim;i++){
1224  myHeatFluxBuffer[i] = &myHeatFlux[i*numNodesDomain];
1225  }
1226 
1227  if(viscid::util::ComputeHeatFluxBuffer(bufferExtent, numNodes, gridType,gridMetric,
1228  gridJacobian, Re, myTVBuffers, myTempGradBuffer,
1229  myHeatFluxBuffer)){
1230  std::cout << "Calculation of the heat flux vector failed" << std::endl;
1231  }
1232 
1233  // Construct the expected heat flux vector
1234  // q_i = mu/Re/Pr * (dT/dx_i)
1235  // Re = 100, Pr = 0.75, mu and lambda set above from T=3.5
1236  // gridmetrics are applied by ComputeHeatFlux, so account for this here
1237  std::vector<double> heatFluxExpected;
1238  if (gridType == simulation::grid::RECTILINEAR){
1239  for(int iDim = 0;iDim < numDim;iDim++){
1240  double metric = gridMetric[iDim*numNodesDomain];
1241  double jac = gridJacobian[0];
1242  heatFluxExpected.push_back(Cp*tempMu/Pr/Re*(iDim+1)*metric*jac);
1243  }
1244  } else if(gridType < simulation::grid::CURVILINEAR) {
1245  for(int iDim = 0;iDim < numDim;iDim++){
1246  heatFluxExpected.push_back(Cp*tempMu/Pr/Re*(iDim+1)*gridMetric[iDim]*gridJacobian[0]);
1247  }
1248  } else { // must be curvilinear
1249  for(int iDim = 0;iDim < numDim;iDim++){
1250  double metric = gridMetric[iDim*numDim*numNodesDomain];
1251  double jac = gridJacobian[0];
1252  heatFluxExpected.push_back(Cp*tempMu/Pr/Re*(iDim+1)*metric*jac);
1253  }
1254  }
1255 
1256 
1257  // Compare expected against actual
1258  bool heatFluxFailed=false;
1259  bool computeHeatFluxWorks=true;
1260  for(int i=0;i<numDim;i++){
1261  bool printHeatFlux=true;
1262  for(int iNode = 0;iNode < numNodesDomain;iNode++){
1263  double error = std::abs((myHeatFluxBuffer[i][iNode] - heatFluxExpected[i])/
1264  heatFluxExpected[i]);
1265  if(error > 1e-15){
1266  computeHeatFluxWorks = false;
1267  heatFluxFailed = true;
1268  if(printHeatFlux) {
1269  std::cout << "In ComputeHeatFluxTest, Expected heatFlux[" << i << "]="
1270  << heatFluxExpected[i]
1271  << " got heatFlux=" << myHeatFluxBuffer[i][iNode] << " at iNode="
1272  << iNode << " error=" << error << std::endl;
1273  std::cout << "No further error messages will be generated for this q index"
1274  << std::endl;
1275  printHeatFlux=false;
1276  }
1277  }
1278  }
1279  }
1280  dimComputeHeatFlux[numDim-2] = computeHeatFluxWorks;
1281  if(heatFluxFailed){
1282  std::cout << "Heat flux failed" << std::endl;
1283  }
1284  std::cout << "Done running tests for " << numDim
1285  << "D ComputeHeatFlux" << std::endl;
1286 
1287  //
1288  // now test the computation of the viscous flux terms
1289  // This is completely fabricated and non-physical as the velocity
1290  // is inconsistent with the velocity gradient.
1291  //
1292  std::cout << "Running tests for " << numDim
1293  << "D viscous flux" << std::endl;
1294 
1295  std::vector<size_t> fortranBufferInterval(2*numDim,1);
1296  for(int iDim = 0;iDim < numDim;iDim++){
1297  fortranBufferInterval[2*iDim+1] = bufferInterval[2*iDim+1] + 1;
1298  }
1299 
1300  for(int iDim = 0;iDim < numDim;iDim++){
1301  vBuffers[iDim] = &velocity[iDim*numNodesDomain];
1302  }
1303 
1304  // New sequence:
1305  // Compute v_i, tau_i_j and -q_i (done above in original test)
1306  // Compute the energy flux vector Q_i = (v_j * tau_i_j + q_i)
1307  // Use new flux routine (viscidstrongflux1d) to get viscous fluxes:
1308  // momentum terms = metric * tau
1309  // energy term = metric * Q
1310 
1311  for(int iDim = 0;iDim < numDim;iDim++){
1312  // Compute q_i += (v_j * tau_i_j)
1313  for(int iVel = 0;iVel < numDim;iVel++){
1314  int tensorIndex = iDim*numDim + iVel;
1315  size_t dirOffset = iVel*numNodesDomain;
1316 
1318  (&numDim,&numNodesDomain,&numNodes[0],&fortranBufferInterval[0],
1319  &velocity[dirOffset],myTauBuffer[tensorIndex],myHeatFluxBuffer[iDim]);
1320  }
1321  }
1322 
1323  // Check expected v * tau
1324  for(int iDim = 0;iDim < numDim;iDim++){
1325  bool triggered = false;
1326  double expectedValue = 0;
1327  for(int iVel = 0;iVel < numDim;iVel++){
1328  int tensorIndex = iDim*numDim + iVel;
1329  expectedValue += (vVec[iVel] * tauExpected[tensorIndex]);
1330  }
1331  expectedValue += heatFluxExpected[iDim];
1332  for(size_t iPoint = 0;iPoint < numNodesDomain;iPoint++){
1333  if((std::abs(myHeatFluxBuffer[iDim][iPoint] - expectedValue)/std::abs(expectedValue)) >
1334  1e-12){
1335  dimComputeTEF[nDim-2] = false;
1336  if(!triggered){
1337  std::cout << "Failed in " << (iDim+1) << "/" << numDim
1338  << " dimension " << std::endl;
1339  std::cout << "TEF(" << iPoint << ") [r,e] = [" << myHeatFluxBuffer[iDim][iPoint]
1340  << "," << expectedValue << "]" << std::endl;
1341  triggered = true;
1342  }
1343  }
1344  }
1345  }
1346 
1347 
1348  for(int iDim = 0;iDim < numDim;iDim++){
1349 
1350  double metricX = gridMetric[iDim];
1351 
1352  if(gridType == simulation::grid::RECTILINEAR) {
1353  metricX = gridMetric[iDim*numNodesDomain];
1354  } else if (gridType == simulation::grid::CURVILINEAR) {
1355  metricX = gridMetric[iDim*numDim*numNodesDomain];
1356  }
1357 
1358  std::vector<double> viscidFlux(numNodesDomain*(numDim+2),0.0);
1359  std::vector<double> expectedFlux((numDim+2)*numNodesDomain,0.0);
1360  std::vector<double> scaledTau(numNodesDomain,0.0);
1361 
1362  for(size_t iPoint = 0;iPoint < numNodesDomain;iPoint++){
1363  size_t fOffset = 0;
1364 
1365  for(int ivDim = 0;ivDim < numDim;ivDim++){
1366  size_t iOffset = ivDim*numNodesDomain;
1367  fOffset = iOffset + numNodesDomain;
1368  size_t vectorOffset = ivDim*numNodesDomain;
1369 
1370  // momentum
1371  int tauIndex=iDim*numDim+ivDim;
1372  expectedFlux[iPoint+fOffset] += tauExpected[tauIndex]*metricX;
1373 
1374  // energy
1375  expectedFlux[iPoint+(numDim+1)*numNodesDomain] +=
1376  tauExpected[tauIndex]*velocity[vectorOffset+iPoint]*metricX;
1377  }
1378 
1379  // thermal conduction
1380  expectedFlux[iPoint+(numDim+1)*numNodesDomain] +=
1381  heatFluxExpected[iDim]*metricX;
1382 
1383  fOffset += numNodesDomain;
1384  }
1385 
1386  int fluxDim = iDim + 1;
1387  int tau1=iDim*numDim;
1388  int tau2=tau1+1;
1389  int tau3=tau2+1;
1390 
1391  FC_MODULE(viscid,strongflux1d,VISCID,STRONGFLUX1D)
1392  (&numDim,&fluxDim,&numNodes[0],&numNodesDomain,&fortranBufferInterval[0],
1393  &gridType,&gridMetric[0],&myTau[0],&myHeatFlux[0],&viscidFlux[0]);
1394 
1395  std::vector<bool> uniformFlux(numDim+2,true);
1396  for(int fDim = 0 ;fDim < (numDim+2);fDim++){
1397  size_t fOffset = fDim * numNodesDomain;
1398  bool triggered = false;
1399  for(size_t iPoint = 0;iPoint < numNodesDomain;iPoint++){
1400  double error= std::abs((viscidFlux[fOffset+iPoint] - expectedFlux[fOffset+iPoint])/
1401  expectedFlux[fOffset+iPoint]);
1402  if(error > 1e-10){
1403  if(!triggered ){
1404  std::cout << "iDim " << iDim << " Flux Dimension " << fDim << std::endl;
1405  std::cout << std::scientific << std::setprecision(16)
1406  << "\tActual: " << viscidFlux[fOffset+iPoint] << std::endl
1407  << "\tExpected: " << expectedFlux[fOffset+iPoint] << std::endl
1408  << "\tError: " << error << std::endl;
1409  triggered = true;
1410  }
1411  uniformFlux[fDim] = false;
1412  }
1413  }
1414  }
1415  for(int fDim = 0;fDim < (numDim+2);fDim++){
1416  if(!uniformFlux[fDim]){
1417  dimViscidUniformFlux[numDim-2] = false;
1418  std::cout << "uniform flux failed in dim,fdim " << iDim
1419  << "," << fDim << std::endl;
1420  }
1421  }
1422  std::cout << "Done running tests for "<<numDim<<"D viscous flux" << std::endl;
1423 
1424  } // loop over iDim
1425 
1426  } // nDim
1427 
1428  bool computeDVWorks = true;
1429  bool computeTVWorks = true;
1430  bool computeStressTensorWorks = true;
1431  bool computeHeatFluxWorks = true;
1432  bool viscidUniformFluxWorks = true;
1433  bool computeTotalEnergyFlux = true;
1434  // Make sure these tests worked in 2d and 3d
1435  for(int nDim = 2;nDim <= 3;nDim++){
1436  // compute DV tests are temporay until I have computeTV working
1437  computeDVWorks = computeDVWorks && dimComputeDV2[nDim-2];
1438  computeTVWorks = computeTVWorks && dimComputeTV[nDim-2];
1439  computeTotalEnergyFlux = computeTotalEnergyFlux && dimComputeTEF[nDim-2];
1440  computeStressTensorWorks = computeStressTensorWorks && dimComputeStressTensor[nDim-2];
1441  computeHeatFluxWorks = computeHeatFluxWorks && dimComputeHeatFlux[nDim-2];
1442  viscidUniformFluxWorks = viscidUniformFluxWorks && dimViscidUniformFlux[nDim-2];
1443  }
1444  if(computeStressTensorWorks && computeHeatFluxWorks && viscidUniformFluxWorks)
1445  metricSuccess[gridType] = true;
1446  else {
1447  metricSuccess[gridType] = false;
1448  testResult = false;
1449  }
1450 
1451  } // gridType
1452 
1453 
1454  serialUnitResults.UpdateResult("Viscid:Kernels:GridMetrics",testResult);
1455 
1456 // serialUnitResults.UpdateResult("Viscid:Kernels:HeatFlux:GridMetrics",computeHeatFluxWorks);
1457 // serialUnitResults.UpdateResult("Viscid:Kernels:UniformViscidFlux:GridMetrics",viscidUniformFluxWorks);
1458 
1459 };
1460 
1462 {
1463  std::cout << "TestVelocityGradient..." << std::endl;
1464 
1471 
1475 
1476  std::ostringstream messageStream;
1477 
1478  grid_t simGrid2d;
1479  grid_t simGrid3d;
1480  operator_t sbpOperator2d;
1481  operator_t sbpOperator3d;
1482  halo_t &simHalo2d(simGrid2d.Halo());
1483  halo_t &simHalo3d(simGrid3d.Halo());
1484 
1485  state_t simState2d;
1486  state_t simState3d;
1487  state_t paramState2d;
1488  state_t paramState3d;
1489 
1490  bool parTestViscidRHS = true;
1491  bool VelocityGradientWorks = true;
1492  bool TemperatureGradientWorks = true;
1493 
1494  std::cout << "Starting 2D linear Velocity Gradient Test" << std::endl;
1495 
1496  // sets up a 2D grid with 4 points in each direction
1497  int numNodes = 21;
1498  std::vector<size_t> gridSizes(2,numNodes);
1499  simGrid2d.SetGridSizes(gridSizes);
1500 
1501  std::vector<double> physicalExtent(4,1.0);
1502  physicalExtent[0] = 0.0;
1503  physicalExtent[2] = 0.0;
1504  simGrid2d.SetPhysicalExtent(physicalExtent);
1505 
1506  std::vector<bool> periodicDirs(2,false);
1507  simGrid2d.SetPeriodicDirs(periodicDirs);
1508 
1509  if(euler::util::InitializeSimulationFixtures(simGrid2d,sbpOperator2d,2,testComm,&messageStream)){
1510  parTestViscidRHS = false;
1511  std::cout << "Failed to setup 2D grid in TestViscidRHS" << std::endl;
1512  return;
1513  }
1514 
1515  std::cout << messageStream.str() << std::endl;
1516  messageStream.str("");
1517  messageStream.clear();
1518 
1519  const pcpp::IndexIntervalType &partitionBufferInterval2d(simGrid2d.PartitionBufferInterval());
1520  const pcpp::IndexIntervalType &partitionInterval2d(simGrid2d.PartitionInterval());
1521  int numDim = gridSizes.size();
1522 
1523 
1524  if(testfixtures::viscid::SetupViscidState(simGrid2d,simState2d,paramState2d,0)){
1525  parTestViscidRHS = false;
1526  std::cout << "Failed to setup state in TestViscidRHS" << std::endl;
1527  return;
1528  }
1529 
1530  size_t numPointsBuffer = simGrid2d.BufferSize();
1531  const std::vector<size_t> &bufferSizes(simGrid2d.BufferSizes());
1532 
1533  double t = 0.0;
1534  double gamma = 1.4;
1535  double dt = .001;
1536  double cfl = 1.0;
1537  double Re = 100;
1538  double power = 0.666;
1539  double beta = 5;
1540  double bulkViscFac = 2;
1541  double Pr = 0.75;
1542  std::vector<double> &dX(simGrid2d.DX());
1543 
1544  // Add some fields that are not usual
1545  paramState2d.AddField("dX",'s',numDim,8,"space");
1546  paramState2d.Create(numPointsBuffer,0);
1547 
1548  paramState2d.SetFieldBuffer("gamma",&gamma);
1549  paramState2d.SetFieldBuffer("inputDT",&dt);
1550  paramState2d.SetFieldBuffer("inputCFL",&cfl);
1551  paramState2d.SetFieldBuffer("dX",&dX[0]);
1552  paramState2d.SetFieldBuffer("refRe",&Re);
1553  paramState2d.SetFieldBuffer("refPr",&Pr);
1554  paramState2d.SetFieldBuffer("power",&power);
1555  paramState2d.SetFieldBuffer("beta",&beta);
1556  paramState2d.SetFieldBuffer("bulkViscFac",&bulkViscFac);
1557 
1558  std::vector<double> rho(numPointsBuffer,1.0);
1559  std::vector<double> rhoV(numDim*numPointsBuffer,0.0);
1560  std::vector<double> rhoE(numPointsBuffer,1.0/(gamma-1.0));
1561 
1562  std::vector<double> T(numPointsBuffer,0.0);
1563  std::vector<double> p(numPointsBuffer,0.0);
1564  std::vector<double> V(3*numPointsBuffer,0.0);
1565  std::vector<double> rhom1(numPointsBuffer,0.0);
1566 
1567  simState2d.SetFieldBuffer("simTime",&t);
1568  simState2d.SetFieldBuffer("rho",&rho[0]);
1569  simState2d.SetFieldBuffer("rhoV",&rhoV[0]);
1570  simState2d.SetFieldBuffer("rhoE",&rhoE[0]);
1571 
1572  simState2d.SetFieldBuffer("pressure",&p[0]);
1573  simState2d.SetFieldBuffer("temperature",&T[0]);
1574  simState2d.SetFieldBuffer("velocity",&V[0]);
1575  simState2d.SetFieldBuffer("rhom1",&rhom1[0]);
1576 
1577  state_t rhsState(simState2d);
1578 
1579 
1580  // -- Set up the RHS --
1581  rhs_t viscidRHS2d;
1582 
1583  if(viscidRHS2d.Initialize(simGrid2d,simState2d,paramState2d,sbpOperator2d)){
1584  parTestViscidRHS = false;
1585  std::cout << "Failed to initialize RHS in TestViscidRHS" << std::endl;
1586  return;
1587  }
1588 
1589  // Insert thread partitioning here
1590  // - initialize RHS and grid thread intervals
1591  std::vector<int> numThreadsDim;
1592  simGrid2d.SetupThreads(numThreadsDim);
1593  viscidRHS2d.InitThreadIntervals();
1594 
1595  if(viscidRHS2d.SetupRHS(simGrid2d,simState2d,rhsState)){
1596  parTestViscidRHS = false;
1597  std::cout << "Failed to setup RHS in TestViscidRHS" << std::endl;
1598  return;
1599  }
1600 
1601  parallelUnitResults.UpdateResult("Viscid:RHS:RunsInParallel",parTestViscidRHS);
1602 
1603  //
1604  // setup a 2D linear velocity field so we can test the velocity gradient
1605  // setup a 2D linear temperature field so we can test the temperature gradient
1606  // leave the density alone, update the energy to be consistent with the temperature
1607  //
1608  std::vector<double> velGradExpected(numDim*numDim*numPointsBuffer,-999.0);
1609  std::vector<double> tempGradExpected(numDim*numPointsBuffer,-999.0);
1610  std::vector<double> uAmp;
1611  std::vector<double> vAmp;
1612  std::vector<double> tempAmp;
1613  uAmp.push_back(1.0);
1614  uAmp.push_back(2.0);
1615  uAmp.push_back(0.0);
1616  vAmp.push_back(3.0);
1617  vAmp.push_back(4.0);
1618  vAmp.push_back(0.0);
1619  tempAmp.push_back(5.0);
1620  tempAmp.push_back(6.0);
1621  tempAmp.push_back(0.0);
1622  double x0 = 0.;
1623  double y0 = 0.;
1624  size_t iStart = partitionBufferInterval2d[0].first;
1625  size_t iEnd = partitionBufferInterval2d[0].second;
1626  size_t jStart = partitionBufferInterval2d[1].first;
1627  size_t jEnd = partitionBufferInterval2d[1].second;
1628  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
1629  size_t jBufferIndex = jIndex*bufferSizes[0];
1630  size_t jPartIndex = (jIndex - jStart) + partitionInterval2d[1].first;
1631  double y = jPartIndex*dX[1];
1632  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
1633  size_t bufferIndex = jBufferIndex + iIndex;
1634  size_t iPartIndex = (iIndex - iStart) + partitionInterval2d[0].first;
1635  double x = iPartIndex*dX[0];
1636 
1637  rhoV[bufferIndex] = rho[bufferIndex]*
1638  testfixtures::viscid::Linear(uAmp,x0,y0,0.,x,y,0.,-1);
1639  rhoV[bufferIndex+numPointsBuffer] = rho[bufferIndex]*
1640  testfixtures::viscid::Linear(vAmp,x0,y0,0.,x,y,0.,-1);
1641  // just the internal part, add a linear offset
1642  rhoE[bufferIndex] += rho[bufferIndex]/(gamma-1)*
1643  testfixtures::viscid::Linear(tempAmp,x0,y0,0.,x,y,0.,-1);
1644 
1645  //std::cout << "Expected velocity (" << rhoV[bufferIndex] << ","
1646  //<< rhoV[bufferIndex+numPointsBuffer] << ","
1647  //<< rhoV[bufferIndex+2*numPointsBuffer]
1648  //<< ") at (" << x << "," << y << "," << z << ")" << std::endl;
1649  rhoE[bufferIndex] = rhoE[bufferIndex] + (rhoV[bufferIndex]*rhoV[bufferIndex] +
1650  rhoV[bufferIndex+numPointsBuffer]*
1651  rhoV[bufferIndex+numPointsBuffer])/(2.0*rho[bufferIndex]);
1652 
1653  // calculate the exact velocity gradient for comparison
1654  // one big flat vector with numPointsBuffer*numDin^2 size
1655  // each {} is numPoints in size
1656  // [ {du/dx} {dv/dx} {du/dy} {dv/dy} ]
1657  // we remove the grid space as the metrics are applied inside ComputeStressTensor
1658  for(int dIndex = 0; dIndex<numDim; dIndex++){
1659  velGradExpected[bufferIndex+dIndex*numDim*numPointsBuffer] =
1660  testfixtures::viscid::Linear(uAmp,x0,y0,0.,x,y,0.,dIndex)*dX[dIndex];
1661  velGradExpected[bufferIndex+numPointsBuffer+dIndex*numDim*numPointsBuffer] =
1662  testfixtures::viscid::Linear(vAmp,x0,y0,0.,x,y,0.,dIndex)*dX[dIndex];
1663  }
1664 
1665  // calculate the exact temperature gradient for comparison
1666  // one big flat vector with numPointsBuffer*numDim size
1667  // each {} is numPoints in size
1668  // [ {dT/dx} {dT/dy} ]
1669  // we remove the grid space as the metrics are applied inside ComputeStressTensor
1670  for(int dIndex = 0; dIndex<numDim; dIndex++){
1671  tempGradExpected[bufferIndex+dIndex*numPointsBuffer] =
1672  testfixtures::viscid::Linear(tempAmp,x0,y0,0.,x,y,0.,dIndex)*dX[dIndex];
1673  }
1674  }
1675  }
1676 
1677  int returnCode = viscidRHS2d.ComputeDV(0);
1678  if(returnCode > 0){
1679  VelocityGradientWorks = false;
1680  std::cout << "ComputeVelGrad failed when computing DV " << std::endl;
1681  return;
1682  }
1683 
1684  std::cout << "Calculating Velocity Gradient" << std::endl;
1685  returnCode = viscidRHS2d.ComputeVelGrad(0);
1686  if(returnCode > 0){
1687  VelocityGradientWorks = false;
1688  return;
1689  }
1690 
1691  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
1692  if(!VelocityGradientWorks){
1693  std::cout << "Velocity Gradient Calculation Failed" << std::endl;
1694  }
1695 
1696 
1697  // check the velocity gradient
1698  // first get the gradient from the rhs object
1699  // then check against the expected answer
1700  std::cout << "Checking Velocity Gradient calculation" << std::endl;
1701  const std::vector<double *> &velGradBuffers(viscidRHS2d.VelGradBuffers());
1702 
1703  if(VelocityGradientWorks){
1704  bool printVelGrad = true;
1705  for(int iDim = 0;iDim < numDim;iDim++){
1706  const double* velGradData = velGradBuffers[iDim];
1707 
1708  for(int jDim = 0;jDim < numDim;jDim++){
1709  const double* velGradDataComponent = &velGradData[jDim*numPointsBuffer];
1710 
1711  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
1712  size_t jBufferIndex = jIndex*bufferSizes[0];
1713  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
1714  size_t bufferIndex = jBufferIndex + iIndex;
1715  size_t expectedIndex = numPointsBuffer*iDim*numDim+jDim*numPointsBuffer+bufferIndex;
1716 
1717  double error = std::abs(velGradDataComponent[bufferIndex] -
1718  velGradExpected[expectedIndex])/velGradExpected[expectedIndex];
1719 
1720  if(error > 1e-12){
1721  VelocityGradientWorks = false;
1722  if(printVelGrad) {
1723  std::cout << std::scientific << std::setprecision(16)
1724  << "In ComputeVelGrad: "<< std::endl
1725  << "Expected velGrad=" << velGradExpected[expectedIndex] << std::endl
1726  << " got velGrad=" << velGradDataComponent[bufferIndex] << std::endl
1727  << " at (i,j,bufferIndex)=(" << iDim << "," << jDim << ","
1728  << bufferIndex << ")" << std::endl;
1729  std::cout << "Error =" << error << std::endl;;
1730  std::cout << "No further error messages will be generated for velGrad 2D Linear" << std::endl;
1731  printVelGrad=false;
1732  }
1733  }
1734  }
1735  }
1736  }
1737  }
1738  }
1739  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
1740  if(!VelocityGradientWorks){
1741  std::cout << "Velocity Gradient Compare Failed" << std::endl;
1742  }
1743 
1744  // Compute the temperature gradient
1745  std::cout << "Calculating Temperature Gradient" << std::endl;
1746  returnCode = viscidRHS2d.ComputeTemperatureGrad(0);
1747  if(returnCode > 0){
1748  TemperatureGradientWorks = false;
1749  return;
1750  }
1751 
1752  TemperatureGradientWorks = CheckResult(TemperatureGradientWorks,testComm);
1753  if(!TemperatureGradientWorks){
1754  std::cout << "Temperature Gradient Calculation Failed" << std::endl;
1755  }
1756 
1757  // check the temperature gradient
1758  // first get the gradient from the rhs object
1759  // then check against the expected answer
1760  std::cout << "Checking Temperature Gradient calculation" << std::endl;
1761  const std::vector<double *> &tempGradBuffers(viscidRHS2d.TemperatureGradBuffers());
1762 
1763  if(TemperatureGradientWorks){
1764  bool printTempGrad = true;
1765  for(int iDim = 0;iDim < numDim;iDim++){
1766  const double* tempGradDataComponent = tempGradBuffers[iDim];
1767 
1768  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
1769  size_t jBufferIndex = jIndex*bufferSizes[0];
1770  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
1771  size_t bufferIndex = jBufferIndex + iIndex;
1772  size_t expectedIndex = bufferIndex+numPointsBuffer*iDim;
1773 
1774  double error = std::abs(tempGradDataComponent[bufferIndex] -
1775  tempGradExpected[expectedIndex])/tempGradExpected[expectedIndex];
1776 
1777  if(error > 1e-12){
1778  TemperatureGradientWorks = false;
1779  if(printTempGrad) {
1780  std::cout << std::scientific << std::setprecision(16)
1781  << "In ComputeTemperatureGrad: "<< std::endl
1782  << "Expected tempGrad=" << tempGradExpected[expectedIndex] << std::endl
1783  << " got tempGrad=" << tempGradDataComponent[bufferIndex] << std::endl
1784  << " at (i,bufferIndex)=(" << iDim << ","
1785  << bufferIndex << ")" << std::endl;
1786  std::cout << "Temperature " << T[bufferIndex] << std::endl;
1787  std::cout << "Error =" << error << std::endl;;
1788  std::cout << "No further error messages will be generated for tempGrad 2D Linear"
1789  << std::endl;
1790  printTempGrad=false;
1791  }
1792  }
1793  }
1794  }
1795  }
1796  }
1797  TemperatureGradientWorks = CheckResult(TemperatureGradientWorks,testComm);
1798  if(!TemperatureGradientWorks){
1799  std::cout << "Temperature Gradient Compare Failed" << std::endl;
1800  }
1801 
1802  std::cout << "Done with 2D linear Velocity Gradient Test" << std::endl;
1803  std::cout << "Starting 3D linear Velocity Gradient Test" << std::endl;
1804 
1805  numNodes = 21;
1806  gridSizes.resize(3,numNodes);
1807  simGrid3d.SetGridSizes(gridSizes);
1808 
1809  physicalExtent.resize(6,1.0);
1810  physicalExtent[0] = 0.0;
1811  physicalExtent[2] = 0.0;
1812  physicalExtent[4] = 0.0;
1813  simGrid3d.SetPhysicalExtent(physicalExtent);
1814 
1815  periodicDirs.resize(3,false);
1816  simGrid3d.SetPeriodicDirs(periodicDirs);
1817 
1818  if(euler::util::InitializeSimulationFixtures(simGrid3d,sbpOperator3d,2,testComm,&messageStream)){
1819  parTestViscidRHS = false;
1820  std::cout << "Failed to setup 3D grid in TestViscidRHS" << std::endl;
1821  return;
1822  }
1823 
1824  std::cout << messageStream.str() << std::endl;
1825  messageStream.str("");
1826  messageStream.clear();
1827 
1828  const pcpp::IndexIntervalType &partitionBufferInterval3d(simGrid3d.PartitionBufferInterval());
1829  const pcpp::IndexIntervalType &partitionInterval3d(simGrid3d.PartitionInterval());
1830  numDim = gridSizes.size();
1831 
1832  if(testfixtures::viscid::SetupViscidState(simGrid3d,simState3d,paramState3d,0)){
1833  parTestViscidRHS = false;
1834  std::cout << "Failed to setup state in TestViscidRHS" << std::endl;
1835  return;
1836  }
1837 
1838 
1839  numPointsBuffer = simGrid3d.BufferSize();
1840  //bufferSizes.resize(simGrid3d.BufferSizes());
1841  const std::vector<size_t> &bufferSizes3d(simGrid3d.BufferSizes());
1842 
1843  //std::vector<double> &dX.resize(simGrid3d.DX());
1844  std::vector<double> &dX3d(simGrid3d.DX());
1845 
1846  // Add some fields that are not usual
1847  paramState3d.AddField("dX",'s',3,8,"space");
1848  paramState3d.Create(numPointsBuffer,0);
1849 
1850  paramState3d.SetFieldBuffer("gamma",&gamma);
1851  paramState3d.SetFieldBuffer("inputDT",&dt);
1852  paramState3d.SetFieldBuffer("inputCFL",&cfl);
1853  paramState3d.SetFieldBuffer("dX",&dX3d[0]);
1854  paramState3d.SetFieldBuffer("refRe",&Re);
1855  paramState3d.SetFieldBuffer("refPr",&Pr);
1856  paramState3d.SetFieldBuffer("power",&power);
1857  paramState3d.SetFieldBuffer("beta",&beta);
1858  paramState3d.SetFieldBuffer("bulkViscFac",&bulkViscFac);
1859 
1860  rho.resize(numPointsBuffer,1.0);
1861  rhoV.resize(3*numPointsBuffer,0.0);
1862  rhoE.resize(numPointsBuffer);
1863  rhoE.assign(rhoE.size(),1.0/(gamma-1));
1864 
1865  T.resize(numPointsBuffer,0.0);
1866  p.resize(numPointsBuffer,0.0);
1867  V.resize(3*numPointsBuffer,0.0);
1868 
1869  rhom1.resize(numPointsBuffer,0.0);
1870 
1871  simState3d.SetFieldBuffer("simTime",&t);
1872  simState3d.SetFieldBuffer("rho",&rho[0]);
1873  simState3d.SetFieldBuffer("rhoV",&rhoV[0]);
1874  simState3d.SetFieldBuffer("rhoE",&rhoE[0]);
1875 
1876  simState3d.SetFieldBuffer("pressure",&p[0]);
1877  simState3d.SetFieldBuffer("temperature",&T[0]);
1878  simState3d.SetFieldBuffer("velocity",&V[0]);
1879  simState3d.SetFieldBuffer("rhom1",&rhom1[0]);
1880 
1881  state_t rhsState3d(simState3d);
1882 
1883 
1884  // -- Set up the RHS --
1885  rhs_t viscidRHS3d;
1886 
1887  if(viscidRHS3d.Initialize(simGrid3d,simState3d,paramState3d,sbpOperator3d)){
1888  parTestViscidRHS = false;
1889  std::cout << "Failed to initialize RHS in TestViscidRHS" << std::endl;
1890  return;
1891  }
1892 
1893  std::vector<int> numThreadsDim3;
1894  simGrid3d.SetupThreads(numThreadsDim3);
1895  viscidRHS3d.InitThreadIntervals();
1896 
1897  if(viscidRHS3d.SetupRHS(simGrid3d,simState3d,rhsState3d)){
1898  parTestViscidRHS = false;
1899  std::cout << "Failed to setup RHS in TestViscidRHS" << std::endl;
1900  return;
1901  }
1902 
1903  parallelUnitResults.UpdateResult("Viscid:RHS:RunsInParallel",parTestViscidRHS);
1904 
1905  //
1906  // setup a 3D linear velocity field so we can test the velocity gradient
1907  // setup a 3D linear temperature field so we can test the temperature gradient
1908  // leave the density alone, update the energy
1909  //
1910  velGradExpected.resize(numDim*numDim*numPointsBuffer,-999.0);
1911  tempGradExpected.resize(numDim*numPointsBuffer,-999.0);
1912  uAmp.resize(0);
1913  vAmp.resize(0);
1914  tempAmp.resize(0);
1915  std::vector<double> wAmp;
1916  uAmp.push_back(1.0);
1917  uAmp.push_back(2.0);
1918  uAmp.push_back(3.0);
1919  vAmp.push_back(4.0);
1920  vAmp.push_back(5.0);
1921  vAmp.push_back(6.0);
1922  wAmp.push_back(7.0);
1923  wAmp.push_back(8.0);
1924  wAmp.push_back(9.0);
1925  tempAmp.push_back(10.0);
1926  tempAmp.push_back(11.0);
1927  tempAmp.push_back(12.0);
1928  x0 = 0.;
1929  y0 = 0.;
1930  double z0 = 0.;
1931  iStart = partitionBufferInterval3d[0].first;
1932  iEnd = partitionBufferInterval3d[0].second;
1933  jStart = partitionBufferInterval3d[1].first;
1934  jEnd = partitionBufferInterval3d[1].second;
1935  size_t kStart = partitionBufferInterval3d[2].first;
1936  size_t kEnd = partitionBufferInterval3d[2].second;
1937  size_t nPlane = bufferSizes3d[0]*bufferSizes3d[1];
1938  for(size_t kIndex = kStart;kIndex <= kEnd;kIndex++){
1939  size_t kBufferIndex = kIndex*nPlane;
1940  size_t kPartIndex = (kIndex - kStart) + partitionInterval3d[2].first;
1941  double z = kPartIndex*dX3d[2];
1942  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
1943  size_t jkBufferIndex = kBufferIndex + jIndex*bufferSizes3d[0];
1944  size_t jPartIndex = (jIndex - jStart) + partitionInterval3d[1].first;
1945  double y = jPartIndex*dX3d[1];
1946  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
1947  size_t bufferIndex = jkBufferIndex + iIndex;
1948  size_t iPartIndex = (iIndex - iStart) + partitionInterval3d[0].first;
1949  double x = iPartIndex*dX3d[0];
1950 
1951  rhoV[bufferIndex] = rho[bufferIndex]*
1952  testfixtures::viscid::Linear(uAmp,x0,y0,z0,x,y,z,-1);
1953  rhoV[bufferIndex+numPointsBuffer] = rho[bufferIndex]*
1954  testfixtures::viscid::Linear(vAmp,x0,y0,z0,x,y,z,-1);
1955  rhoV[bufferIndex+2*numPointsBuffer] = rho[bufferIndex]*
1956  testfixtures::viscid::Linear(wAmp,x0,y0,z0,x,y,z,-1);
1957 
1958  // just the internal part, add a linear offset
1959  rhoE[bufferIndex] += rho[bufferIndex]/(gamma-1)*
1960  testfixtures::viscid::Linear(tempAmp,x0,y0,z0,x,y,z,-1);
1961 
1962  rhoE[bufferIndex] = rhoE[bufferIndex] + (rhoV[bufferIndex]*rhoV[bufferIndex] +
1963  rhoV[bufferIndex+numPointsBuffer]*
1964  rhoV[bufferIndex+numPointsBuffer] +
1965  rhoV[bufferIndex+2*numPointsBuffer]*
1966  rhoV[bufferIndex+2*numPointsBuffer])/(2.0*rho[bufferIndex]);
1967 
1968  // calculate the exact velocity gradient for comparison
1969  // one big flat vector with numPointsBuffer*numDin^2 size
1970  // each {} is numPoints in size
1971  // [ {du/dx} {dv/dx} {dw/dx} {du/dy} {dv/dy} {dw/dy} {du/dz} {dv/dz} {dw/dz} ]
1972  for(int dIndex = 0; dIndex<numDim; dIndex++){
1973  velGradExpected[bufferIndex+dIndex*numDim*numPointsBuffer] =
1974  testfixtures::viscid::Linear(uAmp,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
1975  velGradExpected[bufferIndex+numPointsBuffer+dIndex*numDim*numPointsBuffer] =
1976  testfixtures::viscid::Linear(vAmp,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
1977  velGradExpected[bufferIndex+2*numPointsBuffer+dIndex*numDim*numPointsBuffer] =
1978  testfixtures::viscid::Linear(wAmp,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
1979  }
1980 
1981  // calculate the exact temperature gradient for comparison
1982  // one big flat vector with numPointsBuffer*numDim size
1983  // each {} is numPoints in size
1984  // [ {dT/dx} {dT/dy} {dT/dz}]
1985  // we remove the grid space as the metrics are applied inside ComputeStressTensor
1986  for(int dIndex = 0; dIndex<numDim; dIndex++){
1987  tempGradExpected[bufferIndex+dIndex*numPointsBuffer] =
1988  testfixtures::viscid::Linear(tempAmp,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
1989  }
1990  }
1991  }
1992  }
1993 
1994  returnCode = viscidRHS3d.ComputeDV(0);
1995  if(returnCode > 0){
1996  VelocityGradientWorks = false;
1997  std::cout << "ComputeVelGrad failed when computing DV " << std::endl;
1998  return;
1999  }
2000 
2001  std::cout << "Calculating Velocity Gradient" << std::endl;
2002  returnCode = viscidRHS3d.ComputeVelGrad(0);
2003  if(returnCode > 0){
2004  VelocityGradientWorks = false;
2005  return;
2006  }
2007 
2008  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
2009  if(!VelocityGradientWorks){
2010  std::cout << "Velocity Gradient Calculation Failed" << std::endl;
2011  }
2012 
2013  if(VelocityGradientWorks){
2014  std::cout << "Checking Velocity Gradient calculation" << std::endl;
2015  // check the velocity gradient
2016  // first get the gradient from the rhs object
2017  // then check against the expected answer
2018  const std::vector<double *> &velGradBuffers3d(viscidRHS3d.VelGradBuffers());
2019 
2020  bool printVelGrad = true;
2021  for(int iDim = 0;iDim < numDim;iDim++){
2022  const double* velGradData3d = velGradBuffers3d[iDim];
2023 
2024  for(int jDim = 0;jDim < numDim;jDim++){
2025  const double* velGradDataComponent3d = &velGradData3d[jDim*numPointsBuffer];
2026 
2027  for(size_t kIndex = kStart;kIndex <= kEnd;kIndex++){
2028  size_t kBufferIndex = kIndex*nPlane;
2029  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2030  size_t jkBufferIndex = kBufferIndex + jIndex*bufferSizes3d[0];
2031  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2032  size_t bufferIndex = jkBufferIndex + iIndex;
2033  size_t expectedIndex = numPointsBuffer*iDim*numDim+jDim*numPointsBuffer+bufferIndex;
2034 
2035  double error = std::abs(velGradDataComponent3d[bufferIndex] -
2036  velGradExpected[expectedIndex])/velGradExpected[expectedIndex];
2037 
2038  if(error > 1e-12){
2039  VelocityGradientWorks = false;
2040  if(printVelGrad) {
2041  std::cout << std::scientific << std::setprecision(16)
2042  << "In ComputeVelGrad: "<< std::endl
2043  << "Expected velGrad=" << velGradExpected[expectedIndex] << std::endl
2044  << " got velGrad=" << velGradDataComponent3d[bufferIndex] << std::endl
2045  << " at (i,j,bufferIndex)=(" << iDim << "," << jDim << ","
2046  << bufferIndex << ")" << std::endl;
2047  std::cout << "Error =" << error << std::endl;;
2048  std::cout << "No further error messages will be generated for velGrad 3d" << std::endl;
2049  printVelGrad=false;
2050  }
2051  }
2052  }
2053  }
2054  }
2055  }
2056  }
2057  }
2058 
2059  // Compute the temperature gradient
2060  std::cout << "Calculating Temperature Gradient" << std::endl;
2061  returnCode = viscidRHS3d.ComputeTemperatureGrad(0);
2062  if(returnCode > 0){
2063  TemperatureGradientWorks = false;
2064  return;
2065  }
2066 
2067  TemperatureGradientWorks = CheckResult(TemperatureGradientWorks,testComm);
2068  if(!TemperatureGradientWorks){
2069  std::cout << "Temperature Gradient Calculation Failed" << std::endl;
2070  }
2071 
2072  // check the temperature gradient
2073  // first get the gradient from the rhs object
2074  // then check against the expected answer
2075  std::cout << "Checking Temperature Gradient calculation" << std::endl;
2076  const std::vector<double *> &tempGradBuffers3d(viscidRHS3d.TemperatureGradBuffers());
2077 
2078  if(TemperatureGradientWorks){
2079  bool printTempGrad = true;
2080  for(int iDim = 0;iDim < numDim;iDim++){
2081  const double* tempGradDataComponent = tempGradBuffers3d[iDim];
2082 
2083  for(size_t kIndex = kStart;kIndex <= kEnd;kIndex++){
2084  size_t kBufferIndex = kIndex*nPlane;
2085  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2086  size_t jkBufferIndex = kBufferIndex + jIndex*bufferSizes3d[0];
2087  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2088  size_t bufferIndex = jkBufferIndex + iIndex;
2089  size_t expectedIndex = bufferIndex + numPointsBuffer*iDim;
2090 
2091  double error = std::abs(tempGradDataComponent[bufferIndex] -
2092  tempGradExpected[expectedIndex])/tempGradExpected[expectedIndex];
2093 
2094  if(error > 1e-12){
2095  TemperatureGradientWorks = false;
2096  if(printTempGrad) {
2097  std::cout << std::scientific << std::setprecision(16)
2098  << "In ComputeTemperatureGrad: "<< std::endl
2099  << "Expected tempGrad=" << tempGradExpected[expectedIndex] << std::endl
2100  << " got tempGrad=" << tempGradDataComponent[bufferIndex] << std::endl
2101  << " at (i,bufferIndex)=(" << iDim << ","
2102  << bufferIndex << ")" << std::endl;
2103  std::cout << "Temperature " << T[bufferIndex] << std::endl;
2104  std::cout << "Error =" << error << std::endl;;
2105  std::cout << "No further error messages will be generated for tempGrad 3D Linear"
2106  << std::endl;
2107  printTempGrad=false;
2108  }
2109  }
2110  }
2111  }
2112  }
2113  }
2114  }
2115 
2116  std::cout << "Done with 3D linear Velocity Gradient Test" << std::endl;
2117 
2118  TemperatureGradientWorks = CheckResult(TemperatureGradientWorks,testComm);
2119  if(!TemperatureGradientWorks){
2120  std::cout << "Temperature Gradient Compare Failed" << std::endl;
2121  }
2122 
2123  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
2124  if(!VelocityGradientWorks){
2125  std::cout << "Velocity Gradient Compare Failed" << std::endl;
2126  }
2127 
2128 
2129  parallelUnitResults.UpdateResult("Viscid:RHS:VelocityGradient",VelocityGradientWorks);
2130  parallelUnitResults.UpdateResult("Viscid:RHS:TemperatureGradient",TemperatureGradientWorks);
2131 
2132 };
2133 
2135 {
2136  std::cout << "TestVelocityGradientPeriodic..." << std::endl;
2137 
2144 
2148 
2149  std::ostringstream messageStream;
2150 
2151  grid_t simGrid2d;
2152  grid_t simGrid3d;
2153  operator_t sbpOperator2d;
2154  operator_t sbpOperator3d;
2155  halo_t &simHalo2d(simGrid2d.Halo());
2156  halo_t &simHalo3d(simGrid3d.Halo());
2157 
2158  state_t simState2d;
2159  state_t simState3d;
2160  state_t paramState2d;
2161  state_t paramState3d;
2162 
2163  bool parTestViscidRHS = true;
2164  bool VelocityGradientWorks = true;
2165  bool TemperatureGradientWorks = true;
2166 
2167  std::cout << "Starting 2D periodic Velocity Gradient Test" << std::endl;
2168 
2169  // sets up a 2D grid with 4 points in each direction
2170  int numNodes = 31;
2171  std::vector<size_t> gridSizes(2,numNodes);
2172  simGrid2d.SetGridSizes(gridSizes);
2173 
2174  std::vector<double> physicalExtent(4,1.0);
2175  physicalExtent[0] = 0.0;
2176  physicalExtent[2] = 0.0;
2177  simGrid2d.SetPhysicalExtent(physicalExtent);
2178 
2179  std::vector<bool> periodicDirs(2,true);
2180  simGrid2d.SetPeriodicDirs(periodicDirs);
2181 
2182  if(euler::util::InitializeSimulationFixtures(simGrid2d,sbpOperator2d,2,testComm,&messageStream)){
2183  parTestViscidRHS = false;
2184  std::cout << "Failed to setup 2D grid in TestViscidRHS" << std::endl;
2185  return;
2186  }
2187 
2188  std::cout << messageStream.str() << std::endl;
2189  messageStream.str("");
2190  messageStream.clear();
2191 
2192  const pcpp::IndexIntervalType &partitionBufferInterval2d(simGrid2d.PartitionBufferInterval());
2193  const pcpp::IndexIntervalType &partitionInterval2d(simGrid2d.PartitionInterval());
2194  int numDim = gridSizes.size();
2195 
2196  if(testfixtures::viscid::SetupViscidState(simGrid2d,simState2d,paramState2d,0)){
2197  parTestViscidRHS = false;
2198  std::cout << "Failed to setup state in TestViscidRHS" << std::endl;
2199  return;
2200  }
2201 
2202  size_t numPointsBuffer = simGrid2d.BufferSize();
2203  const std::vector<size_t> &bufferSizes(simGrid2d.BufferSizes());
2204 
2205  double t = 0.0;
2206  double gamma = 1.4;
2207  double dt = .001;
2208  double cfl = 1.0;
2209  double Re = 100;
2210  double Pr = 0.75;
2211  double power = 0.666;
2212  double beta = 5;
2213  double bulkViscFac = 2;
2214  std::vector<double> &dX(simGrid2d.DX());
2215 
2216  // Add some fields that are not usual
2217  paramState2d.AddField("dX",'s',numDim,8,"space");
2218  paramState2d.Create(numPointsBuffer,0);
2219 
2220  paramState2d.SetFieldBuffer("gamma",&gamma);
2221  paramState2d.SetFieldBuffer("inputDT",&dt);
2222  paramState2d.SetFieldBuffer("inputCFL",&cfl);
2223  paramState2d.SetFieldBuffer("dX",&dX[0]);
2224  paramState2d.SetFieldBuffer("refRe",&Re);
2225  paramState2d.SetFieldBuffer("refPr",&Pr);
2226  paramState2d.SetFieldBuffer("power",&power);
2227  paramState2d.SetFieldBuffer("beta",&beta);
2228  paramState2d.SetFieldBuffer("bulkViscFac",&bulkViscFac);
2229 
2230  std::vector<double> rho(numPointsBuffer,1.0);
2231  std::vector<double> rhoV(numDim*numPointsBuffer,0.0);
2232  std::vector<double> rhoE(numPointsBuffer,1.0/(gamma-1.0));
2233 
2234  std::vector<double> T(numPointsBuffer,0.0);
2235  std::vector<double> p(numPointsBuffer,0.0);
2236  std::vector<double> V(numDim*numPointsBuffer,0.0);
2237  std::vector<double> rhom1(numPointsBuffer,0.0);
2238 
2239  simState2d.SetFieldBuffer("simTime",&t);
2240  simState2d.SetFieldBuffer("rho",&rho[0]);
2241  simState2d.SetFieldBuffer("rhoV",&rhoV[0]);
2242  simState2d.SetFieldBuffer("rhoE",&rhoE[0]);
2243 
2244  simState2d.SetFieldBuffer("pressure",&p[0]);
2245  simState2d.SetFieldBuffer("temperature",&T[0]);
2246  simState2d.SetFieldBuffer("velocity",&V[0]);
2247  simState2d.SetFieldBuffer("rhom1",&rhom1[0]);
2248 
2249  state_t rhsState(simState2d);
2250 
2251 
2252  // -- Set up the RHS --
2253  rhs_t viscidRHS2d;
2254 
2255  if(viscidRHS2d.Initialize(simGrid2d,simState2d,paramState2d,sbpOperator2d)){
2256  parTestViscidRHS = false;
2257  std::cout << "Failed to initialize RHS in TestViscidRHS" << std::endl;
2258  return;
2259  }
2260 
2261 
2262  std::vector<int> numThreadsDim;
2263  simGrid2d.SetupThreads(numThreadsDim);
2264  viscidRHS2d.InitThreadIntervals();
2265 
2266  if(viscidRHS2d.SetupRHS(simGrid2d,simState2d,rhsState)){
2267  parTestViscidRHS = false;
2268  std::cout << "Failed to setup RHS in TestViscidRHS" << std::endl;
2269  return;
2270  }
2271 
2272 
2273  parallelUnitResults.UpdateResult("Viscid:RHS:RunsInParallel",parTestViscidRHS);
2274 
2275  //
2276  // setup a 2D periodic velocity field so we can test the velocity gradient
2277  // setup a 2D periodic temperature field so we can test the temperature gradient
2278  // leave the density alone, update the energy
2279  //
2280  std::vector<double> velGradExpected(numDim*numDim*numPointsBuffer,-999.0);
2281  std::vector<double> tempGradExpected(numDim*numPointsBuffer,-999.0);
2282  std::vector<double> uAmp;
2283  std::vector<double> vAmp;
2284  std::vector<double> tempAmp;
2285  uAmp.push_back(1.0);
2286  uAmp.push_back(2.0);
2287  uAmp.push_back(0.0);
2288  vAmp.push_back(3.0);
2289  vAmp.push_back(4.0);
2290  vAmp.push_back(0.0);
2291  tempAmp.push_back(5.0);
2292  tempAmp.push_back(6.0);
2293  tempAmp.push_back(0.0);
2294  std::vector<double> period(numDim,0);
2295  for(int i=0;i<numDim;i++){
2296  period[i]=dX[i]*numNodes;
2297  }
2298  double x0 = 0.;
2299  double y0 = 0.;
2300  size_t iStart = partitionBufferInterval2d[0].first;
2301  size_t iEnd = partitionBufferInterval2d[0].second;
2302  size_t jStart = partitionBufferInterval2d[1].first;
2303  size_t jEnd = partitionBufferInterval2d[1].second;
2304  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2305  size_t jBufferIndex = jIndex*bufferSizes[0];
2306  size_t jPartIndex = (jIndex - jStart) + partitionInterval2d[1].first;
2307  double y = jPartIndex*dX[1];
2308  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2309  size_t bufferIndex = jBufferIndex + iIndex;
2310  size_t iPartIndex = (iIndex - iStart) + partitionInterval2d[0].first;
2311  double x = iPartIndex*dX[0];
2312 
2313  rhoV[bufferIndex] = rho[bufferIndex]*
2314  testfixtures::viscid::Cosine(uAmp,period,x0,y0,0.,x,y,0.,-1);
2315  rhoV[bufferIndex+numPointsBuffer] = rho[bufferIndex]*
2316  testfixtures::viscid::Cosine(vAmp,period,x0,y0,0.,x,y,0.,-1);
2317 
2318  // just the internal part, add a linear offset
2319  rhoE[bufferIndex] += rho[bufferIndex]/(gamma-1)*
2320  testfixtures::viscid::Cosine(tempAmp,period,x0,y0,0.,x,y,0.,-1);
2321 
2322  //std::cout << "Expected velocity (" << rhoV[bufferIndex] << ","
2323  //<< rhoV[bufferIndex+numPointsBuffer] << ","
2324  //<< rhoV[bufferIndex+2*numPointsBuffer]
2325  //<< ") at (" << x << "," << y << "," << z << ")" << std::endl;
2326  rhoE[bufferIndex] = rhoE[bufferIndex] + (rhoV[bufferIndex]*rhoV[bufferIndex] +
2327  rhoV[bufferIndex+numPointsBuffer]*
2328  rhoV[bufferIndex+numPointsBuffer])/(2.0*rho[bufferIndex]);
2329 
2330  // calculate the exact velocity gradient for comparison
2331  // one big flat vector with numPointsBuffer*numDin^2 size
2332  // each {} is numPoints in size
2333  // [ {du/dx} {dv/dx} {du/dy} {dv/dy} ]
2334  for(int dIndex = 0; dIndex<numDim; dIndex++){
2335  velGradExpected[bufferIndex+dIndex*numDim*numPointsBuffer] =
2336  testfixtures::viscid::Cosine(uAmp,period,x0,y0,0.,x,y,0.,dIndex)*dX[dIndex];
2337  velGradExpected[bufferIndex+numPointsBuffer+dIndex*numDim*numPointsBuffer] =
2338  testfixtures::viscid::Cosine(vAmp,period,x0,y0,0.,x,y,0.,dIndex)*dX[dIndex];
2339  }
2340 
2341  // calculate the exact temperature gradient for comparison
2342  // one big flat vector with numPointsBuffer*numDim size
2343  // each {} is numPoints in size
2344  // [ {dT/dx} {dT/dy} ]
2345  // we remove the grid space as the metrics are applied inside ComputeStressTensor
2346  for(int dIndex = 0; dIndex<numDim; dIndex++){
2347  tempGradExpected[bufferIndex+dIndex*numPointsBuffer] =
2348  testfixtures::viscid::Cosine(tempAmp,period,x0,y0,0.,x,y,0.,dIndex)*dX[dIndex];
2349  }
2350  }
2351  }
2352 
2353 
2354 
2355  int returnCode = viscidRHS2d.ComputeDV(0);
2356  if(returnCode > 0){
2357  VelocityGradientWorks = false;
2358  std::cout << "ComputeVelGrad failed when computing DV " << std::endl;
2359  return;
2360  }
2361  //std::cout << "ComputeDV done" << std::endl;
2362 
2363 
2364  std::cout << "Calculating Velocity Gradient" << std::endl;
2365  returnCode = viscidRHS2d.ComputeVelGrad(0);
2366  if(returnCode > 0){
2367  std::cout << "ComputeVelGrad failed, aborting tests." << std::endl;
2368  VelocityGradientWorks = false;
2369  return;
2370  }
2371 
2372  simGrid2d.Communicator().Barrier();
2373 
2374  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
2375  if(!VelocityGradientWorks){
2376  std::cout << "Velocity Gradient Calculation Failed" << std::endl;
2377  }
2378 
2379  // check the velocity gradient
2380  // first get the gradient from the rhs object
2381  // then check against the expected answer
2382  simGrid2d.Communicator().Barrier();
2383 
2384  if(VelocityGradientWorks){
2385  std::cout << "Checking Velocity Gradient calculation" << std::endl;
2386 
2387  const std::vector<double *> &velGradBuffers(viscidRHS2d.VelGradBuffers());
2388 
2389  bool printVelGrad = true;
2390  for(int iDim = 0;iDim < numDim;iDim++){
2391  const double* velGradData = velGradBuffers[iDim];
2392 
2393  for(int jDim = 0;jDim < numDim;jDim++){
2394  const double* velGradDataComponent = &velGradData[jDim*numPointsBuffer];
2395 
2396  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2397  size_t jBufferIndex = jIndex*bufferSizes[0];
2398  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2399  size_t bufferIndex = jBufferIndex + iIndex;
2400  size_t expectedIndex = numPointsBuffer*iDim*numDim+jDim*numPointsBuffer+bufferIndex;
2401 
2402 
2403  double error = std::abs(velGradDataComponent[bufferIndex] -
2404  velGradExpected[expectedIndex])/velGradExpected[expectedIndex];
2405 
2406  if(error > 1e-2){
2407  VelocityGradientWorks = false;
2408  if(printVelGrad) {
2409  std::cout << std::scientific << std::setprecision(16)
2410  << "In ComputeVelGrad: "<< std::endl
2411  << "Expected velGrad=" << velGradExpected[expectedIndex] << std::endl
2412  << " got velGrad=" << velGradDataComponent[bufferIndex] << std::endl
2413  << " at (i,j,bufferIndex)=(" << iDim << "," << jDim << ","
2414  << bufferIndex << ")" << std::endl;
2415  std::cout << "Error =" << error << std::endl;;
2416  std::cout << "No further error messages will be generated for velGrad 2D Cosine" << std::endl;
2417  printVelGrad=false;
2418  }
2419  }
2420  }
2421  }
2422  }
2423  }
2424  }
2425 
2426  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
2427  if(!VelocityGradientWorks){
2428  std::cout << "Velocity Gradient Compare Failed" << std::endl;
2429  }
2430 
2431  // Compute the temperature gradient
2432  std::cout << "Calculating Temperature Gradient" << std::endl;
2433  returnCode = viscidRHS2d.ComputeTemperatureGrad(0);
2434  if(returnCode > 0){
2435  TemperatureGradientWorks = false;
2436  return;
2437  }
2438 
2439  TemperatureGradientWorks = CheckResult(TemperatureGradientWorks,testComm);
2440  if(!TemperatureGradientWorks){
2441  std::cout << "Temperature Gradient Calculation Failed" << std::endl;
2442  }
2443 
2444  // check the temperature gradient
2445  // first get the gradient from the rhs object
2446  // then check against the expected answer
2447  std::cout << "Checking Temperature Gradient calculation" << std::endl;
2448  const std::vector<double *> &tempGradBuffers(viscidRHS2d.TemperatureGradBuffers());
2449 
2450  if(TemperatureGradientWorks){
2451  bool printTempGrad = true;
2452  for(int iDim = 0;iDim < numDim;iDim++){
2453  const double* tempGradDataComponent = tempGradBuffers[iDim];
2454 
2455  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2456  size_t jBufferIndex = jIndex*bufferSizes[0];
2457  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2458  size_t bufferIndex = jBufferIndex + iIndex;
2459  size_t expectedIndex = bufferIndex+numPointsBuffer*iDim;
2460 
2461  double error = std::abs(tempGradDataComponent[bufferIndex] -
2462  tempGradExpected[expectedIndex])/tempGradExpected[expectedIndex];
2463 
2464  if(error > 1e-2){
2465  TemperatureGradientWorks = false;
2466  if(printTempGrad) {
2467  std::cout << std::scientific << std::setprecision(16)
2468  << "In ComputeTemperatureGrad: "<< std::endl
2469  << "Expected tempGrad=" << tempGradExpected[expectedIndex] << std::endl
2470  << " got tempGrad=" << tempGradDataComponent[bufferIndex] << std::endl
2471  << " at (i,bufferIndex)=(" << iDim << ","
2472  << bufferIndex << ")" << std::endl;
2473  std::cout << "Temperature " << T[bufferIndex] << std::endl;
2474  std::cout << "Error =" << error << std::endl;;
2475  std::cout << "No further error messages will be generated for tempGrad 2D periodic"
2476  << std::endl;
2477  printTempGrad=false;
2478  }
2479  }
2480  }
2481  }
2482  }
2483  }
2484  TemperatureGradientWorks = CheckResult(TemperatureGradientWorks,testComm);
2485  if(!TemperatureGradientWorks){
2486  std::cout << "Temperature Gradient Compare Failed" << std::endl;
2487  }
2488 
2489  std::cout << "Done with 2D periodic Velocity Gradient Test" << std::endl;
2490  std::cout << "Starting 3D periodic Velocity Gradient Test" << std::endl;
2491 
2492  //numNodes = 51;
2493  gridSizes.resize(3,numNodes);
2494  simGrid3d.SetGridSizes(gridSizes);
2495 
2496  physicalExtent.resize(6,1.0);
2497  physicalExtent[0] = 0.0;
2498  physicalExtent[2] = 0.0;
2499  physicalExtent[4] = 0.0;
2500  simGrid3d.SetPhysicalExtent(physicalExtent);
2501 
2502  periodicDirs.resize(3,true);
2503  simGrid3d.SetPeriodicDirs(periodicDirs);
2504 
2505  if(euler::util::InitializeSimulationFixtures(simGrid3d,sbpOperator3d,2,testComm,&messageStream)){
2506  parTestViscidRHS = false;
2507  std::cout << "Failed to setup 3D grid in TestViscidRHS" << std::endl;
2508  return;
2509  }
2510 
2511  std::cout << messageStream.str() << std::endl;
2512  messageStream.str("");
2513  messageStream.clear();
2514 
2515  const pcpp::IndexIntervalType &partitionBufferInterval3d(simGrid3d.PartitionBufferInterval());
2516  const pcpp::IndexIntervalType &partitionInterval3d(simGrid3d.PartitionInterval());
2517  numDim = gridSizes.size();
2518 
2519  if(testfixtures::viscid::SetupViscidState(simGrid3d,simState3d,paramState3d,0)){
2520  parTestViscidRHS = false;
2521  std::cout << "Failed to setup state in TestViscidRHS" << std::endl;
2522  return;
2523  }
2524 
2525  numPointsBuffer = simGrid3d.BufferSize();
2526  //bufferSizes.resize(simGrid3d.BufferSizes());
2527  const std::vector<size_t> &bufferSizes3d(simGrid3d.BufferSizes());
2528 
2529  //std::vector<double> &dX.resize(simGrid3d.DX());
2530  std::vector<double> &dX3d(simGrid3d.DX());
2531 
2532  // Add some fields that are not usual
2533  paramState3d.AddField("dX",'s',numDim,8,"space");
2534  paramState3d.Create(numPointsBuffer,0);
2535 
2536  paramState3d.SetFieldBuffer("gamma",&gamma);
2537  paramState3d.SetFieldBuffer("inputDT",&dt);
2538  paramState3d.SetFieldBuffer("inputCFL",&cfl);
2539  paramState3d.SetFieldBuffer("dX",&dX3d[0]);
2540  paramState3d.SetFieldBuffer("refRe",&Re);
2541  paramState3d.SetFieldBuffer("refPr",&Pr);
2542  paramState3d.SetFieldBuffer("power",&power);
2543  paramState3d.SetFieldBuffer("beta",&beta);
2544  paramState3d.SetFieldBuffer("bulkViscFac",&bulkViscFac);
2545 
2546  rho.resize(numPointsBuffer,1.0);
2547  rhoV.resize(numDim*numPointsBuffer,0.0);
2548  rhoE.resize(numPointsBuffer);
2549  rhoE.assign(rhoE.size(),1.0/(gamma-1));
2550 
2551  T.resize(numPointsBuffer,0.0);
2552  p.resize(numPointsBuffer,0.0);
2553  V.resize(numDim*numPointsBuffer,0.0);
2554 
2555  rhom1.resize(numPointsBuffer,0.0);
2556 
2557  simState3d.SetFieldBuffer("simTime",&t);
2558  simState3d.SetFieldBuffer("rho",&rho[0]);
2559  simState3d.SetFieldBuffer("rhoV",&rhoV[0]);
2560  simState3d.SetFieldBuffer("rhoE",&rhoE[0]);
2561 
2562  simState3d.SetFieldBuffer("pressure",&p[0]);
2563  simState3d.SetFieldBuffer("temperature",&T[0]);
2564  simState3d.SetFieldBuffer("velocity",&V[0]);
2565  simState3d.SetFieldBuffer("rhom1",&rhom1[0]);
2566 
2567  state_t rhsState3d(simState3d);
2568 
2569  // -- Set up the RHS --
2570  rhs_t viscidRHS3d;
2571 
2572  if(viscidRHS3d.Initialize(simGrid3d,simState3d,paramState3d,sbpOperator3d)){
2573  parTestViscidRHS = false;
2574  std::cout << "Failed to initialize RHS in TestViscidRHS" << std::endl;
2575  return;
2576  }
2577 
2578  std::vector<int> numThreadsDim3;
2579  simGrid3d.SetupThreads(numThreadsDim3);
2580  viscidRHS3d.InitThreadIntervals();
2581 
2582  if(viscidRHS3d.SetupRHS(simGrid3d,simState3d,rhsState3d)){
2583  parTestViscidRHS = false;
2584  std::cout << "Failed to setup RHS in TestViscidRHS" << std::endl;
2585  return;
2586  }
2587 
2588  parallelUnitResults.UpdateResult("Viscid:RHS:RunsInParallel",parTestViscidRHS);
2589 
2590  //
2591  // setup a 3D periodic velocity field so we can test the velocity gradient
2592  // setup a 3D periodic temperature field so we can test the temperature gradient
2593  // leave the density alone, update the energy even though we don't really need it
2594  //
2595  velGradExpected.resize(numDim*numDim*numPointsBuffer,-999.0);
2596  tempGradExpected.resize(numDim*numPointsBuffer,-999.0);
2597  uAmp.resize(0);
2598  vAmp.resize(0);
2599  tempAmp.resize(0);
2600  std::vector<double> wAmp;
2601  uAmp.push_back(1.0);
2602  uAmp.push_back(2.0);
2603  uAmp.push_back(3.0);
2604  vAmp.push_back(4.0);
2605  vAmp.push_back(5.0);
2606  vAmp.push_back(6.0);
2607  wAmp.push_back(7.0);
2608  wAmp.push_back(8.0);
2609  wAmp.push_back(9.0);
2610  tempAmp.push_back(10.0);
2611  tempAmp.push_back(11.0);
2612  tempAmp.push_back(12.0);
2613  period.resize(numDim,0);
2614  for(int i=0;i<numDim;i++){
2615  period[i]=dX3d[i]*numNodes;
2616  }
2617  x0 = 0.;
2618  y0 = 0.;
2619  double z0 = 0.;
2620  iStart = partitionBufferInterval3d[0].first;
2621  iEnd = partitionBufferInterval3d[0].second;
2622  jStart = partitionBufferInterval3d[1].first;
2623  jEnd = partitionBufferInterval3d[1].second;
2624  size_t kStart = partitionBufferInterval3d[2].first;
2625  size_t kEnd = partitionBufferInterval3d[2].second;
2626  size_t nPlane = bufferSizes3d[0]*bufferSizes3d[1];
2627  for(size_t kIndex = kStart;kIndex <= kEnd;kIndex++){
2628  size_t kBufferIndex = kIndex*nPlane;
2629  size_t kPartIndex = (kIndex - kStart) + partitionInterval3d[2].first;
2630  double z = kPartIndex*dX3d[2];
2631  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2632  size_t jkBufferIndex = kBufferIndex + jIndex*bufferSizes3d[0];
2633  size_t jPartIndex = (jIndex - jStart) + partitionInterval3d[1].first;
2634  double y = jPartIndex*dX3d[1];
2635  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2636  size_t bufferIndex = jkBufferIndex + iIndex;
2637  size_t iPartIndex = (iIndex - iStart) + partitionInterval3d[0].first;
2638  double x = iPartIndex*dX3d[0];
2639 
2640  rhoV[bufferIndex] = rho[bufferIndex]*
2641  testfixtures::viscid::Cosine(uAmp,period,x0,y0,z0,x,y,z,-1);
2642  rhoV[bufferIndex+numPointsBuffer] = rho[bufferIndex]*
2643  testfixtures::viscid::Cosine(vAmp,period,x0,y0,z0,x,y,z,-1);
2644  rhoV[bufferIndex+2*numPointsBuffer] = rho[bufferIndex]*
2645  testfixtures::viscid::Cosine(wAmp,period,x0,y0,z0,x,y,z,-1);
2646 
2647  // just the internal part, add a linear offset
2648  rhoE[bufferIndex] += rho[bufferIndex]/(gamma-1)*
2649  testfixtures::viscid::Cosine(tempAmp,period,x0,y0,z0,x,y,z,-1);
2650 
2651  rhoE[bufferIndex] = rhoE[bufferIndex] + (rhoV[bufferIndex]*rhoV[bufferIndex] +
2652  rhoV[bufferIndex+numPointsBuffer]*
2653  rhoV[bufferIndex+numPointsBuffer] +
2654  rhoV[bufferIndex+2*numPointsBuffer]*
2655  rhoV[bufferIndex+2*numPointsBuffer])/(2.0*rho[bufferIndex]);
2656 
2657  // calculate the exact velocity gradient for comparison
2658  // one big flat vector with numPointsBuffer*numDin^2 size
2659  // each {} is numPoints in size
2660  // [ {du/dx} {dv/dx} {dw/dx} {du/dy} {dv/dy} {dw/dy} {du/dz} {dv/dz} {dw/dz} ]
2661  for(int dIndex = 0; dIndex<numDim; dIndex++){
2662  velGradExpected[bufferIndex+dIndex*numDim*numPointsBuffer] =
2663  testfixtures::viscid::Cosine(uAmp,period,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
2664  velGradExpected[bufferIndex+numPointsBuffer+dIndex*numDim*numPointsBuffer] =
2665  testfixtures::viscid::Cosine(vAmp,period,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
2666  velGradExpected[bufferIndex+2*numPointsBuffer+dIndex*numDim*numPointsBuffer] =
2667  testfixtures::viscid::Cosine(wAmp,period,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
2668  }
2669 
2670  // calculate the exact temperature gradient for comparison
2671  // one big flat vector with numPointsBuffer*numDim size
2672  // each {} is numPoints in size
2673  // [ {dT/dx} {dT/dy} {dT/dz}]
2674  // we remove the grid space as the metrics are applied inside ComputeStressTensor
2675  for(int dIndex = 0; dIndex<numDim; dIndex++){
2676  tempGradExpected[bufferIndex+dIndex*numPointsBuffer] =
2677  testfixtures::viscid::Cosine(tempAmp,period,x0,y0,z0,x,y,z,dIndex)*dX3d[dIndex];
2678  }
2679  }
2680  }
2681  }
2682 
2683  returnCode = viscidRHS3d.ComputeDV(0);
2684  if(returnCode > 0){
2685  VelocityGradientWorks = false;
2686  std::cout << "ComputeVelGrad failed when computing DV " << std::endl;
2687  return;
2688  }
2689 
2690  std::cout << "Calling ComputeVelGrad" << std::endl;
2691  returnCode = viscidRHS3d.ComputeVelGrad(0);
2692  if(returnCode > 0){
2693  VelocityGradientWorks = false;
2694  return;
2695  }
2696 
2697  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
2698  if(!VelocityGradientWorks){
2699  std::cout << "Velocity Gradient Calculation Failed" << std::endl;
2700  }
2701 
2702  if(VelocityGradientWorks){
2703  std::cout << "Checking Velocity Gradient calculation" << std::endl;
2704  // check the velocity gradient
2705  // first get the gradient from the rhs object
2706  // then check against the expected answer
2707  const std::vector<double *> &velGradBuffers3d(viscidRHS3d.VelGradBuffers());
2708 
2709  bool printVelGrad = true;
2710  for(int iDim = 0;iDim < numDim;iDim++){
2711  const double* velGradData3d = velGradBuffers3d[iDim];
2712 
2713  for(int jDim = 0;jDim < numDim;jDim++){
2714  const double* velGradDataComponent3d = &velGradData3d[jDim*numPointsBuffer];
2715 
2716  for(size_t kIndex = kStart;kIndex <= kEnd;kIndex++){
2717  size_t kBufferIndex = kIndex*nPlane;
2718  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2719  size_t jkBufferIndex = kBufferIndex + jIndex*bufferSizes3d[0];
2720  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2721  size_t bufferIndex = jkBufferIndex + iIndex;
2722  size_t expectedIndex = numPointsBuffer*iDim*numDim+jDim*numPointsBuffer+bufferIndex;
2723 
2724  double error = std::abs(velGradDataComponent3d[bufferIndex] -
2725  velGradExpected[expectedIndex])/velGradExpected[expectedIndex];
2726 
2727  if(error > 1e-2){
2728  VelocityGradientWorks = false;
2729  if(printVelGrad) {
2730  std::cout << std::scientific << std::setprecision(16)
2731  << "In ComputeVelGrad: "<< std::endl
2732  << "Expected velGrad=" << velGradExpected[expectedIndex] << std::endl
2733  << " got velGrad=" << velGradDataComponent3d[bufferIndex] << std::endl
2734  << " at (i,j,bufferIndex)=(" << iDim << "," << jDim << ","
2735  << bufferIndex << ")" << std::endl;
2736  std::cout << "Error =" << error << std::endl;;
2737  std::cout << "No further error messages will be generated for velGrad 3d" << std::endl;
2738  printVelGrad=false;
2739  }
2740  }
2741  }
2742  }
2743  }
2744  }
2745  }
2746  }
2747 
2748  VelocityGradientWorks = CheckResult(VelocityGradientWorks,testComm);
2749  if(!VelocityGradientWorks){
2750  std::cout << "Velocity Gradient Compare Failed" << std::endl;
2751  }
2752 
2753  // Compute the temperature gradient
2754  std::cout << "Calculating Temperature Gradient" << std::endl;
2755  returnCode = viscidRHS3d.ComputeTemperatureGrad(0);
2756  if(returnCode > 0){
2757  TemperatureGradientWorks = false;
2758  return;
2759  }
2760 
2761  TemperatureGradientWorks = CheckResult(TemperatureGradientWorks,testComm);
2762  if(!TemperatureGradientWorks){
2763  std::cout << "Temperature Gradient Calculation Failed" << std::endl;
2764  }
2765 
2766  // check the temperature gradient
2767  // first get the gradient from the rhs object
2768  // then check against the expected answer
2769  std::cout << "Checking Temperature Gradient calculation" << std::endl;
2770  const std::vector<double *> &tempGradBuffers3d(viscidRHS3d.TemperatureGradBuffers());
2771 
2772  if(TemperatureGradientWorks){
2773  bool printTempGrad = true;
2774  for(int iDim = 0;iDim < numDim;iDim++){
2775  const double* tempGradDataComponent = tempGradBuffers3d[iDim];
2776 
2777  for(size_t kIndex = kStart;kIndex <= kEnd;kIndex++){
2778  size_t kBufferIndex = kIndex*nPlane;
2779  for(size_t jIndex = jStart;jIndex <= jEnd;jIndex++){
2780  size_t jkBufferIndex = kBufferIndex + jIndex*bufferSizes3d[0];
2781  for(size_t iIndex = iStart;iIndex <= iEnd;iIndex++){
2782  size_t bufferIndex = jkBufferIndex + iIndex;
2783  size_t expectedIndex = bufferIndex + numPointsBuffer*iDim;
2784 
2785  double error = std::abs(tempGradDataComponent[bufferIndex] -
2786  tempGradExpected[expectedIndex])/tempGradExpected[expectedIndex];
2787 
2788  if(error > 1e-2){
2789  TemperatureGradientWorks = false;
2790  if(printTempGrad) {
2791  std::cout << std::scientific << std::setprecision(16)
2792  << "In ComputeTemperatureGrad: "<< std::endl
2793  << "Expected tempGrad=" << tempGradExpected[expectedIndex] << std::endl
2794  << " got tempGrad=" << tempGradDataComponent[bufferIndex] << std::endl
2795  << " at (i,bufferIndex)=(" << iDim << ","
2796  << bufferIndex << ")" << std::endl;
2797  std::cout << "Temperature " << T[bufferIndex] << std::endl;
2798  std::cout << "Error =" << error << std::endl;;
2799  std::cout << "No further error messages will be generated for tempGrad 3D Linear"
2800  << std::endl;
2801  printTempGrad=false;
2802  }
2803  }
2804  }
2805  }
2806  }
2807  }
2808  }
2809 
2810  std::cout << "Done with 3D periodic Velocity Gradient Test" << std::endl;
2811 
2812  parallelUnitResults.UpdateResult("Viscid:RHS:VelocityGradientPeriodic",VelocityGradientWorks);
2813  parallelUnitResults.UpdateResult("Viscid:RHS:TemperatureGradientPeriodic",TemperatureGradientWorks);
2814 
2815  std::cout << "Done TestVelocityGradientPeriodic..." << std::endl;
2816 
2817 };
2818 
2819 void TestViscidRHS(ix::test::results &parallelUnitResults,pcpp::CommunicatorType &testComm)
2820 {
2821  std::cout << "TestViscidRHS..." << std::endl;
2822 
2829 
2833 
2834  std::ostringstream messageStream;
2835 
2836  grid_t simGrid;
2837  operator_t sbpOperator;
2838  halo_t &simHalo(simGrid.Halo());
2839  state_t simState;
2840  state_t paramState;
2841 
2842  bool parTestViscidRHS = true;
2843  std::vector<size_t> gridSizes(3,4);
2844 
2845  if(testfixtures::CreateSimulationFixtures(simGrid,simHalo,sbpOperator,
2846  gridSizes,2,testComm,&messageStream)){
2847  parTestViscidRHS = false;
2848  return;
2849  }
2850 
2851  pcpp::IndexIntervalType &partitionBufferInterval(simGrid.PartitionBufferInterval());
2852 
2853  if(testfixtures::viscid::SetupViscidState(simGrid,simState,paramState,0)){
2854  parTestViscidRHS = false;
2855  return;
2856  }
2857 
2858  std::cout << messageStream.str() << std::endl;
2859 
2860  size_t numPointsBuffer = simGrid.BufferSize();
2861 
2862  double t = 0.0;
2863  double gamma = 1.4;
2864  double power = 2.0/3.0;
2865  double beta = 1.0;
2866  double bulkViscFac = 0.6;
2867  double dt = .001;
2868  double cfl = 1.0;
2869  double Re = 100.0;
2870  double Pr = 0.75;
2871  // double numbers[] = {};
2872  int flags = 1;
2873 
2874  int numDim = 3;
2875 
2876  paramState.SetFieldBuffer("gamma",&gamma);
2877  paramState.SetFieldBuffer("inputDT",&dt);
2878  paramState.SetFieldBuffer("inputCFL",&cfl);
2879  paramState.SetFieldBuffer("refRe",&Re);
2880  paramState.SetFieldBuffer("refPr",&Pr);
2881  paramState.SetFieldBuffer("power",&power);
2882  paramState.SetFieldBuffer("beta",&beta);
2883  paramState.SetFieldBuffer("bulkViscFac",&bulkViscFac);
2884  // paramState.SetFieldBuffer("Numbers",numbers);
2885  paramState.SetFieldBuffer("Flags",&flags);
2886 
2887  std::vector<double> rho(numPointsBuffer,1.0);
2888  std::vector<double> rhoV(3*numPointsBuffer,0.0);
2889  std::vector<double> rhoE(3*numPointsBuffer,1.0/(gamma-1.0));
2890 
2891  std::vector<double> dRho(numPointsBuffer,0.0);
2892  std::vector<double> dRhoV(3*numPointsBuffer,0.0);
2893  std::vector<double> dRhoE(numPointsBuffer,0.0);
2894 
2895  std::vector<double> T(numPointsBuffer,0.0);
2896  std::vector<double> p(numPointsBuffer,0.0);
2897  std::vector<double> V(3*numPointsBuffer,0.0);
2898 
2899  std::vector<double> rhom1(numPointsBuffer,0.0);
2900 
2901 
2902  simState.SetFieldBuffer("simTime",&t);
2903  simState.SetFieldBuffer("rho",&rho[0]);
2904  simState.SetFieldBuffer("rhoV",&rhoV[0]);
2905  simState.SetFieldBuffer("rhoE",&rhoE[0]);
2906 
2907  simState.SetFieldBuffer("pressure",&p[0]);
2908  simState.SetFieldBuffer("temperature",&T[0]);
2909  simState.SetFieldBuffer("velocity",&V[0]);
2910  simState.SetFieldBuffer("rhom1",&rhom1[0]);
2911 
2912  state_t rhsState(simState);
2913 
2914  rhsState.SetFieldBuffer("rho",&dRho[0]);
2915  rhsState.SetFieldBuffer("rhoV",&dRhoV[0]);
2916  rhsState.SetFieldBuffer("rhoE",&dRhoE[0]);
2917 
2918  // set up the domain - don't care about this in testing
2919  // domain_t eulerDomain;
2920  // eulerDomain.numGrids = 1;
2921  // eulerDomain.Grids().resize(1,&simGrid);
2922  // eulerDomain.States().resize(1,&simState);
2923 
2924  // -- Set up the RHS --
2925  rhs_t eulerRHS;
2926 
2927  std::cout << "Initialize" << std::endl;
2928  if(eulerRHS.Initialize(simGrid,simState,paramState,sbpOperator)){
2929  parTestViscidRHS = false;
2930  return;
2931  }
2932 
2933  std::cout << "SetupRHS" << std::endl;
2934  if(eulerRHS.SetupRHS(simGrid,simState,rhsState)){
2935  parTestViscidRHS = false;
2936  return;
2937  }
2938 
2939  simGrid.SetNumThreads(1);
2940  eulerRHS.InitThreadIntervals();
2941 
2942 
2943  std::cout << "RHS" << std::endl;
2944  int returnCode = eulerRHS.RHS(0);
2945  if(returnCode > 0){
2946  parTestViscidRHS = false;
2947  }
2948  std::cout << "Done RHS" << std::endl;
2949 
2950  parTestViscidRHS = CheckResult(parTestViscidRHS,testComm);
2951  if(!parTestViscidRHS){
2952  std::cout << "Problem 0" << std::endl;
2953  }
2954 
2955  if(parTestViscidRHS){
2956  for(size_t iPoint = 0;(iPoint < numPointsBuffer)&&parTestViscidRHS;iPoint++){
2957  if(std::abs(dRho[iPoint]) > 1e-15) parTestViscidRHS = false;
2958  for(int iDim = 0;iDim < numDim;iDim++)
2959  if(std::abs(dRhoV[iPoint+iDim*numPointsBuffer]) > 1e-15) parTestViscidRHS = false;
2960  if(std::abs(dRhoE[iPoint]) > 1e-15) parTestViscidRHS = false;
2961  }
2962  }
2963 
2964  parTestViscidRHS = CheckResult(parTestViscidRHS,testComm);
2965  if(!parTestViscidRHS){
2966  std::cout << "Problem 1" << std::endl;
2967  }
2968 
2969  parallelUnitResults.UpdateResult("Viscid:ViscidRHS:3dWorksInParallel",parTestViscidRHS);
2970 
2971 
2972 };
2973 
2983 {
2984 
2985  std::cout << "Running viscid kernels tests with full curvilinear metrics."
2986  << std::endl;
2987 
2988  bool tauCurvilinear = true;
2989  bool qCurvilinear = true;
2990  bool flux1dTest = true;
2991 
2992  for(int numDim = 1;numDim <= 3;numDim++){
2993 
2994 
2995  std::vector<size_t> numPoints(numDim,1);
2996  size_t numPointsBuffer = 1;
2997  for(int iDim = 0;iDim < numDim;iDim++){
2998  numPoints[iDim] = 2*std::pow(2,iDim) + 1;
2999  numPointsBuffer *= numPoints[iDim];
3000  // std::cout << "NumPoints[" << iDim << "] = " << numPoints[iDim] << std::endl;
3001  }
3002 
3003  // std::cout << "NumPoints = " << numPointsBuffer << std::endl;
3004 
3005  std::vector<double> mu(numPointsBuffer,0.0);
3006  std::vector<double> lambda(numPointsBuffer,0.0);
3007  std::vector<double> gradVIJK(numDim*numDim*numPointsBuffer,0.0);
3008  std::vector<double> gradVXYZ(numDim*numDim*numPointsBuffer,0.0);
3009  std::vector<double> gridJacobian(numPointsBuffer,0.0);
3010  std::vector<double> gridMetric(numDim*numDim*numPointsBuffer,0.0);
3011  std::vector<double> velocity(numDim*numPointsBuffer,0.0);
3012  std::vector<double> gradT(numDim*numPointsBuffer,0.0);
3013  std::vector<double> tau(numDim*numDim*numPointsBuffer,0.0);
3014  std::vector<double> expectedTau(numDim*numDim*numPointsBuffer,0.0);
3015 
3016  double piValue = 4.0*std::atan(1.0);
3017  double Re = 25.0;
3018  std::vector<double> metricValues(numDim*numDim,0.0);
3019  std::vector<double> gradValuesIJK(numDim*numDim,0.0);
3020  std::vector<double> gradValuesXYZ(numDim*numDim,0.0);
3021  // All the metric and gradient components are set to
3022  // the following for all points:
3023  //
3024  // metric = |.01 .02 | | .01 .02 .03 |
3025  // |.03 .04 |, | .04 .05 .06 |
3026  // | .07 .08 .09 |
3027  //
3028  // **NOTE: gradVIJK goes like: dV(j)/dX(i) (i.e. the *transpose* of gradV(ijk))
3029  //
3030  // gradVIJK = | 1 2 | | 1 2 3 |
3031  // | 3 4 |, | 4 5 6 |
3032  // | 7 8 9 |
3033  for(int iDim = 0;iDim < numDim;iDim++){
3034  for(int jDim = 0;jDim < numDim;jDim++){
3035  int component = iDim*numDim + jDim;
3036  gradValuesIJK[component] = static_cast<double>(component + 1);
3037  metricValues[component] = static_cast<double>(component+1)/100.0;
3038  // std::cout << "GradValuesIJK[" << iDim << "][" << jDim << "] = " << gradValuesIJK[component] << std::endl
3039  // << "metricValues[" << iDim << "][" << jDim << "] = " << metricValues[component] << std::endl;
3040  for(size_t iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3041  gradVIJK[component*numPointsBuffer+iPoint] = gradValuesIJK[component];
3042  gridMetric[component*numPointsBuffer+iPoint] = metricValues[component];
3043  }
3044  }
3045  }
3046 
3047  // Velocity = <1, 2, 3>
3048  // gradT = <4 , 5, 6>
3049  for(int iDim = 0;iDim < numDim;iDim++){
3050  for(size_t iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3051  velocity[iDim*numPointsBuffer+iPoint] = static_cast<double>(iDim+1);
3052  gradT[iDim*numPointsBuffer+iPoint] = static_cast<double>(iDim+4);
3053  }
3054  }
3055 
3056  // Jacobian = iPoint + 1
3057  // mu = ((iPoint*iPoint) + 1)/1000.0
3058  // lambda = COS(iPoint/2PI)
3059  for(size_t iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3060  gridJacobian[iPoint] = static_cast<double>(iPoint+1);
3061  mu[iPoint] = static_cast<double>(iPoint*iPoint + 1)/1000.0;
3062  lambda[iPoint] = std::cos(static_cast<double>(iPoint+1)/(2.0*piValue));
3063  }
3064 
3065 
3066 
3067  double divValue = 0.0;
3068  for(int iDim = 0;iDim < numDim;iDim++){
3069  int gradOffset = iDim;
3070  for(int jDim = 0;jDim < numDim;jDim++){
3071  int component = iDim*numDim + jDim;
3072  int metricOffset = jDim;
3073  for(int kDim = 0;kDim < numDim;kDim++){
3074  gradValuesXYZ[component] += gradValuesIJK[gradOffset+kDim*numDim]*metricValues[jDim+kDim*numDim];
3075  }
3076  if(iDim == jDim)
3077  divValue += gradValuesXYZ[component];
3078  }
3079  }
3080 
3081  pcpp::IndexIntervalType regionInterval;
3082  regionInterval.InitSimple(numPoints);
3083  std::vector<size_t> fortranInterval;
3084  regionInterval.Flatten(fortranInterval);
3085  for(int iDim = 0;iDim < numDim;iDim++){
3086  fortranInterval[iDim*2]++;
3087  fortranInterval[iDim*2+1]++;
3088  }
3089 
3091  std::vector<double*> bufferPtrArray(10,NULL);
3092  bufferPtrArray[0] = &mu[0];
3093  bufferPtrArray[1] = &lambda[0];
3094  bufferPtrArray[2] = &lambda[0];
3095  std::vector<double *> velGradBuffers(numDim,NULL);
3096  std::vector<double *> tauBuffers(numDim*numDim,NULL);
3097 
3098  for(int iDim = 0;iDim < numDim;iDim++){
3099  velGradBuffers[iDim] = &gradVIJK[iDim*numDim*numPointsBuffer];
3100  for(int jDim = 0;jDim < numDim;jDim++){
3101  size_t tauComponent = iDim*numDim + jDim;
3102  size_t tauTComponent = jDim*numDim + iDim;
3103  if(iDim <= jDim){
3104  tauBuffers[tauComponent] = &tau[tauComponent*numPointsBuffer];
3105  if(iDim == jDim){
3106  for(size_t iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3107  expectedTau[tauComponent*numPointsBuffer+iPoint] = (gridJacobian[iPoint]/Re)*
3108  (mu[iPoint]*(gradValuesXYZ[tauComponent]+gradValuesXYZ[tauTComponent]) +
3109  lambda[iPoint]*divValue);
3110  // std::cout << "expectedTau[" << iDim << "][" << jDim << "]["
3111  // << iPoint << "] = " << expectedTau[tauComponent*numPointsBuffer+iPoint]
3112  // << std::endl;
3113  }
3114  } else {
3115  for(size_t iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3116  expectedTau[tauComponent*numPointsBuffer+iPoint] = (gridJacobian[iPoint]/Re)*
3117  (mu[iPoint]*(gradValuesXYZ[tauComponent]+gradValuesXYZ[tauTComponent]));
3118  // std::cout << "expectedTau[" << iDim << "][" << jDim << "]["
3119  // << iPoint << "] = " << expectedTau[tauComponent*numPointsBuffer+iPoint]
3120  // << std::endl;
3121  }
3122  }
3123  } else {
3124  tauBuffers[tauComponent] = &tau[tauTComponent*numPointsBuffer];
3125  for(size_t iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3126  expectedTau[tauComponent*numPointsBuffer+iPoint] = (gridJacobian[iPoint]/Re)*
3127  (mu[iPoint]*(gradValuesXYZ[tauComponent]+gradValuesXYZ[tauTComponent]));
3128  // std::cout << "expectedTau[" << iDim << "][" << jDim << "]["
3129  // << iPoint << "] = " << expectedTau[tauComponent*numPointsBuffer+iPoint]
3130  // << std::endl;
3131 
3132  }
3133  }
3134  }
3135  }
3136 
3137  std::cout << "Checking tau in " << numDim << " dimensions...";
3138  if(viscid::util::ComputeTauBuffer(regionInterval,numPoints,gridType,gridMetric,gridJacobian,
3139  Re,bufferPtrArray,velGradBuffers,tauBuffers)){
3140  std::cout << "Compute Tau failed." << std::endl;
3141  return;
3142  }
3143 
3144  double errMax = -10000.0;
3145  double errMin = 1000000.0;
3146  double error = 0;
3147  for(int iDim = 0;iDim < numDim;iDim++){
3148  for(int jDim = 0;jDim < numDim;jDim++){
3149  size_t tauComponent = iDim*numDim + jDim;
3150  size_t tauIndex = tauComponent*numPointsBuffer;
3151  if(iDim <= jDim){
3152  for(size_t iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3153  error = std::abs(tau[tauComponent+iPoint] -
3154  expectedTau[tauComponent+iPoint])/std::abs(expectedTau[tauComponent+iPoint]);
3155  // std::cout << "Actual Tau[" << iDim << "][" << jDim << "][" << iPoint << "] = "
3156  // << tau[tauComponent+iPoint] << std::endl;
3157  if(error > errMax) errMax = error;
3158  if(error < errMin) errMin = error;
3159  }
3160  }
3161  }
3162  }
3163  double tol = 1e-15;
3164  if(errMax > tol){
3165  tauCurvilinear = false;
3166  std::cout << "failed." << std::endl
3167  << "TAU Error: " << errMax << std::endl;
3168  } else {
3169  std::cout << "passed." << std::endl;
3170  }
3171 
3172  std::vector<double> expectedQ(numDim*numPointsBuffer,0.0);
3173  std::vector<double> q(numDim*numPointsBuffer,0.0);
3174  std::vector<double *> gradTBuffers(numDim,NULL);
3175  std::vector<double *> heatFluxBuffers(numDim,NULL);
3176  for(int iDim = 0;iDim < numDim;iDim++){
3177  gradTBuffers[iDim] = &gradT[iDim*numPointsBuffer];
3178  heatFluxBuffers[iDim] = &q[iDim*numPointsBuffer];
3179  size_t qIndex = iDim*numPointsBuffer;
3180  double dTdX = 0.0;
3181  for(int jDim = 0;jDim < numDim;jDim++){
3182  // Compute dT/dX(iDim)
3183  double gradTValue = gradT[jDim*numPointsBuffer];
3184  dTdX += gradTValue*metricValues[iDim+jDim*numDim];
3185  }
3186 
3187  for(int iPoint = 0;iPoint < numPointsBuffer;iPoint++)
3188  expectedQ[qIndex+iPoint] = lambda[iPoint]*gridJacobian[iPoint]*dTdX/Re;
3189  }
3190 
3191  std::cout << "Checking heat flux in " << numDim << " dimensions....";
3192 
3193  if(viscid::util::ComputeHeatFluxBuffer(regionInterval,numPoints,gridType,gridMetric,
3194  gridJacobian,Re,bufferPtrArray,gradTBuffers,
3195  heatFluxBuffers)){
3196  std::cout << "ComputeHeatFlux failed." << std::endl;
3197  return;
3198  }
3199  errMax = -100000.0;
3200  errMin = 1000000.0;
3201  for(int iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3202  double err = std::abs(q[iPoint] - expectedQ[iPoint])/std::abs(expectedQ[iPoint]);
3203  if(err > tol){
3204  // std::cout << "Q[" << iPoint << "] = " << q[iPoint] << " Expected: " << expectedQ[iPoint] << std::endl;
3205  qCurvilinear = false;
3206  }
3207  if(errMax < err) errMax = err;
3208  if(errMin > err) errMin = err;
3209  }
3210  if(errMax > tol){
3211  std::cout << "failed." << std::endl
3212  << "Max Heat Flux Error : " << errMax << std::endl;
3213  } else {
3214  std::cout << "passed." << std::endl;
3215  }
3216 
3217  // prescribe a whole other tau, one with whole numbers for easy debugging
3218  int tComponent = 0;
3219  int numTauComponents = (numDim*(numDim+1))/2;
3220  std::vector<double> tau2(numTauComponents*numPointsBuffer,0);
3221  for(int iDim = 0;iDim < numDim;iDim++){
3222  for(int jDim = 0;jDim < numDim;jDim++){
3223  if(iDim <= jDim){
3224  for(int iPoint = 0;iPoint < numPointsBuffer;iPoint++)
3225  tau2[tComponent*numPointsBuffer+iPoint] = mu[iPoint]*(tComponent+1);
3226  tComponent++;
3227  }
3228  }
3229  }
3230 
3231  std::vector<double> energyVector(numDim*numPointsBuffer,0);
3232  for(int iDim = 0;iDim < numDim;iDim++){
3233  for(int iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3234  energyVector[iDim*numPointsBuffer+iPoint] = lambda[iPoint]*(iDim+1);
3235  }
3236  }
3237 
3238 
3239  // index2D = RESHAPE((/ 0, 1, 1, 2 /), SHAPE(index2D))
3240  // index3D = RESHAPE((/ 0, 1, 2, 1, 3, 4, 2, 4, 5 /), SHAPE(index3D))
3241  std::vector<int> symmetricIndex(numDim*numDim,0);
3242  if(numDim == 1)
3243  symmetricIndex[0] = 0;
3244  if(numDim == 2){
3245  symmetricIndex[0] = 0;
3246  symmetricIndex[1] = 1;
3247  symmetricIndex[2] = 1;
3248  symmetricIndex[3] = 2;
3249  }
3250  if(numDim == 3){
3251  symmetricIndex[0] = 0;
3252  symmetricIndex[1] = 1;
3253  symmetricIndex[2] = 2;
3254  symmetricIndex[3] = 1;
3255  symmetricIndex[4] = 3;
3256  symmetricIndex[5] = 4;
3257  symmetricIndex[6] = 2;
3258  symmetricIndex[7] = 4;
3259  symmetricIndex[8] = 5;
3260  }
3261 
3262  std::cout << "Checking flux in " << numDim << " dimensions....";
3263  for(int iDim = 0;iDim < numDim;iDim++){
3264 
3265  int fluxDir = iDim+1;
3266 
3267  std::cout << "(" << fluxDir << ")...";
3268 
3269  int metricOffset = iDim*numDim*numPointsBuffer; // offset to appropriate row of metric
3270 
3271  std::vector<double> flux((numDim+2)*numPointsBuffer,0);
3272  std::vector<double> expectedFlux((numDim+2)*numPointsBuffer,0);
3273 
3274  FC_MODULE(viscid,strongflux1d,VISCID,STRONGFLUX1D)
3275  (&numDim,&fluxDir,&numPoints[0],&numPointsBuffer,&fortranInterval[0],
3276  &gridType,&gridMetric[0],&tau2[0],&energyVector[0],&flux[0]);
3277 
3278  // expected flux is row of metric dot column of tau (for momentum)
3279  for(int jDim = 0;jDim < numDim;jDim++){
3280  // need jDim(th) column of tau
3281  for(int kDim = 0;kDim < numDim;kDim++){
3282  int tauComponent = symmetricIndex[jDim+kDim*numDim];
3283  double *metricComponent = &gridMetric[metricOffset+kDim*numPointsBuffer];
3284  for(int iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3285  expectedFlux[(jDim+1)*numPointsBuffer + iPoint] +=
3286  metricComponent[iPoint]*tau2[tauComponent*numPointsBuffer+iPoint];
3287  }
3288  }
3289  }
3290 
3291  // expected flux is row of metric dot Q (for energy)
3292  for(int jDim = 0;jDim < numDim;jDim++){
3293  double *metricComponent = &gridMetric[metricOffset+jDim*numPointsBuffer];
3294  for(int iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3295  expectedFlux[(numDim+1)*numPointsBuffer + iPoint] +=
3296  metricComponent[iPoint]*energyVector[jDim*numPointsBuffer+iPoint];
3297  }
3298  }
3299 
3300  double maxError = -10000.0;
3301  double minError = 10000.0;
3302  for(int iDim = 0;iDim < numDim+2;iDim++){
3303  bool triggered = false;
3304  for(int iPoint = 0;iPoint < numPointsBuffer;iPoint++){
3305  double error = std::abs(flux[iDim*numPointsBuffer+iPoint] -
3306  expectedFlux[iDim*numPointsBuffer+iPoint])/
3307  std::abs(expectedFlux[iDim*numPointsBuffer+iPoint]);
3308  if(error > tol){
3309  if(!triggered){
3310  std::cout << "Flux component " << iDim << " failed." << std::endl;
3311  triggered = true;
3312  }
3313  flux1dTest = false;
3314  }
3315  if(error > maxError) maxError = error;
3316  if(error < minError) minError = error;
3317  }
3318  }
3319  if(maxError > tol){
3320  std::cout << "failed." << std::endl
3321  << "Max flux error: " << maxError << std::endl;
3322  flux1dTest = false;
3323  }
3324  }
3325  if(flux1dTest){
3326  std::cout << "passed." << std::endl;
3327  }
3328  }
3329 
3330  serialUnitResults.UpdateResult("Viscid:ComputeHeatFlux:Curvilinear",qCurvilinear);
3331  serialUnitResults.UpdateResult("Viscid:ComputeTau:Curvilinear",tauCurvilinear);
3332  serialUnitResults.UpdateResult("Viscid:StrongFlux1D:Curvilinear",flux1dTest);
3333 
3334  return;
3335 
3336 };
double Cosine(std::vector< double > amp, std::vector< double > period, double x0, double y0, double z0, double x, double y, double z, int direction)
void const size_t const size_t const size_t const int const int const double * gridMetric
Definition: EulerKernels.H:10
int ComputeDVBuffer(const pcpp::IndexIntervalType &regionInterval, const std::vector< size_t > &bufferSizes, const std::vector< double *> &stateBuffers, std::vector< double *> &dvBuffers)
Definition: EulerUtil.C:153
int ComputeTauBuffer(const pcpp::IndexIntervalType &regionInterval, const std::vector< size_t > &bufferSize, int gridType, const std::vector< double > &gridMetrics, const std::vector< double > &gridJacobian, const double &Re, const std::vector< double *> &tvBuffers, const std::vector< double *> &velGradBuffers, std::vector< double *> &tauBuffers)
Definition: ViscidUtil.C:113
void TestVelocityGradient(ix::test::results &parallelUnitResults, pcpp::CommunicatorType &testComm)
subroutine ywxpy(numDim, numPoints, bufferSize, bufferInterval, W, X, Y)
YWXPY point-wise operator performing Y = WX + Y, where all are vectors.
Definition: Operators.f90:835
void SetPeriodicDirs(const std::vector< bool > &inPeriodic)
Definition: Grid.H:586
void Flatten(ContainerType &output) const
Definition: IndexUtil.H:274
void const size_t * numPoints
Definition: EulerKernels.H:10
void TestVelocityGradientPeriodic(ix::test::results &parallelUnitResults, pcpp::CommunicatorType &testComm)
plascom2::operators::sbp::base operator_t
const std::vector< double > & DX() const
Definition: Grid.H:538
pcpp::IndexIntervalType & PartitionInterval()
Definition: Grid.H:500
void SetNumThreads(int numThreads)
Definition: Grid.C:2291
int ComputeHeatFluxBuffer(const pcpp::IndexIntervalType &regionInterval, const std::vector< size_t > &bufferSize, int gridType, const std::vector< double > &gridMetrics, const std::vector< double > &gridJacobian, const double &Re, const std::vector< double *> &tvBuffers, const std::vector< double *> &temperatureGradBuffers, std::vector< double *> &heatFluxBuffers)
Definition: ViscidUtil.C:627
void const size_t const size_t * gridSizes
Definition: EulerKernels.H:10
bool CheckResult(bool &localResult, pcpp::CommunicatorType &testComm)
Definition: PCPPCommUtil.C:176
void const size_t const size_t const size_t const double const double double * y
void SetupPressureBuffer(double *const inPtr)
Definition: EOS.H:69
int ComputePressureBuffer(const pcpp::IndexIntervalType &regionInterval, const std::vector< size_t > &bufferSizes)
Compute pressure for the entire buffer.
Definition: EOS.C:5
void const size_t const size_t const size_t const int const int * gridType
Definition: EulerKernels.H:10
pcpp::CommunicatorType comm_t
void SetGamma(const double &inValue)
Definition: EOS.H:174
virtual size_t Create(size_t number_of_nodes=0, size_t number_of_cells=0)
void SetSpecificGasConstant(const double &inValue)
Definition: EOS.H:167
void const size_t const size_t const size_t const int * fluxDir
Definition: EulerKernels.H:10
void const size_t const size_t const size_t const int const double const int const double * velocity
Definition: MetricKernels.H:19
pcpp::IndexIntervalType interval_t
void SetupInternalEnergyBuffer(double *const inPtr)
Definition: EOS.H:73
void SetGridSizes(const std::vector< size_t > &inSize)
Definition: Grid.H:452
pcpp::ParallelGlobalType global_t
Definition: TestHDF5.C:16
subroutine strongflux1d(numDim, fluxDir, gridSizes, numPoints, opInterval, gridType, gridMetric, tauBuffer, energyBuffer, fluxBuffer)
Compute the curvilinear cartesian viscous fluxes in 1 dimension.
Definition: Viscid.f90:126
void const size_t const size_t const size_t const double const double * x
const std::vector< size_t > & BufferSizes() const
Definition: Grid.H:459
void SetupTemperatureBuffer(double *const inPtr)
Definition: EOS.H:70
static const int NUMGRIDTYPES
Definition: Grid.H:29
Encapsulating class for collections of test results.
Definition: Testing.H:18
void TestViscidKernelsMetrics(ix::test::results &serialUnitResults)
Tests viscid kernels on uniform grid using all metric types.
simulation::domain::base< grid_t, state_t > domain_t
Definition: PlasCom2.H:19
simulation::state::base state_t
Definition: Viscid.f90:1
pcpp::IndexIntervalType & PartitionBufferInterval()
Definition: Grid.H:519
void TestViscidRHS(ix::test::results &parallelUnitResults, pcpp::CommunicatorType &testComm)
const std::vector< size_t > & GridSizes() const
Definition: Grid.H:469
void SetupSpecificVolumeBuffer(double *const inPtr)
Definition: EOS.H:71
void SetGridSpacings(const std::vector< double > &inSpacing)
Definition: Grid.H:540
int InitializeSimulationFixtures(GridType &inGrid, plascom2::operators::sbp::base &inOperator, int interiorOrder, pcpp::CommunicatorType &inComm, std::ostream *messageStreamPtr=NULL)
Definition: EulerUtil.H:218
int ComputeTVBufferPower(const pcpp::IndexIntervalType &regionInterval, const std::vector< size_t > &bufferSize, const double *temperatureBuffer, std::vector< double *> &tvBuffer, const double beta, const double power, const double bulkViscFac, const double specificHeat, const double prandtlNumber)
Compute transport coefficients using the power law.
Definition: ViscidUtil.C:14
Main encapsulation of MPI.
Definition: COMM.H:62
int InitializeMaterialProperties()
Derive material properties from a minimum required set.
Definition: EOS.H:145
void size_t int size_t int size_t int int int int double int int double double *void size_t int size_t int int int int int double int size_t size_t size_t double double *void size_t int size_t int size_t size_t int double int double double *void size_t size_t size_t double * a
Testing constructs for unit testing.
double Linear(std::vector< double > amp, double x0, double y0, double z0, double x, double y, double z, int direction)
int SetupViscidState(const GridType &inGrid, StateType &inState, StateType &inParams, int numScalars, bool withFluxes=false)
int SetupThreads(std::vector< int > &numThreadPartitions)
Definition: Grid.C:2174
Encapsulation for a collection of operator stencils.
Definition: Stencil.H:26
void const size_t const size_t const size_t const int const double * gridJacobian
Definition: MetricKernels.H:9
int CreateSimulationFixtures(GridType &inGrid, HaloType &inHalo, plascom2::operators::sbp::base &inOperator, const std::vector< size_t > &gridSizes, int interiorOrder, pcpp::CommunicatorType &inComm, std::ostream *messageStreamPtr=NULL)
Definition: TestFixtures.H:31
void const size_t const size_t * bufferSizes
Definition: MetricKernels.H:19
void const size_t const size_t const size_t const int const double * V
void size_t int size_t int size_t int int int int double int int double double *void size_t int size_t int int int int int double int size_t size_t size_t double double *void size_t int size_t int size_t size_t int double int double double *void size_t size_t size_t * bufferInterval
void UpdateResult(const std::string &name, const ValueType &result)
Updates an existing test result.
Definition: Testing.H:55
Perfect Gas Equation of State.
Definition: EOS.H:124
const std::vector< double > & PhysicalExtent() const
Definition: Grid.H:533
Definition: EulerRHS.H:33
simulation::grid::halo halo_t
Definition: PlasCom2.H:18
Simple Block Structured Mesh object.
Definition: IndexUtil.H:21
void AddField(const std::string &name, char loc, unsigned int ncomp, unsigned int dsize, const std::string &unit)
fixtures::CommunicatorType & Communicator() const
Definition: Grid.H:350
simulation::grid::parallel_blockstructured grid_t
Definition: PlasCom2.H:16
int ComputeTemperatureBuffer(const pcpp::IndexIntervalType &regionInterval, const std::vector< size_t > &bufferSizes)
Compute temperature for the entire buffer.
Definition: EOS.C:52
void SetFieldBuffer(const std::string &name, void *buf)
void TestViscidKernelsCurvilinear(ix::test::results &serialUnitResults)
Tests viscid kernels with full curvilinear metrics.
void SetPhysicalExtent(const std::vector< double > &inExtent)
Definition: Grid.H:535
int Finalize(bool allocateCoordinateData=false)
Definition: Grid.C:2318
void InitSimple(const ContainerType &inSize)
Definition: IndexUtil.H:169
void const size_t * numPointsBuffer
Definition: MetricKernels.H:19
void TestViscidKernels(ix::test::results &serialUnitResults)
void FC_MODULE(euler, flux1d, EULER, FLUX1D)(const int *numDim