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 
50 #include "Intrepid_HGRAD_HEX_C1_FEM.hpp"
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_HEX_C1_FEM) |\n" \
214  << "| |\n" \
215  << "| 1) Patch test involving mass and stiffness matrices, |\n" \
216  << "| for the Neumann problem on a physical parallelepiped |\n" \
217  << "| AND a reference hex 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  << "| For a generic parallelepiped, the basis recovers a complete |\n" \
222  << "| polynomial space of order 1. On a (scaled and/or translated) |\n" \
223  << "| reference hex, the basis recovers a complete tensor product |\n" \
224  << "| space of order 1 (i.e. incl. xy, xz, yz, xyz term). |\n" \
225  << "| |\n" \
226  << "| Questions? Contact Pavel Bochev (pbboche@sandia.gov), |\n" \
227  << "| Denis Ridzal (dridzal@sandia.gov), |\n" \
228  << "| Kara Peterson (kjpeter@sandia.gov). |\n" \
229  << "| |\n" \
230  << "| Intrepid's website: http://trilinos.sandia.gov/packages/intrepid |\n" \
231  << "| Trilinos website: http://trilinos.sandia.gov |\n" \
232  << "| |\n" \
233  << "===============================================================================\n"\
234  << "| TEST 1: Patch test |\n"\
235  << "===============================================================================\n";
236 
237 
238  int errorFlag = 0;
239 
240  outStream -> precision(16);
241 
242 
243  try {
244 
245  int max_order = 1; // max total order of polynomial solution
246  DefaultCubatureFactory<double> cubFactory; // create factory
247  shards::CellTopology cell(shards::getCellTopologyData< shards::Hexahedron<> >()); // create parent cell topology
248  shards::CellTopology side(shards::getCellTopologyData< shards::Quadrilateral<> >()); // create relevant subcell (side) topology
249  int cellDim = cell.getDimension();
250  int sideDim = side.getDimension();
251  unsigned numSides = 6;
252 
253  // Define array containing points at which the solution is evaluated, on the reference tet.
254  int numIntervals = 10;
255  int numInterpPoints = (numIntervals + 1)*(numIntervals + 1)*(numIntervals + 1);
256  FieldContainer<double> interp_points_ref(numInterpPoints, 3);
257  int counter = 0;
258  for (int k=0; k<=numIntervals; k++) {
259  for (int j=0; j<=numIntervals; j++) {
260  for (int i=0; i<=numIntervals; i++) {
261  interp_points_ref(counter,0) = i*(1.0/numIntervals)-1.0;
262  interp_points_ref(counter,1) = j*(1.0/numIntervals)-1.0;
263  interp_points_ref(counter,2) = k*(1.0/numIntervals)-1.0;
264  counter++;
265  }
266  }
267  }
268 
269  /* Parent cell definition. */
270  FieldContainer<double> cell_nodes[2];
271  cell_nodes[0].resize(1, 8, cellDim);
272  cell_nodes[1].resize(1, 8, cellDim);
273 
274  // Generic parallelepiped.
275  cell_nodes[0](0, 0, 0) = -5.0;
276  cell_nodes[0](0, 0, 1) = -1.0;
277  cell_nodes[0](0, 0, 2) = 0.0;
278  cell_nodes[0](0, 1, 0) = 4.0;
279  cell_nodes[0](0, 1, 1) = 1.0;
280  cell_nodes[0](0, 1, 2) = 1.0;
281  cell_nodes[0](0, 2, 0) = 8.0;
282  cell_nodes[0](0, 2, 1) = 3.0;
283  cell_nodes[0](0, 2, 2) = 1.0;
284  cell_nodes[0](0, 3, 0) = -1.0;
285  cell_nodes[0](0, 3, 1) = 1.0;
286  cell_nodes[0](0, 3, 2) = 0.0;
287  cell_nodes[0](0, 4, 0) = 5.0;
288  cell_nodes[0](0, 4, 1) = 9.0;
289  cell_nodes[0](0, 4, 2) = 1.0;
290  cell_nodes[0](0, 5, 0) = 14.0;
291  cell_nodes[0](0, 5, 1) = 11.0;
292  cell_nodes[0](0, 5, 2) = 2.0;
293  cell_nodes[0](0, 6, 0) = 18.0;
294  cell_nodes[0](0, 6, 1) = 13.0;
295  cell_nodes[0](0, 6, 2) = 2.0;
296  cell_nodes[0](0, 7, 0) = 9.0;
297  cell_nodes[0](0, 7, 1) = 11.0;
298  cell_nodes[0](0, 7, 2) = 1.0;
299  // Reference hex.
300  cell_nodes[1](0, 0, 0) = -1.0;
301  cell_nodes[1](0, 0, 1) = -1.0;
302  cell_nodes[1](0, 0, 2) = -1.0;
303  cell_nodes[1](0, 1, 0) = 1.0;
304  cell_nodes[1](0, 1, 1) = -1.0;
305  cell_nodes[1](0, 1, 2) = -1.0;
306  cell_nodes[1](0, 2, 0) = 1.0;
307  cell_nodes[1](0, 2, 1) = 1.0;
308  cell_nodes[1](0, 2, 2) = -1.0;
309  cell_nodes[1](0, 3, 0) = -1.0;
310  cell_nodes[1](0, 3, 1) = 1.0;
311  cell_nodes[1](0, 3, 2) = -1.0;
312  cell_nodes[1](0, 4, 0) = -1.0;
313  cell_nodes[1](0, 4, 1) = -1.0;
314  cell_nodes[1](0, 4, 2) = 1.0;
315  cell_nodes[1](0, 5, 0) = 1.0;
316  cell_nodes[1](0, 5, 1) = -1.0;
317  cell_nodes[1](0, 5, 2) = 1.0;
318  cell_nodes[1](0, 6, 0) = 1.0;
319  cell_nodes[1](0, 6, 1) = 1.0;
320  cell_nodes[1](0, 6, 2) = 1.0;
321  cell_nodes[1](0, 7, 0) = -1.0;
322  cell_nodes[1](0, 7, 1) = 1.0;
323  cell_nodes[1](0, 7, 2) = 1.0;
324 
325  std::stringstream mystream[2];
326  mystream[0].str("\n>> Now testing basis on a generic parallelepiped ...\n");
327  mystream[1].str("\n>> Now testing basis on the reference hex ...\n");
328 
329 
330  for (int pcell = 0; pcell < 2; pcell++) {
331  *outStream << mystream[pcell].str();
332  FieldContainer<double> interp_points(1, numInterpPoints, cellDim);
333  CellTools<double>::mapToPhysicalFrame(interp_points, interp_points_ref, cell_nodes[pcell], cell);
334  interp_points.resize(numInterpPoints, cellDim);
335 
336  for (int x_order=0; x_order <= max_order; x_order++) {
337  int max_y_order = max_order;
338  if (pcell == 0) {
339  max_y_order -= x_order;
340  }
341  for (int y_order=0; y_order <= max_y_order; y_order++) {
342  int max_z_order = max_order;
343  if (pcell == 0) {
344  max_z_order -= x_order;
345  max_z_order -= y_order;
346  }
347  for (int z_order=0; z_order <= max_z_order; z_order++) {
348 
349  // evaluate exact solution
350  FieldContainer<double> exact_solution(1, numInterpPoints);
351  u_exact(exact_solution, interp_points, x_order, y_order, z_order);
352 
353  int basis_order = 1;
354 
355  // set test tolerance;
356  double zero = basis_order*basis_order*basis_order*100*INTREPID_TOL;
357 
358  //create basis
359  Teuchos::RCP<Basis<double,FieldContainer<double> > > basis =
360  Teuchos::rcp(new Basis_HGRAD_HEX_C1_FEM<double,FieldContainer<double> >() );
361  int numFields = basis->getCardinality();
362 
363  // create cubatures
364  Teuchos::RCP<Cubature<double> > cellCub = cubFactory.create(cell, 2*basis_order);
365  Teuchos::RCP<Cubature<double> > sideCub = cubFactory.create(side, 2*basis_order);
366  int numCubPointsCell = cellCub->getNumPoints();
367  int numCubPointsSide = sideCub->getNumPoints();
368 
369  /* Computational arrays. */
370  /* Section 1: Related to parent cell integration. */
371  FieldContainer<double> cub_points_cell(numCubPointsCell, cellDim);
372  FieldContainer<double> cub_points_cell_physical(1, numCubPointsCell, cellDim);
373  FieldContainer<double> cub_weights_cell(numCubPointsCell);
374  FieldContainer<double> jacobian_cell(1, numCubPointsCell, cellDim, cellDim);
375  FieldContainer<double> jacobian_inv_cell(1, numCubPointsCell, cellDim, cellDim);
376  FieldContainer<double> jacobian_det_cell(1, numCubPointsCell);
377  FieldContainer<double> weighted_measure_cell(1, numCubPointsCell);
378 
379  FieldContainer<double> value_of_basis_at_cub_points_cell(numFields, numCubPointsCell);
380  FieldContainer<double> transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
381  FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
382  FieldContainer<double> grad_of_basis_at_cub_points_cell(numFields, numCubPointsCell, cellDim);
383  FieldContainer<double> transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
384  FieldContainer<double> weighted_transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
385  FieldContainer<double> fe_matrix(1, numFields, numFields);
386 
387  FieldContainer<double> rhs_at_cub_points_cell_physical(1, numCubPointsCell);
388  FieldContainer<double> rhs_and_soln_vector(1, numFields);
389 
390  /* Section 2: Related to subcell (side) integration. */
391  FieldContainer<double> cub_points_side(numCubPointsSide, sideDim);
392  FieldContainer<double> cub_weights_side(numCubPointsSide);
393  FieldContainer<double> cub_points_side_refcell(numCubPointsSide, cellDim);
394  FieldContainer<double> cub_points_side_physical(1, numCubPointsSide, cellDim);
395  FieldContainer<double> jacobian_side_refcell(1, numCubPointsSide, cellDim, cellDim);
396  FieldContainer<double> jacobian_det_side_refcell(1, numCubPointsSide);
397  FieldContainer<double> weighted_measure_side_refcell(1, numCubPointsSide);
398 
399  FieldContainer<double> value_of_basis_at_cub_points_side_refcell(numFields, numCubPointsSide);
400  FieldContainer<double> transformed_value_of_basis_at_cub_points_side_refcell(1, numFields, numCubPointsSide);
401  FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_side_refcell(1, numFields, numCubPointsSide);
402  FieldContainer<double> neumann_data_at_cub_points_side_physical(1, numCubPointsSide);
403  FieldContainer<double> neumann_fields_per_side(1, numFields);
404 
405  /* Section 3: Related to global interpolant. */
406  FieldContainer<double> value_of_basis_at_interp_points_ref(numFields, numInterpPoints);
407  FieldContainer<double> transformed_value_of_basis_at_interp_points_ref(1, numFields, numInterpPoints);
408  FieldContainer<double> interpolant(1, numInterpPoints);
409 
410  FieldContainer<int> ipiv(numFields);
411 
412 
413 
414  /******************* START COMPUTATION ***********************/
415 
416  // get cubature points and weights
417  cellCub->getCubature(cub_points_cell, cub_weights_cell);
418 
419  // compute geometric cell information
420  CellTools<double>::setJacobian(jacobian_cell, cub_points_cell, cell_nodes[pcell], cell);
421  CellTools<double>::setJacobianInv(jacobian_inv_cell, jacobian_cell);
422  CellTools<double>::setJacobianDet(jacobian_det_cell, jacobian_cell);
423 
424  // compute weighted measure
425  FunctionSpaceTools::computeCellMeasure<double>(weighted_measure_cell, jacobian_det_cell, cub_weights_cell);
426 
428  // Computing mass matrices:
429  // tabulate values of basis functions at (reference) cubature points
430  basis->getValues(value_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_VALUE);
431 
432  // transform values of basis functions
433  FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_cell,
434  value_of_basis_at_cub_points_cell);
435 
436  // multiply with weighted measure
437  FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_cell,
438  weighted_measure_cell,
439  transformed_value_of_basis_at_cub_points_cell);
440 
441  // compute mass matrices
442  FunctionSpaceTools::integrate<double>(fe_matrix,
443  transformed_value_of_basis_at_cub_points_cell,
444  weighted_transformed_value_of_basis_at_cub_points_cell,
445  COMP_BLAS);
447 
449  // Computing stiffness matrices:
450  // tabulate gradients of basis functions at (reference) cubature points
451  basis->getValues(grad_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_GRAD);
452 
453  // transform gradients of basis functions
454  FunctionSpaceTools::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points_cell,
455  jacobian_inv_cell,
456  grad_of_basis_at_cub_points_cell);
457 
458  // multiply with weighted measure
459  FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_grad_of_basis_at_cub_points_cell,
460  weighted_measure_cell,
461  transformed_grad_of_basis_at_cub_points_cell);
462 
463  // compute stiffness matrices and sum into fe_matrix
464  FunctionSpaceTools::integrate<double>(fe_matrix,
465  transformed_grad_of_basis_at_cub_points_cell,
466  weighted_transformed_grad_of_basis_at_cub_points_cell,
467  COMP_BLAS,
468  true);
470 
472  // Computing RHS contributions:
473  // map cell (reference) cubature points to physical space
474  CellTools<double>::mapToPhysicalFrame(cub_points_cell_physical, cub_points_cell, cell_nodes[pcell], cell);
475 
476  // evaluate rhs function
477  rhsFunc(rhs_at_cub_points_cell_physical, cub_points_cell_physical, x_order, y_order, z_order);
478 
479  // compute rhs
480  FunctionSpaceTools::integrate<double>(rhs_and_soln_vector,
481  rhs_at_cub_points_cell_physical,
482  weighted_transformed_value_of_basis_at_cub_points_cell,
483  COMP_BLAS);
484 
485  // compute neumann b.c. contributions and adjust rhs
486  sideCub->getCubature(cub_points_side, cub_weights_side);
487  for (unsigned i=0; i<numSides; i++) {
488  // compute geometric cell information
489  CellTools<double>::mapToReferenceSubcell(cub_points_side_refcell, cub_points_side, sideDim, (int)i, cell);
490  CellTools<double>::setJacobian(jacobian_side_refcell, cub_points_side_refcell, cell_nodes[pcell], cell);
491  CellTools<double>::setJacobianDet(jacobian_det_side_refcell, jacobian_side_refcell);
492 
493  // compute weighted face measure
494  FunctionSpaceTools::computeFaceMeasure<double>(weighted_measure_side_refcell,
495  jacobian_side_refcell,
496  cub_weights_side,
497  i,
498  cell);
499 
500  // tabulate values of basis functions at side cubature points, in the reference parent cell domain
501  basis->getValues(value_of_basis_at_cub_points_side_refcell, cub_points_side_refcell, OPERATOR_VALUE);
502  // transform
503  FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_side_refcell,
504  value_of_basis_at_cub_points_side_refcell);
505 
506  // multiply with weighted measure
507  FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_side_refcell,
508  weighted_measure_side_refcell,
509  transformed_value_of_basis_at_cub_points_side_refcell);
510 
511  // compute Neumann data
512  // map side cubature points in reference parent cell domain to physical space
513  CellTools<double>::mapToPhysicalFrame(cub_points_side_physical, cub_points_side_refcell, cell_nodes[pcell], cell);
514  // now compute data
515  neumann(neumann_data_at_cub_points_side_physical, cub_points_side_physical, jacobian_side_refcell,
516  cell, (int)i, x_order, y_order, z_order);
517 
518  FunctionSpaceTools::integrate<double>(neumann_fields_per_side,
519  neumann_data_at_cub_points_side_physical,
520  weighted_transformed_value_of_basis_at_cub_points_side_refcell,
521  COMP_BLAS);
522 
523  // adjust RHS
524  RealSpaceTools<double>::add(rhs_and_soln_vector, neumann_fields_per_side);;
525  }
527 
529  // Solution of linear system:
530  int info = 0;
531  Teuchos::LAPACK<int, double> solver;
532  solver.GESV(numFields, 1, &fe_matrix[0], numFields, &ipiv(0), &rhs_and_soln_vector[0], numFields, &info);
534 
536  // Building interpolant:
537  // evaluate basis at interpolation points
538  basis->getValues(value_of_basis_at_interp_points_ref, interp_points_ref, OPERATOR_VALUE);
539  // transform values of basis functions
540  FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_interp_points_ref,
541  value_of_basis_at_interp_points_ref);
542  FunctionSpaceTools::evaluate<double>(interpolant, rhs_and_soln_vector, transformed_value_of_basis_at_interp_points_ref);
544 
545  /******************* END COMPUTATION ***********************/
546 
547  RealSpaceTools<double>::subtract(interpolant, exact_solution);
548 
549  *outStream << "\nRelative norm-2 error between exact solution polynomial of order ("
550  << x_order << ", " << y_order << ", " << z_order
551  << ") and finite element interpolant of order " << basis_order << ": "
552  << RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
553  RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) << "\n";
554 
555  if (RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
556  RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) > zero) {
557  *outStream << "\n\nPatch test failed for solution polynomial order ("
558  << x_order << ", " << y_order << ", " << z_order << ") and basis order " << basis_order << "\n\n";
559  errorFlag++;
560  }
561  } // end for z_order
562  } // end for y_order
563  } // end for x_order
564  } // end for pcell
565 
566  }
567  // Catch unexpected errors
568  catch (const std::logic_error & err) {
569  *outStream << err.what() << "\n\n";
570  errorFlag = -1000;
571  };
572 
573  if (errorFlag != 0)
574  std::cout << "End Result: TEST FAILED\n";
575  else
576  std::cout << "End Result: TEST PASSED\n";
577 
578  // reset format state of std::cout
579  std::cout.copyfmt(oldFormatState);
580 
581  return errorFlag;
582 }
Implementation of basic linear algebra functionality in Euclidean space.
Header file for the Intrepid::CellTools class.
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.
void resize(const int dim0)
Resizes FieldContainer to a rank-1 container with the specified dimension, initialized by 0...
Header file for the Intrepid::FunctionSpaceTools class.
Header file for classes providing basic linear algebra functionality in 1D, 2D and 3D...
Implementation of the default H(grad)-compatible FEM basis of degree 1 on Hexahedron cell...
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.
A stateless class for operations on cell data. Provides methods for: