Intrepid
/usr/src/RPM/BUILD/trilinos-11.12.1/packages/intrepid/test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/test_02.cpp
00001 // @HEADER
00002 // ************************************************************************
00003 //
00004 //                           Intrepid Package
00005 //                 Copyright (2007) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Pavel Bochev  (pbboche@sandia.gov)
00038 //                    Denis Ridzal  (dridzal@sandia.gov), or
00039 //                    Kara Peterson (kjpeter@sandia.gov)
00040 //
00041 // ************************************************************************
00042 // @HEADER
00043 
00049 #include "Intrepid_FieldContainer.hpp"
00050 #include "Intrepid_HGRAD_WEDGE_C1_FEM.hpp"
00051 #include "Intrepid_DefaultCubatureFactory.hpp"
00052 #include "Intrepid_RealSpaceTools.hpp"
00053 #include "Intrepid_ArrayTools.hpp"
00054 #include "Intrepid_FunctionSpaceTools.hpp"
00055 #include "Intrepid_CellTools.hpp"
00056 #include "Teuchos_oblackholestream.hpp"
00057 #include "Teuchos_RCP.hpp"
00058 #include "Teuchos_GlobalMPISession.hpp"
00059 #include "Teuchos_SerialDenseMatrix.hpp"
00060 #include "Teuchos_SerialDenseVector.hpp"
00061 #include "Teuchos_LAPACK.hpp"
00062 
00063 using namespace std;
00064 using namespace Intrepid;
00065 
00066 void rhsFunc(FieldContainer<double> &, const FieldContainer<double> &, int, int, int);
00067 void neumann(FieldContainer<double>       & ,
00068              const FieldContainer<double> & ,
00069              const FieldContainer<double> & ,
00070              const shards::CellTopology   & ,
00071              int, int, int, int);
00072 void u_exact(FieldContainer<double> &, const FieldContainer<double> &, int, int, int);
00073 
00075 void rhsFunc(FieldContainer<double> & result,
00076              const FieldContainer<double> & points,
00077              int xd,
00078              int yd,
00079              int zd) {
00080 
00081   int x = 0, y = 1, z = 2;
00082 
00083   // second x-derivatives of u
00084   if (xd > 1) {
00085     for (int cell=0; cell<result.dimension(0); cell++) {
00086       for (int pt=0; pt<result.dimension(1); pt++) {
00087         result(cell,pt) = - xd*(xd-1)*std::pow(points(cell,pt,x), xd-2) *
00088                             std::pow(points(cell,pt,y), yd) * std::pow(points(cell,pt,z), zd);
00089       }
00090     }
00091   }
00092 
00093   // second y-derivatives of u
00094   if (yd > 1) {
00095     for (int cell=0; cell<result.dimension(0); cell++) {
00096       for (int pt=0; pt<result.dimension(1); pt++) {
00097         result(cell,pt) -=  yd*(yd-1)*std::pow(points(cell,pt,y), yd-2) *
00098                             std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,z), zd);
00099       }
00100     }
00101   }
00102 
00103   // second z-derivatives of u
00104   if (zd > 1) {
00105     for (int cell=0; cell<result.dimension(0); cell++) {
00106       for (int pt=0; pt<result.dimension(1); pt++) {
00107         result(cell,pt) -=  zd*(zd-1)*std::pow(points(cell,pt,z), zd-2) *
00108                             std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,y), yd);
00109       }
00110     }
00111   }
00112 
00113   // add u
00114   for (int cell=0; cell<result.dimension(0); cell++) {
00115     for (int pt=0; pt<result.dimension(1); pt++) {
00116       result(cell,pt) +=  std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,y), yd) * std::pow(points(cell,pt,z), zd);
00117     }
00118   }
00119 
00120 }
00121 
00122 
00124 void neumann(FieldContainer<double>       & result,
00125              const FieldContainer<double> & points,
00126              const FieldContainer<double> & jacs,
00127              const shards::CellTopology   & parentCell,
00128              int sideOrdinal, int xd, int yd, int zd) {
00129 
00130   int x = 0, y = 1, z = 2;
00131 
00132   int numCells  = result.dimension(0);
00133   int numPoints = result.dimension(1);
00134 
00135   FieldContainer<double> grad_u(numCells, numPoints, 3);
00136   FieldContainer<double> side_normals(numCells, numPoints, 3);
00137   FieldContainer<double> normal_lengths(numCells, numPoints);
00138 
00139   // first x-derivatives of u
00140   if (xd > 0) {
00141     for (int cell=0; cell<numCells; cell++) {
00142       for (int pt=0; pt<numPoints; pt++) {
00143         grad_u(cell,pt,x) = xd*std::pow(points(cell,pt,x), xd-1) *
00144                             std::pow(points(cell,pt,y), yd) * std::pow(points(cell,pt,z), zd);
00145       }
00146     }
00147   }
00148 
00149   // first y-derivatives of u
00150   if (yd > 0) {
00151     for (int cell=0; cell<numCells; cell++) {
00152       for (int pt=0; pt<numPoints; pt++) {
00153         grad_u(cell,pt,y) = yd*std::pow(points(cell,pt,y), yd-1) *
00154                             std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,z), zd);
00155       }
00156     }
00157   }
00158 
00159   // first z-derivatives of u
00160   if (zd > 0) {
00161     for (int cell=0; cell<numCells; cell++) {
00162       for (int pt=0; pt<numPoints; pt++) {
00163         grad_u(cell,pt,z) = zd*std::pow(points(cell,pt,z), zd-1) *
00164                             std::pow(points(cell,pt,x), xd) * std::pow(points(cell,pt,y), yd);
00165       }
00166     }
00167   }
00168   
00169   CellTools<double>::getPhysicalSideNormals(side_normals, jacs, sideOrdinal, parentCell);
00170 
00171   // scale normals
00172   RealSpaceTools<double>::vectorNorm(normal_lengths, side_normals, NORM_TWO);
00173   FunctionSpaceTools::scalarMultiplyDataData<double>(side_normals, normal_lengths, side_normals, true); 
00174 
00175   FunctionSpaceTools::dotMultiplyDataData<double>(result, grad_u, side_normals);
00176 
00177 }
00178 
00180 void u_exact(FieldContainer<double> & result, const FieldContainer<double> & points, int xd, int yd, int zd) {
00181   int x = 0, y = 1, z = 2;
00182   for (int cell=0; cell<result.dimension(0); cell++) {
00183     for (int pt=0; pt<result.dimension(1); pt++) {
00184       result(cell,pt) = std::pow(points(pt,x), xd)*std::pow(points(pt,y), yd)*std::pow(points(pt,z), zd);
00185     }
00186   }
00187 }
00188 
00189 
00190 
00191 
00192 int main(int argc, char *argv[]) {
00193 
00194   Teuchos::GlobalMPISession mpiSession(&argc, &argv);
00195 
00196   // This little trick lets us print to std::cout only if
00197   // a (dummy) command-line argument is provided.
00198   int iprint     = argc - 1;
00199   Teuchos::RCP<std::ostream> outStream;
00200   Teuchos::oblackholestream bhs; // outputs nothing
00201   if (iprint > 0)
00202     outStream = Teuchos::rcp(&std::cout, false);
00203   else
00204     outStream = Teuchos::rcp(&bhs, false);
00205 
00206   // Save the format state of the original std::cout.
00207   Teuchos::oblackholestream oldFormatState;
00208   oldFormatState.copyfmt(std::cout);
00209 
00210   *outStream \
00211     << "===============================================================================\n" \
00212     << "|                                                                             |\n" \
00213     << "|                    Unit Test (Basis_HGRAD_WEDGE_C1_FEM)                     |\n" \
00214     << "|                                                                             |\n" \
00215     << "|     1) Patch test involving mass and stiffness matrices,                    |\n" \
00216     << "|        for the Neumann problem on a wedge patch                             |\n" \
00217     << "|        Omega with boundary Gamma.                                           |\n" \
00218     << "|                                                                             |\n" \
00219     << "|        - div (grad u) + u = f  in Omega,  (grad u) . n = g  on Gamma        |\n" \
00220     << "|                                                                             |\n" \
00221     << "|  Questions? Contact  Pavel Bochev  (pbboche@sandia.gov),                    |\n" \
00222     << "|                      Denis Ridzal  (dridzal@sandia.gov),                    |\n" \
00223     << "|                      Kara Peterson (kjpeter@sandia.gov).                    |\n" \
00224     << "|                      Mauro Perego  (mperego@sandia.gov).                    |\n" \
00225     << "|                                                                             |\n" \
00226     << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
00227     << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
00228     << "|                                                                             |\n" \
00229     << "===============================================================================\n"\
00230     << "| TEST 1: Patch test                                                          |\n"\
00231     << "===============================================================================\n";
00232 
00233   
00234   int errorFlag = 0;
00235 
00236   outStream -> precision(16);
00237 
00238 
00239   try {
00240 
00241     int max_order = 1;                                                                  // max total order of polynomial solution
00242     DefaultCubatureFactory<double>  cubFactory;                                         // create factory
00243     shards::CellTopology cell(shards::getCellTopologyData< shards::Wedge<> >());       // create parent cell topology
00244     shards::CellTopology sideQ(shards::getCellTopologyData< shards::Quadrilateral<> >());     // create relevant subcell (side) topology
00245     shards::CellTopology sideT(shards::getCellTopologyData< shards::Triangle<> >());
00246     int cellDim = cell.getDimension();
00247     int sideQDim = sideQ.getDimension();
00248     int sideTDim = sideT.getDimension();
00249 
00250     // Define array containing points at which the solution is evaluated, on the reference Wedge.
00251     int numIntervals = 10;
00252     int numInterpPoints = ((numIntervals + 1)*(numIntervals + 2)*(numIntervals + 3))/6;
00253     FieldContainer<double> interp_points_ref(numInterpPoints, 3);
00254     int counter = 0;
00255     for (int k=0; k<=numIntervals; k++) {
00256       for (int j=0; j<=numIntervals; j++) {
00257         for (int i=0; i<=numIntervals; i++) {
00258           if (i+j+k <= numIntervals) {
00259             interp_points_ref(counter,0) = i*(1.0/numIntervals);
00260             interp_points_ref(counter,1) = j*(1.0/numIntervals);
00261             interp_points_ref(counter,2) = k*(1.0/numIntervals);
00262             counter++;
00263           }
00264         }
00265       }
00266     }
00267 
00268     /* Definition of parent cell. */
00269     FieldContainer<double> cell_nodes(1, 6, cellDim);
00270     // funky Wedge (affine mapping)
00271     cell_nodes(0, 0, 0) = -3.0;
00272     cell_nodes(0, 0, 1) = -5.0;
00273     cell_nodes(0, 0, 2) = -5.0;
00274     cell_nodes(0, 1, 0) = -1.0;
00275     cell_nodes(0, 1, 1) = -4.0;
00276     cell_nodes(0, 1, 2) = -4.0;
00277     cell_nodes(0, 2, 0) = 0.0;
00278     cell_nodes(0, 2, 1) = 0.0;
00279     cell_nodes(0, 2, 2) = -5.0;
00280     cell_nodes(0, 3, 0) = 5.0;
00281     cell_nodes(0, 3, 1) = -1.0;
00282     cell_nodes(0, 3, 2) = 1.0;
00283     cell_nodes(0, 4, 0) = 7.0;
00284     cell_nodes(0, 4, 1) = 0.0;
00285     cell_nodes(0, 4, 2) = 2.0;
00286     cell_nodes(0, 5, 0) = 8.0;
00287     cell_nodes(0, 5, 1) = 4.0;
00288     cell_nodes(0, 5, 2) = 1.0;
00289 
00290     // perturbed reference Wedge
00291     /*cell_nodes(0, 0, 0) = 0.1;
00292     cell_nodes(0, 0, 1) = 0.1;
00293     cell_nodes(0, 0, 2) = -0.8;
00294     cell_nodes(0, 1, 0) = 1.2;
00295     cell_nodes(0, 1, 1) = 0.1;
00296     cell_nodes(0, 1, 2) = -0.95;
00297     cell_nodes(0, 2, 0) = 0.0;
00298     cell_nodes(0, 2, 1) = 0.9;
00299     cell_nodes(0, 2, 2) = -0.0;
00300     cell_nodes(0, 3, 0) = 0.1;
00301     cell_nodes(0, 3, 1) = 0.0;
00302     cell_nodes(0, 3, 2) = 0.9;
00303     cell_nodes(0, 4, 0) = 0.9;
00304     cell_nodes(0, 4, 1) = 0.1;
00305     cell_nodes(0, 4, 2) = 1.1;
00306     cell_nodes(0, 5, 0) = -0.1;
00307     cell_nodes(0, 5, 1) = 1.0;
00308     cell_nodes(0, 5, 2) = 1.0;*/
00309 
00310     // reference Wedge
00311     /*cell_nodes(0, 0, 0) = 0.0;
00312     cell_nodes(0, 0, 1) = 0.0;
00313     cell_nodes(0, 0, 2) = -1.0;
00314     cell_nodes(0, 1, 0) = 1.0;
00315     cell_nodes(0, 1, 1) = 0.0;
00316     cell_nodes(0, 1, 2) = -1.0;
00317     cell_nodes(0, 2, 0) = 0.0;
00318     cell_nodes(0, 2, 1) = 1.0;
00319     cell_nodes(0, 2, 2) = -1.0;
00320     cell_nodes(0, 3, 0) = 0.0;
00321     cell_nodes(0, 3, 1) = 0.0;
00322     cell_nodes(0, 3, 2) = 1.0;
00323     cell_nodes(0, 4, 0) = 1.0;
00324     cell_nodes(0, 4, 1) = 0.0;
00325     cell_nodes(0, 4, 2) = 1.0;
00326     cell_nodes(0, 5, 0) = 0.0;
00327     cell_nodes(0, 5, 1) = 1.0;
00328     cell_nodes(0, 5, 2) = 1.0;*/
00329 
00330 
00331     FieldContainer<double> interp_points(1, numInterpPoints, cellDim);
00332     CellTools<double>::mapToPhysicalFrame(interp_points, interp_points_ref, cell_nodes, cell);
00333     interp_points.resize(numInterpPoints, cellDim);
00334 
00335     for (int x_order=0; x_order <= max_order; x_order++) {
00336       for (int y_order=0; y_order <= max_order-x_order; y_order++) {
00337         for (int z_order=0; z_order <= max_order-x_order-y_order; z_order++) {
00338 
00339           // evaluate exact solution
00340           FieldContainer<double> exact_solution(1, numInterpPoints);
00341           u_exact(exact_solution, interp_points, x_order, y_order, z_order);
00342 
00343           int basis_order = 1;
00344 
00345           // set test tolerance;
00346           double zero = basis_order*basis_order*basis_order*100*INTREPID_TOL;
00347 
00348           //create basis
00349           Teuchos::RCP<Basis<double,FieldContainer<double> > > basis =
00350             Teuchos::rcp(new Basis_HGRAD_WEDGE_C1_FEM<double,FieldContainer<double> >() );
00351           int numFields = basis->getCardinality();
00352 
00353           // create cubatures
00354           Teuchos::RCP<Cubature<double> > cellCub = cubFactory.create(cell, 2*basis_order);
00355           Teuchos::RCP<Cubature<double> > sideQCub = cubFactory.create(sideQ, 2*basis_order);
00356           Teuchos::RCP<Cubature<double> > sideTCub = cubFactory.create(sideT, 2*basis_order);
00357           int numCubPointsCell = cellCub->getNumPoints();
00358           int numCubPointsSideQ = sideQCub->getNumPoints();
00359           int numCubPointsSideT = sideTCub->getNumPoints();
00360 
00361           /* Computational arrays. */
00362           /* Section 1: Related to parent cell integration. */
00363           FieldContainer<double> cub_points_cell(numCubPointsCell, cellDim);
00364           FieldContainer<double> cub_points_cell_physical(1, numCubPointsCell, cellDim);
00365           FieldContainer<double> cub_weights_cell(numCubPointsCell);
00366           FieldContainer<double> jacobian_cell(1, numCubPointsCell, cellDim, cellDim);
00367           FieldContainer<double> jacobian_inv_cell(1, numCubPointsCell, cellDim, cellDim);
00368           FieldContainer<double> jacobian_det_cell(1, numCubPointsCell);
00369           FieldContainer<double> weighted_measure_cell(1, numCubPointsCell);
00370 
00371           FieldContainer<double> value_of_basis_at_cub_points_cell(numFields, numCubPointsCell);
00372           FieldContainer<double> transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
00373           FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell);
00374           FieldContainer<double> grad_of_basis_at_cub_points_cell(numFields, numCubPointsCell, cellDim);
00375           FieldContainer<double> transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
00376           FieldContainer<double> weighted_transformed_grad_of_basis_at_cub_points_cell(1, numFields, numCubPointsCell, cellDim);
00377           FieldContainer<double> fe_matrix(1, numFields, numFields);
00378 
00379           FieldContainer<double> rhs_at_cub_points_cell_physical(1, numCubPointsCell);
00380           FieldContainer<double> rhs_and_soln_vector(1, numFields);
00381 
00382           /* Section 2: Related to subcell (side) integration. */
00383           unsigned numSides = 5;
00384           unsigned numSidesQ = 3;
00385           FieldContainer<double> cub_points_sideQ(numCubPointsSideQ, sideQDim);
00386           FieldContainer<double> cub_points_sideT(numCubPointsSideT, sideTDim);
00387           FieldContainer<double> cub_weights_sideQ(numCubPointsSideQ);
00388           FieldContainer<double> cub_weights_sideT(numCubPointsSideT);
00389           FieldContainer<double> cub_points_sideQ_refcell(numCubPointsSideQ, cellDim);
00390           FieldContainer<double> cub_points_sideT_refcell(numCubPointsSideT, cellDim);
00391           FieldContainer<double> cub_points_sideQ_physical(1, numCubPointsSideQ, cellDim);
00392           FieldContainer<double> cub_points_sideT_physical(1, numCubPointsSideT, cellDim);
00393           FieldContainer<double> jacobian_sideQ_refcell(1, numCubPointsSideQ, cellDim, cellDim);
00394           FieldContainer<double> jacobian_sideT_refcell(1, numCubPointsSideT, cellDim, cellDim);
00395           FieldContainer<double> jacobian_det_sideQ_refcell(1, numCubPointsSideQ);
00396           FieldContainer<double> jacobian_det_sideT_refcell(1, numCubPointsSideT);
00397           FieldContainer<double> weighted_measure_sideQ_refcell(1, numCubPointsSideQ);
00398           FieldContainer<double> weighted_measure_sideT_refcell(1, numCubPointsSideT);
00399 
00400           FieldContainer<double> value_of_basis_at_cub_points_sideQ_refcell(numFields, numCubPointsSideQ);
00401           FieldContainer<double> value_of_basis_at_cub_points_sideT_refcell(numFields, numCubPointsSideT);
00402           FieldContainer<double> transformed_value_of_basis_at_cub_points_sideQ_refcell(1, numFields, numCubPointsSideQ);
00403           FieldContainer<double> transformed_value_of_basis_at_cub_points_sideT_refcell(1, numFields, numCubPointsSideT);
00404           FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_sideQ_refcell(1, numFields, numCubPointsSideQ);
00405           FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points_sideT_refcell(1, numFields, numCubPointsSideT);
00406           FieldContainer<double> neumann_data_at_cub_points_sideQ_physical(1, numCubPointsSideQ);
00407           FieldContainer<double> neumann_data_at_cub_points_sideT_physical(1, numCubPointsSideT);
00408           FieldContainer<double> neumann_fields_per_side(1, numFields);
00409 
00410           /* Section 3: Related to global interpolant. */
00411           FieldContainer<double> value_of_basis_at_interp_points_ref(numFields, numInterpPoints);
00412           FieldContainer<double> transformed_value_of_basis_at_interp_points_ref(1, numFields, numInterpPoints);
00413           FieldContainer<double> interpolant(1, numInterpPoints);
00414 
00415           FieldContainer<int> ipiv(numFields);
00416 
00417 
00418 
00419           /******************* START COMPUTATION ***********************/
00420 
00421           // get cubature points and weights
00422           cellCub->getCubature(cub_points_cell, cub_weights_cell);
00423 
00424           // compute geometric cell information
00425           CellTools<double>::setJacobian(jacobian_cell, cub_points_cell, cell_nodes, cell);
00426           CellTools<double>::setJacobianInv(jacobian_inv_cell, jacobian_cell);
00427           CellTools<double>::setJacobianDet(jacobian_det_cell, jacobian_cell);
00428 
00429           // compute weighted measure
00430           FunctionSpaceTools::computeCellMeasure<double>(weighted_measure_cell, jacobian_det_cell, cub_weights_cell);
00431 
00433           // Computing mass matrices:
00434           // tabulate values of basis functions at (reference) cubature points
00435           basis->getValues(value_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_VALUE);
00436 
00437           // transform values of basis functions 
00438           FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_cell,
00439                                                           value_of_basis_at_cub_points_cell);
00440 
00441           // multiply with weighted measure
00442           FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_cell,
00443                                                       weighted_measure_cell,
00444                                                       transformed_value_of_basis_at_cub_points_cell);
00445 
00446           // compute mass matrices
00447           FunctionSpaceTools::integrate<double>(fe_matrix,
00448                                                 transformed_value_of_basis_at_cub_points_cell,
00449                                                 weighted_transformed_value_of_basis_at_cub_points_cell,
00450                                                 COMP_BLAS);
00452 
00454           // Computing stiffness matrices:
00455           // tabulate gradients of basis functions at (reference) cubature points
00456           basis->getValues(grad_of_basis_at_cub_points_cell, cub_points_cell, OPERATOR_GRAD);
00457 
00458           // transform gradients of basis functions 
00459           FunctionSpaceTools::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points_cell,
00460                                                          jacobian_inv_cell,
00461                                                          grad_of_basis_at_cub_points_cell);
00462 
00463           // multiply with weighted measure
00464           FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_grad_of_basis_at_cub_points_cell,
00465                                                       weighted_measure_cell,
00466                                                       transformed_grad_of_basis_at_cub_points_cell);
00467 
00468           // compute stiffness matrices and sum into fe_matrix
00469           FunctionSpaceTools::integrate<double>(fe_matrix,
00470                                                 transformed_grad_of_basis_at_cub_points_cell,
00471                                                 weighted_transformed_grad_of_basis_at_cub_points_cell,
00472                                                 COMP_BLAS,
00473                                                 true);
00475 
00477           // Computing RHS contributions:
00478           // map cell (reference) cubature points to physical space
00479           CellTools<double>::mapToPhysicalFrame(cub_points_cell_physical, cub_points_cell, cell_nodes, cell);
00480 
00481           // evaluate rhs function
00482           rhsFunc(rhs_at_cub_points_cell_physical, cub_points_cell_physical, x_order, y_order, z_order);
00483 
00484           // compute rhs
00485           FunctionSpaceTools::integrate<double>(rhs_and_soln_vector,
00486                                                 rhs_at_cub_points_cell_physical,
00487                                                 weighted_transformed_value_of_basis_at_cub_points_cell,
00488                                                 COMP_BLAS);
00489 
00490           // compute neumann b.c. contributions and adjust rhs
00491           sideQCub->getCubature(cub_points_sideQ, cub_weights_sideQ);
00492           sideTCub->getCubature(cub_points_sideT, cub_weights_sideT);
00493 
00494           for (unsigned i=0; i<numSidesQ; i++) {
00495             // compute geometric cell information
00496             CellTools<double>::mapToReferenceSubcell(cub_points_sideQ_refcell, cub_points_sideQ, sideQDim, (int)i, cell);
00497             CellTools<double>::setJacobian(jacobian_sideQ_refcell, cub_points_sideQ_refcell, cell_nodes, cell);
00498             CellTools<double>::setJacobianDet(jacobian_det_sideQ_refcell, jacobian_sideQ_refcell);
00499 
00500             // compute weighted face measure
00501             FunctionSpaceTools::computeFaceMeasure<double>(weighted_measure_sideQ_refcell,
00502                                                            jacobian_sideQ_refcell,
00503                                                            cub_weights_sideQ,
00504                                                            i,
00505                                                            cell);
00506 
00507             // tabulate values of basis functions at side cubature points, in the reference parent cell domain
00508             basis->getValues(value_of_basis_at_cub_points_sideQ_refcell, cub_points_sideQ_refcell, OPERATOR_VALUE);
00509             // transform
00510             FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_sideQ_refcell,
00511                                                             value_of_basis_at_cub_points_sideQ_refcell);
00512 
00513             // multiply with weighted measure
00514             FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_sideQ_refcell,
00515                                                         weighted_measure_sideQ_refcell,
00516                                                         transformed_value_of_basis_at_cub_points_sideQ_refcell);
00517 
00518             // compute Neumann data
00519             // map side cubature points in reference parent cell domain to physical space
00520             CellTools<double>::mapToPhysicalFrame(cub_points_sideQ_physical, cub_points_sideQ_refcell, cell_nodes, cell);
00521             // now compute data
00522             neumann(neumann_data_at_cub_points_sideQ_physical, cub_points_sideQ_physical, jacobian_sideQ_refcell,
00523                     cell, (int)i, x_order, y_order, z_order);
00524 
00525             FunctionSpaceTools::integrate<double>(neumann_fields_per_side,
00526                                                   neumann_data_at_cub_points_sideQ_physical,
00527                                                   weighted_transformed_value_of_basis_at_cub_points_sideQ_refcell,
00528                                                   COMP_BLAS);
00529 
00530             // adjust RHS
00531             RealSpaceTools<double>::add(rhs_and_soln_vector, neumann_fields_per_side);;
00532           }
00533 
00534           for (unsigned i=numSidesQ; i<numSides; i++) {
00535                         // compute geometric cell information
00536                         CellTools<double>::mapToReferenceSubcell(cub_points_sideT_refcell, cub_points_sideT, sideTDim, (int)i, cell);
00537                         CellTools<double>::setJacobian(jacobian_sideT_refcell, cub_points_sideT_refcell, cell_nodes, cell);
00538                         CellTools<double>::setJacobianDet(jacobian_det_sideT_refcell, jacobian_sideT_refcell);
00539 
00540                         // compute weighted face measure
00541                         FunctionSpaceTools::computeFaceMeasure<double>(weighted_measure_sideT_refcell,
00542                                                                                                                    jacobian_sideT_refcell,
00543                                                                                                                    cub_weights_sideT,
00544                                                                                                                    i,
00545                                                                                                                    cell);
00546 
00547                         // tabulate values of basis functions at side cubature points, in the reference parent cell domain
00548                         basis->getValues(value_of_basis_at_cub_points_sideT_refcell, cub_points_sideT_refcell, OPERATOR_VALUE);
00549                         // transform
00550                         FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points_sideT_refcell,
00551                                                                                             value_of_basis_at_cub_points_sideT_refcell);
00552 
00553                         // multiply with weighted measure
00554                         FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points_sideT_refcell,
00555                                                                                                             weighted_measure_sideT_refcell,
00556                                                                                                                 transformed_value_of_basis_at_cub_points_sideT_refcell);
00557 
00558                         // compute Neumann data
00559                         // map side cubature points in reference parent cell domain to physical space
00560                         CellTools<double>::mapToPhysicalFrame(cub_points_sideT_physical, cub_points_sideT_refcell, cell_nodes, cell);
00561                         // now compute data
00562                         neumann(neumann_data_at_cub_points_sideT_physical, cub_points_sideT_physical, jacobian_sideT_refcell,
00563                                     cell, (int)i, x_order, y_order, z_order);
00564 
00565                         FunctionSpaceTools::integrate<double>(neumann_fields_per_side,
00566                                                                                                   neumann_data_at_cub_points_sideT_physical,
00567                                                                                                   weighted_transformed_value_of_basis_at_cub_points_sideT_refcell,
00568                                                                                                   COMP_BLAS);
00569 
00570                     // adjust RHS
00571                         RealSpaceTools<double>::add(rhs_and_soln_vector, neumann_fields_per_side);;
00572                   }
00574 
00576           // Solution of linear system:
00577           int info = 0;
00578           Teuchos::LAPACK<int, double> solver;
00579           solver.GESV(numFields, 1, &fe_matrix[0], numFields, &ipiv(0), &rhs_and_soln_vector[0], numFields, &info);
00581 
00583           // Building interpolant:
00584           // evaluate basis at interpolation points
00585           basis->getValues(value_of_basis_at_interp_points_ref, interp_points_ref, OPERATOR_VALUE);
00586           // transform values of basis functions 
00587           FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_interp_points_ref,
00588                                                           value_of_basis_at_interp_points_ref);
00589           FunctionSpaceTools::evaluate<double>(interpolant, rhs_and_soln_vector, transformed_value_of_basis_at_interp_points_ref);
00591 
00592           /******************* END COMPUTATION ***********************/
00593       
00594           RealSpaceTools<double>::subtract(interpolant, exact_solution);
00595 
00596           *outStream << "\nRelative norm-2 error between exact solution polynomial of order ("
00597                      << x_order << ", " << y_order << ", " << z_order
00598                      << ") and finite element interpolant of order " << basis_order << ": "
00599                      << RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
00600                         RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) << "\n";
00601 
00602           if (RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) /
00603               RealSpaceTools<double>::vectorNorm(&exact_solution[0], exact_solution.dimension(1), NORM_TWO) > zero) {
00604             *outStream << "\n\nPatch test failed for solution polynomial order ("
00605                        << x_order << ", " << y_order << ", " << z_order << ") and basis order " << basis_order << "\n\n";
00606             errorFlag++;
00607           }
00608         } // end for z_order
00609       } // end for y_order
00610     } // end for x_order
00611 
00612   }
00613   // Catch unexpected errors
00614   catch (std::logic_error err) {
00615     *outStream << err.what() << "\n\n";
00616     errorFlag = -1000;
00617   };
00618 
00619   if (errorFlag != 0)
00620     std::cout << "End Result: TEST FAILED\n";
00621   else
00622     std::cout << "End Result: TEST PASSED\n";
00623 
00624   // reset format state of std::cout
00625   std::cout.copyfmt(oldFormatState);
00626 
00627   return errorFlag;
00628 }