Intrepid
test_02.cpp
1 // @HEADER
2 // ************************************************************************
3 //
4 // Intrepid Package
5 // Copyright (2007) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Pavel Bochev (pbboche@sandia.gov)
38 // Denis Ridzal (dridzal@sandia.gov), or
39 // Kara Peterson (kjpeter@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
53 #include "Intrepid_ArrayTools.hpp"
55 #include "Intrepid_CellTools.hpp"
56 #include "Teuchos_oblackholestream.hpp"
57 #include "Teuchos_RCP.hpp"
58 #include "Teuchos_GlobalMPISession.hpp"
59 #include "Teuchos_SerialDenseMatrix.hpp"
60 #include "Teuchos_SerialDenseVector.hpp"
61 #include "Teuchos_LAPACK.hpp"
62 
63 using namespace std;
64 using namespace Intrepid;
65 
66 void rhsFunc(FieldContainer<double> &, const FieldContainer<double> &, int, int, int);
67 void neumann(FieldContainer<double> & ,
68  const FieldContainer<double> & ,
69  const FieldContainer<double> & ,
70  const shards::CellTopology & ,
71  int, int, int, int);
72 void u_exact(FieldContainer<double> &, const FieldContainer<double> &, int, int, int);
73 
75 void rhsFunc(FieldContainer<double> & result,
76  const FieldContainer<double> & points,
77  int xd,
78  int yd,
79  int zd) {
80 
81  int x = 0, y = 1, z = 2;
82 
83  // second x-derivatives of u
84  if (xd > 1) {
85  for (int cell=0; cell<result.dimension(0); cell++) {
86  for (int pt=0; pt<result.dimension(1); pt++) {
87  result(cell,pt) = - xd*(xd-1)*std::pow(points(cell,pt,x), xd-2) *
88  std::pow(points(cell,pt,y), yd) * std::pow(points(cell,pt,z), zd);
89  }
90  }
91  }
92 
93  // second y-derivatives of u
94  if (yd > 1) {
95  for (int cell=0; cell<result.dimension(0); cell++) {
96  for (int pt=0; pt<result.dimension(1); pt++) {
97  result(cell,pt) -= yd*(yd-1)*std::pow(points(cell,pt,y), yd-2) *
98  std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,z), zd);
99  }
100  }
101  }
102 
103  // second z-derivatives of u
104  if (zd > 1) {
105  for (int cell=0; cell<result.dimension(0); cell++) {
106  for (int pt=0; pt<result.dimension(1); pt++) {
107  result(cell,pt) -= zd*(zd-1)*std::pow(points(cell,pt,z), zd-2) *
108  std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,y), yd);
109  }
110  }
111  }
112 
113  // add u
114  for (int cell=0; cell<result.dimension(0); cell++) {
115  for (int pt=0; pt<result.dimension(1); pt++) {
116  result(cell,pt) += std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,y), yd) * std::pow(points(cell,pt,z), zd);
117  }
118  }
119 
120 }
121 
122 
124 void neumann(FieldContainer<double> & result,
125  const FieldContainer<double> & points,
126  const FieldContainer<double> & jacs,
127  const shards::CellTopology & parentCell,
128  int sideOrdinal, int xd, int yd, int zd) {
129 
130  int x = 0, y = 1, z = 2;
131 
132  int numCells = result.dimension(0);
133  int numPoints = result.dimension(1);
134 
135  FieldContainer<double> grad_u(numCells, numPoints, 3);
136  FieldContainer<double> side_normals(numCells, numPoints, 3);
137  FieldContainer<double> normal_lengths(numCells, numPoints);
138 
139  // first x-derivatives of u
140  if (xd > 0) {
141  for (int cell=0; cell<numCells; cell++) {
142  for (int pt=0; pt<numPoints; pt++) {
143  grad_u(cell,pt,x) = xd*std::pow(points(cell,pt,x), xd-1) *
144  std::pow(points(cell,pt,y), yd) * std::pow(points(cell,pt,z), zd);
145  }
146  }
147  }
148 
149  // first y-derivatives of u
150  if (yd > 0) {
151  for (int cell=0; cell<numCells; cell++) {
152  for (int pt=0; pt<numPoints; pt++) {
153  grad_u(cell,pt,y) = yd*std::pow(points(cell,pt,y), yd-1) *
154  std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,z), zd);
155  }
156  }
157  }
158 
159  // first z-derivatives of u
160  if (zd > 0) {
161  for (int cell=0; cell<numCells; cell++) {
162  for (int pt=0; pt<numPoints; pt++) {
163  grad_u(cell,pt,z) = zd*std::pow(points(cell,pt,z), zd-1) *
164  std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,y), yd);
165  }
166  }
167  }
168 
169  CellTools<double>::getPhysicalSideNormals(side_normals, jacs, sideOrdinal, parentCell);
170 
171  // scale normals
172  RealSpaceTools<double>::vectorNorm(normal_lengths, side_normals, NORM_TWO);
173  FunctionSpaceTools::scalarMultiplyDataData<double>(side_normals, normal_lengths, side_normals, true);
174 
175  FunctionSpaceTools::dotMultiplyDataData<double>(result, grad_u, side_normals);
176 
177 }
178 
180 void u_exact(FieldContainer<double> & result, const FieldContainer<double> & points, int xd, int yd, int zd) {
181  int x = 0, y = 1, z = 2;
182  for (int cell=0; cell<result.dimension(0); cell++) {
183  for (int pt=0; pt<result.dimension(1); pt++) {
184  result(cell,pt) = std::pow(points(pt,x), xd)*std::pow(points(pt,y), yd)*std::pow(points(pt,z), zd);
185  }
186  }
187 }
188 
189 
190 
191 
192 int main(int argc, char *argv[]) {
193 
194  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
195 
196  // This little trick lets us print to std::cout only if
197  // a (dummy) command-line argument is provided.
198  int iprint = argc - 1;
199  Teuchos::RCP<std::ostream> outStream;
200  Teuchos::oblackholestream bhs; // outputs nothing
201  if (iprint > 0)
202  outStream = Teuchos::rcp(&std::cout, false);
203  else
204  outStream = Teuchos::rcp(&bhs, false);
205 
206  // Save the format state of the original std::cout.
207  Teuchos::oblackholestream oldFormatState;
208  oldFormatState.copyfmt(std::cout);
209 
210  *outStream \
211  << "===============================================================================\n" \
212  << "| |\n" \
213  << "| Unit Test (Basis_HGRAD_TET_Cn_FEM) |\n" \
214  << "| |\n" \
215  << "| 1) Patch test involving mass and stiffness matrices, |\n" \
216  << "| for the Neumann problem on a tetrahedral patch |\n" \
217  << "| Omega with boundary Gamma. |\n" \
218  << "| |\n" \
219  << "| - div (grad u) + u = f in Omega, (grad u) . n = g on Gamma |\n" \
220  << "| |\n" \
221  << "| Questions? Contact Pavel Bochev (pbboche@sandia.gov), |\n" \
222  << "| Denis Ridzal (dridzal@sandia.gov), |\n" \
223  << "| Kara Peterson (kjpeter@sandia.gov). |\n" \
224  << "| |\n" \
225  << "| Intrepid's website: http://trilinos.sandia.gov/packages/intrepid |\n" \
226  << "| Trilinos website: http://trilinos.sandia.gov |\n" \
227  << "| |\n" \
228  << "===============================================================================\n"\
229  << "| TEST 1: Patch test |\n"\
230  << "===============================================================================\n";
231 
232 
233  int errorFlag = 0;
234 
235  outStream -> precision(16);
236 
237 
238  try {
239 
240  int max_order = 5; // max total order of polynomial solution
241  DefaultCubatureFactory<double> cubFactory; // create factory
242  shards::CellTopology cell(shards::getCellTopologyData< shards::Tetrahedron<> >()); // create parent cell topology
243  shards::CellTopology side(shards::getCellTopologyData< shards::Triangle<> >()); // create relevant subcell (side) topology
244  int cellDim = cell.getDimension();
245  int sideDim = side.getDimension();
246 
247  // Define array containing points at which the solution is evaluated, on the reference tet.
248  int numIntervals = 10;
249  int numInterpPoints = ((numIntervals + 1)*(numIntervals + 2)*(numIntervals + 3))/6;
250  FieldContainer<double> interp_points_ref(numInterpPoints, 3);
251  int counter = 0;
252  for (int k=0; k<=numIntervals; k++) {
253  for (int j=0; j<=numIntervals; j++) {
254  for (int i=0; i<=numIntervals; i++) {
255  if (i+j+k <= numIntervals) {
256  interp_points_ref(counter,0) = i*(1.0/numIntervals);
257  interp_points_ref(counter,1) = j*(1.0/numIntervals);
258  interp_points_ref(counter,2) = k*(1.0/numIntervals);
259  counter++;
260  }
261  }
262  }
263  }
264 
265  /* Definition of parent cell. */
266  FieldContainer<double> cell_nodes(1, 4, cellDim);
267  // funky tet
268  cell_nodes(0, 0, 0) = -1.0;
269  cell_nodes(0, 0, 1) = -2.0;
270  cell_nodes(0, 0, 2) = 0.0;
271  cell_nodes(0, 1, 0) = 6.0;
272  cell_nodes(0, 1, 1) = 2.0;
273  cell_nodes(0, 1, 2) = 0.0;
274  cell_nodes(0, 2, 0) = -5.0;
275  cell_nodes(0, 2, 1) = 1.0;
276  cell_nodes(0, 2, 2) = 0.0;
277  cell_nodes(0, 3, 0) = -4.0;
278  cell_nodes(0, 3, 1) = -1.0;
279  cell_nodes(0, 3, 2) = 3.0;
280  // perturbed reference tet
281  /*cell_nodes(0, 0, 0) = 0.1;
282  cell_nodes(0, 0, 1) = -0.1;
283  cell_nodes(0, 0, 2) = 0.2;
284  cell_nodes(0, 1, 0) = 1.2;
285  cell_nodes(0, 1, 1) = -0.1;
286  cell_nodes(0, 1, 2) = 0.05;
287  cell_nodes(0, 2, 0) = 0.0;
288  cell_nodes(0, 2, 1) = 0.9;
289  cell_nodes(0, 2, 2) = 0.1;
290  cell_nodes(0, 3, 0) = 0.1;
291  cell_nodes(0, 3, 1) = -0.1;
292  cell_nodes(0, 3, 2) = 1.1;*/
293  // reference tet
294  /*cell_nodes(0, 0, 0) = 0.0;
295  cell_nodes(0, 0, 1) = 0.0;
296  cell_nodes(0, 0, 2) = 0.0;
297  cell_nodes(0, 1, 0) = 1.0;
298  cell_nodes(0, 1, 1) = 0.0;
299  cell_nodes(0, 1, 2) = 0.0;
300  cell_nodes(0, 2, 0) = 0.0;
301  cell_nodes(0, 2, 1) = 1.0;
302  cell_nodes(0, 2, 2) = 0.0;
303  cell_nodes(0, 3, 0) = 0.0;
304  cell_nodes(0, 3, 1) = 0.0;
305  cell_nodes(0, 3, 2) = 1.0;*/
306 
307  FieldContainer<double> interp_points(1, numInterpPoints, cellDim);
308  CellTools<double>::mapToPhysicalFrame(interp_points, interp_points_ref, cell_nodes, cell);
309  interp_points.resize(numInterpPoints, cellDim);
310 
311  // we test two types of bases
312  EPointType pointtype[] = {POINTTYPE_EQUISPACED, POINTTYPE_WARPBLEND};
313  for (int ptype=0; ptype < 2; ptype++) {
314 
315  *outStream << "\nTesting bases with " << EPointTypeToString(pointtype[ptype]) << ":\n";
316 
317  for (int x_order=0; x_order <= max_order; x_order++) {
318  for (int y_order=0; y_order <= max_order-x_order; y_order++) {
319  for (int z_order=0; z_order <= max_order-x_order-y_order; z_order++) {
320 
321  // evaluate exact solution
322  FieldContainer<double> exact_solution(1, numInterpPoints);
323  u_exact(exact_solution, interp_points, x_order, y_order, z_order);
324 
325  int total_order = std::max(x_order + y_order + z_order, 1);
326 
327  for (int basis_order=total_order; basis_order <= max_order; basis_order++) {
328 
329  // set test tolerance;
330  double zero = basis_order*basis_order*basis_order*100*INTREPID_TOL;
331 
332  //create basis
333  Teuchos::RCP<Basis<double,FieldContainer<double> > > basis =
334  Teuchos::rcp(new Basis_HGRAD_TET_Cn_FEM<double,FieldContainer<double> >(basis_order, pointtype[ptype]) );
335  int numFields = basis->getCardinality();
336 
337  // create cubatures
338  Teuchos::RCP<Cubature<double> > cellCub = cubFactory.create(cell, 2*basis_order);
339  Teuchos::RCP<Cubature<double> > sideCub = cubFactory.create(side, 2*basis_order);
340  int numCubPointsCell = cellCub->getNumPoints();
341  int numCubPointsSide = sideCub->getNumPoints();
342 
343  /* Computational arrays. */
344  /* Section 1: Related to parent cell integration. */
345  FieldContainer<double> cub_points_cell(numCubPointsCell, cellDim);
346  FieldContainer<double> cub_points_cell_physical(1, numCubPointsCell, cellDim);
347  FieldContainer<double> cub_weights_cell(numCubPointsCell);
348  FieldContainer<double> jacobian_cell(1, numCubPointsCell, cellDim, cellDim);
349  FieldContainer<double> jacobian_inv_cell(1, numCubPointsCell, cellDim, cellDim);
350  FieldContainer<double> jacobian_det_cell(1, numCubPointsCell);
351  FieldContainer<double> weighted_measure_cell(1, numCubPointsCell);
352 
353  FieldContainer<double> value_of_basis_at_cub_points_cell(numFields, numCubPointsCell);
354  FieldContainer<double> transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
355  FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
356  FieldContainer<double> grad_of_basis_at_cub_points_cell(numFields, numCubPointsCell, cellDim);
357  FieldContainer<double> transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
358  FieldContainer<double> weighted_transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
359  FieldContainer<double> fe_matrix(1, numFields, numFields);
360 
361  FieldContainer<double> rhs_at_cub_points_cell_physical(1, numCubPointsCell);
362  FieldContainer<double> rhs_and_soln_vector(1, numFields);
363 
364  /* Section 2: Related to subcell (side) integration. */
365  unsigned numSides = 4;
366  FieldContainer<double> cub_points_side(numCubPointsSide, sideDim);
367  FieldContainer<double> cub_weights_side(numCubPointsSide);
368  FieldContainer<double> cub_points_side_refcell(numCubPointsSide, cellDim);
369  FieldContainer<double> cub_points_side_physical(1, numCubPointsSide, cellDim);
370  FieldContainer<double> jacobian_side_refcell(1, numCubPointsSide, cellDim, cellDim);
371  FieldContainer<double> jacobian_det_side_refcell(1, numCubPointsSide);
372  FieldContainer<double> weighted_measure_side_refcell(1, numCubPointsSide);
373 
374  FieldContainer<double> value_of_basis_at_cub_points_side_refcell(numFields, numCubPointsSide);
375  FieldContainer<double> transformed_value_of_basis_at_cub_points_side_refcell(1, numFields, numCubPointsSide);
376  FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_side_refcell(1, numFields, numCubPointsSide);
377  FieldContainer<double> neumann_data_at_cub_points_side_physical(1, numCubPointsSide);
378  FieldContainer<double> neumann_fields_per_side(1, numFields);
379 
380  /* Section 3: Related to global interpolant. */
381  FieldContainer<double> value_of_basis_at_interp_points_ref(numFields, numInterpPoints);
382  FieldContainer<double> transformed_value_of_basis_at_interp_points_ref(1, numFields, numInterpPoints);
383  FieldContainer<double> interpolant(1, numInterpPoints);
384 
385  FieldContainer<int> ipiv(numFields);
386 
387 
388 
389  /******************* START COMPUTATION ***********************/
390 
391  // get cubature points and weights
392  cellCub->getCubature(cub_points_cell, cub_weights_cell);
393 
394  // compute geometric cell information
395  CellTools<double>::setJacobian(jacobian_cell, cub_points_cell, cell_nodes, cell);
396  CellTools<double>::setJacobianInv(jacobian_inv_cell, jacobian_cell);
397  CellTools<double>::setJacobianDet(jacobian_det_cell, jacobian_cell);
398 
399  // compute weighted measure
400  FunctionSpaceTools::computeCellMeasure<double>(weighted_measure_cell, jacobian_det_cell, cub_weights_cell);
401 
403  // Computing mass matrices:
404  // tabulate values of basis functions at (reference) cubature points
405  basis->getValues(value_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_VALUE);
406 
407  // transform values of basis functions
408  FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_cell,
409  value_of_basis_at_cub_points_cell);
410 
411  // multiply with weighted measure
412  FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_cell,
413  weighted_measure_cell,
414  transformed_value_of_basis_at_cub_points_cell);
415 
416  // compute mass matrices
417  FunctionSpaceTools::integrate<double>(fe_matrix,
418  transformed_value_of_basis_at_cub_points_cell,
419  weighted_transformed_value_of_basis_at_cub_points_cell,
420  COMP_BLAS);
422 
424  // Computing stiffness matrices:
425  // tabulate gradients of basis functions at (reference) cubature points
426  basis->getValues(grad_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_GRAD);
427 
428  // transform gradients of basis functions
429  FunctionSpaceTools::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points_cell,
430  jacobian_inv_cell,
431  grad_of_basis_at_cub_points_cell);
432 
433  // multiply with weighted measure
434  FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_grad_of_basis_at_cub_points_cell,
435  weighted_measure_cell,
436  transformed_grad_of_basis_at_cub_points_cell);
437 
438  // compute stiffness matrices and sum into fe_matrix
439  FunctionSpaceTools::integrate<double>(fe_matrix,
440  transformed_grad_of_basis_at_cub_points_cell,
441  weighted_transformed_grad_of_basis_at_cub_points_cell,
442  COMP_BLAS,
443  true);
445 
447  // Computing RHS contributions:
448  // map cell (reference) cubature points to physical space
449  CellTools<double>::mapToPhysicalFrame(cub_points_cell_physical, cub_points_cell, cell_nodes, cell);
450 
451  // evaluate rhs function
452  rhsFunc(rhs_at_cub_points_cell_physical, cub_points_cell_physical, x_order, y_order, z_order);
453 
454  // compute rhs
455  FunctionSpaceTools::integrate<double>(rhs_and_soln_vector,
456  rhs_at_cub_points_cell_physical,
457  weighted_transformed_value_of_basis_at_cub_points_cell,
458  COMP_BLAS);
459 
460  // compute neumann b.c. contributions and adjust rhs
461  sideCub->getCubature(cub_points_side, cub_weights_side);
462  for (unsigned i=0; i<numSides; i++) {
463  // compute geometric cell information
464  CellTools<double>::mapToReferenceSubcell(cub_points_side_refcell, cub_points_side, sideDim, (int)i, cell);
465  CellTools<double>::setJacobian(jacobian_side_refcell, cub_points_side_refcell, cell_nodes, cell);
466  CellTools<double>::setJacobianDet(jacobian_det_side_refcell, jacobian_side_refcell);
467 
468  // compute weighted face measure
469  FunctionSpaceTools::computeFaceMeasure<double>(weighted_measure_side_refcell,
470  jacobian_side_refcell,
471  cub_weights_side,
472  i,
473  cell);
474 
475  // tabulate values of basis functions at side cubature points, in the reference parent cell domain
476  basis->getValues(value_of_basis_at_cub_points_side_refcell, cub_points_side_refcell, OPERATOR_VALUE);
477  // transform
478  FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_side_refcell,
479  value_of_basis_at_cub_points_side_refcell);
480 
481  // multiply with weighted measure
482  FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_side_refcell,
483  weighted_measure_side_refcell,
484  transformed_value_of_basis_at_cub_points_side_refcell);
485 
486  // compute Neumann data
487  // map side cubature points in reference parent cell domain to physical space
488  CellTools<double>::mapToPhysicalFrame(cub_points_side_physical, cub_points_side_refcell, cell_nodes, cell);
489  // now compute data
490  neumann(neumann_data_at_cub_points_side_physical, cub_points_side_physical, jacobian_side_refcell,
491  cell, (int)i, x_order, y_order, z_order);
492 
493  FunctionSpaceTools::integrate<double>(neumann_fields_per_side,
494  neumann_data_at_cub_points_side_physical,
495  weighted_transformed_value_of_basis_at_cub_points_side_refcell,
496  COMP_BLAS);
497 
498  // adjust RHS
499  RealSpaceTools<double>::add(rhs_and_soln_vector, neumann_fields_per_side);;
500  }
502 
504  // Solution of linear system:
505  int info = 0;
506  Teuchos::LAPACK<int, double> solver;
507  solver.GESV(numFields, 1, &fe_matrix[0], numFields, &ipiv(0), &rhs_and_soln_vector[0], numFields, &info);
509 
511  // Building interpolant:
512  // evaluate basis at interpolation points
513  basis->getValues(value_of_basis_at_interp_points_ref, interp_points_ref, OPERATOR_VALUE);
514  // transform values of basis functions
515  FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_interp_points_ref,
516  value_of_basis_at_interp_points_ref);
517  FunctionSpaceTools::evaluate<double>(interpolant, rhs_and_soln_vector, transformed_value_of_basis_at_interp_points_ref);
519 
520  /******************* END COMPUTATION ***********************/
521 
522  RealSpaceTools<double>::subtract(interpolant, exact_solution);
523 
524  *outStream << "\nRelative norm-2 error between exact solution polynomial of order ("
525  << x_order << ", " << y_order << ", " << z_order
526  << ") and finite element interpolant of order " << basis_order << ": "
527  << RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
528  RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) << "\n";
529 
530  if (RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
531  RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) > zero) {
532  *outStream << "\n\nPatch test failed for solution polynomial order ("
533  << x_order << ", " << y_order << ", " << z_order << ") and basis order " << basis_order << "\n\n";
534  errorFlag++;
535  }
536  } // end for basis_order
537  } // end for z_order
538  } // end for y_order
539  } // end for x_order
540  } // end for ptype
541 
542  }
543  // Catch unexpected errors
544  catch (const std::logic_error & err) {
545  *outStream << err.what() << "\n\n";
546  errorFlag = -1000;
547  };
548 
549  if (errorFlag != 0)
550  std::cout << "End Result: TEST FAILED\n";
551  else
552  std::cout << "End Result: TEST PASSED\n";
553 
554  // reset format state of std::cout
555  std::cout.copyfmt(oldFormatState);
556 
557  return errorFlag;
558 }
Implementation of basic linear algebra functionality in Euclidean space.
Header file for the Intrepid::CellTools class.
Implementation of the default H(grad)-compatible Lagrange basis of arbitrary degree on Tetrahedron ce...
int dimension(const int whichDim) const
Returns the specified dimension.
Header file for utility class to provide multidimensional containers.
Header file for utility class to provide array tools, such as tensor contractions, etc.
Header file for the abstract base class Intrepid::DefaultCubatureFactory.
Header file for the Intrepid::FunctionSpaceTools class.
Header file for classes providing basic linear algebra functionality in 1D, 2D and 3D...
A factory class that generates specific instances of cubatures.
Teuchos::RCP< Cubature< Scalar, ArrayPoint, ArrayWeight > > create(const shards::CellTopology &cellTopology, const std::vector< int > &degree)
Factory method.
Header file for the Intrepid::HGRAD_TET_Cn_FEM class.
A stateless class for operations on cell data. Provides methods for: