|
Intrepid
|
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 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Pavel Bochev (pbboche@sandia.gov), 00025 // Denis Ridzal (dridzal@sandia.gov), 00026 // Kara Peterson (kjpeter@sandia.gov). 00027 // 00028 // ************************************************************************ 00029 // @HEADER 00030 00036 #include "Intrepid_FieldContainer.hpp" 00037 #include "Intrepid_HGRAD_LINE_Cn_FEM_JACOBI.hpp" 00038 #include "Intrepid_DefaultCubatureFactory.hpp" 00039 #include "Intrepid_RealSpaceTools.hpp" 00040 #include "Intrepid_ArrayTools.hpp" 00041 #include "Intrepid_FunctionSpaceTools.hpp" 00042 #include "Intrepid_CellTools.hpp" 00043 #include "Teuchos_oblackholestream.hpp" 00044 #include "Teuchos_RCP.hpp" 00045 #include "Teuchos_GlobalMPISession.hpp" 00046 #include "Teuchos_SerialDenseMatrix.hpp" 00047 #include "Teuchos_SerialDenseVector.hpp" 00048 #include "Teuchos_LAPACK.hpp" 00049 00050 using namespace std; 00051 using namespace Intrepid; 00052 00053 void rhsFunc(FieldContainer<double> &, const FieldContainer<double> &, int); 00054 void neumann(FieldContainer<double> &, const FieldContainer<double> &, const FieldContainer<double> &, int); 00055 void u_exact(FieldContainer<double> &, const FieldContainer<double> &, int); 00056 00058 void rhsFunc(FieldContainer<double> & result, const FieldContainer<double> & points, int degree) { 00059 if (degree == 0) { 00060 for (int cell=0; cell<result.dimension(0); cell++) { 00061 for (int pt=0; pt<result.dimension(1); pt++) { 00062 result(cell,pt) = 1.0; 00063 } 00064 } 00065 } 00066 else if (degree == 1) { 00067 for (int cell=0; cell<result.dimension(0); cell++) { 00068 for (int pt=0; pt<result.dimension(1); pt++) { 00069 result(cell,pt) = points(cell,pt,0); 00070 } 00071 } 00072 } 00073 else { 00074 for (int cell=0; cell<result.dimension(0); cell++) { 00075 for (int pt=0; pt<result.dimension(1); pt++) { 00076 result(cell,pt) = pow(points(cell,pt,0), degree) - degree*(degree-1)*pow(points(cell,pt,0), degree-2); 00077 } 00078 } 00079 } 00080 } 00081 00083 void neumann(FieldContainer<double> & g_phi, const FieldContainer<double> & phi1, const FieldContainer<double> & phi2, int degree) { 00084 double g_at_one, g_at_minus_one; 00085 int num_fields; 00086 00087 if (degree == 0) { 00088 g_at_one = 0.0; 00089 g_at_minus_one = 0.0; 00090 } 00091 else { 00092 g_at_one = degree*pow(1.0, degree-1); 00093 g_at_minus_one = degree*pow(-1.0, degree-1); 00094 } 00095 00096 num_fields = phi1.dimension(0); 00097 00098 for (int i=0; i<num_fields; i++) { 00099 g_phi(0,i) = g_at_minus_one*phi1(i,0); 00100 g_phi(1,i) = g_at_one*phi2(i,0); 00101 } 00102 } 00103 00105 void u_exact(FieldContainer<double> & result, const FieldContainer<double> & points, int degree) { 00106 for (int cell=0; cell<result.dimension(0); cell++) { 00107 for (int pt=0; pt<result.dimension(1); pt++) { 00108 result(cell,pt) = pow(points(pt,0), degree); 00109 } 00110 } 00111 } 00112 00113 00114 00115 00116 int main(int argc, char *argv[]) { 00117 00118 Teuchos::GlobalMPISession mpiSession(&argc, &argv); 00119 00120 // This little trick lets us print to std::cout only if 00121 // a (dummy) command-line argument is provided. 00122 int iprint = argc - 1; 00123 Teuchos::RCP<std::ostream> outStream; 00124 Teuchos::oblackholestream bhs; // outputs nothing 00125 if (iprint > 0) 00126 outStream = Teuchos::rcp(&std::cout, false); 00127 else 00128 outStream = Teuchos::rcp(&bhs, false); 00129 00130 // Save the format state of the original std::cout. 00131 Teuchos::oblackholestream oldFormatState; 00132 oldFormatState.copyfmt(std::cout); 00133 00134 *outStream \ 00135 << "===============================================================================\n" \ 00136 << "| |\n" \ 00137 << "| Unit Test (Basis_HGRAD_LINE_Cn_FEM_JACOBI) |\n" \ 00138 << "| |\n" \ 00139 << "| 1) Patch test involving mass and stiffness matrices, |\n" \ 00140 << "| for the Neumann problem on a REFERENCE line: |\n" \ 00141 << "| |\n" \ 00142 << "| - u'' + u = f in (-1,1), u' = g at -1,1 |\n" \ 00143 << "| |\n" \ 00144 << "| Questions? Contact Pavel Bochev (pbboche@sandia.gov), |\n" \ 00145 << "| Denis Ridzal (dridzal@sandia.gov), |\n" \ 00146 << "| Kara Peterson (kjpeter@sandia.gov). |\n" \ 00147 << "| |\n" \ 00148 << "| Intrepid's website: http://trilinos.sandia.gov/packages/intrepid |\n" \ 00149 << "| Trilinos website: http://trilinos.sandia.gov |\n" \ 00150 << "| |\n" \ 00151 << "===============================================================================\n"\ 00152 << "| TEST 1: Patch test |\n"\ 00153 << "===============================================================================\n"; 00154 00155 00156 int errorFlag = 0; 00157 double zero = 100*INTREPID_TOL; 00158 outStream -> precision(20); 00159 00160 00161 try { 00162 00163 int max_order = 10; // max total order of polynomial solution 00164 00165 // Define array containing points at which the solution is evaluated 00166 int numIntervals = 100; 00167 int numInterpPoints = numIntervals + 1; 00168 FieldContainer<double> interp_points(numInterpPoints, 1); 00169 for (int i=0; i<numInterpPoints; i++) { 00170 interp_points(i,0) = -1.0+(2.0*(double)i)/(double)numIntervals; 00171 } 00172 00173 DefaultCubatureFactory<double> cubFactory; // create factory 00174 shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >()); // create cell topology 00175 00176 for (int soln_order=1; soln_order <= max_order; soln_order++) { 00177 00178 // evaluate exact solution 00179 FieldContainer<double> exact_solution(1, numInterpPoints); 00180 u_exact(exact_solution, interp_points, soln_order); 00181 00182 for (int basis_order=soln_order; basis_order <= max_order; basis_order++) { 00183 00184 //create basis 00185 Teuchos::RCP<Basis<double,FieldContainer<double> > > lineBasis = 00186 Teuchos::rcp(new Basis_HGRAD_LINE_Cn_FEM_JACOBI<double,FieldContainer<double> >(basis_order) ); 00187 int numFields = lineBasis->getCardinality(); 00188 00189 // create cubature 00190 Teuchos::RCP<Cubature<double> > lineCub = cubFactory.create(line, 2*basis_order-2); 00191 int numCubPoints = lineCub->getNumPoints(); 00192 int spaceDim = lineCub->getDimension(); 00193 00194 /* Computational arrays. */ 00195 FieldContainer<double> cub_points(numCubPoints, spaceDim); 00196 FieldContainer<double> cub_points_physical(1, numCubPoints, spaceDim); 00197 FieldContainer<double> cub_weights(numCubPoints); 00198 FieldContainer<double> cell_nodes(1, 2, spaceDim); 00199 FieldContainer<double> jacobian(1, numCubPoints, spaceDim, spaceDim); 00200 FieldContainer<double> jacobian_inv(1, numCubPoints, spaceDim, spaceDim); 00201 FieldContainer<double> jacobian_det(1, numCubPoints); 00202 FieldContainer<double> weighted_measure(1, numCubPoints); 00203 00204 FieldContainer<double> value_of_basis_at_cub_points(numFields, numCubPoints); 00205 FieldContainer<double> transformed_value_of_basis_at_cub_points(1, numFields, numCubPoints); 00206 FieldContainer<double> weighted_transformed_value_of_basis_at_cub_points(1, numFields, numCubPoints); 00207 FieldContainer<double> grad_of_basis_at_cub_points(numFields, numCubPoints, spaceDim); 00208 FieldContainer<double> transformed_grad_of_basis_at_cub_points(1, numFields, numCubPoints, spaceDim); 00209 FieldContainer<double> weighted_transformed_grad_of_basis_at_cub_points(1, numFields, numCubPoints, spaceDim); 00210 FieldContainer<double> fe_matrix(1, numFields, numFields); 00211 00212 FieldContainer<double> rhs_at_cub_points_physical(1, numCubPoints); 00213 FieldContainer<double> rhs_and_soln_vector(1, numFields); 00214 00215 FieldContainer<double> one_point(1, 1); 00216 FieldContainer<double> value_of_basis_at_one(numFields, 1); 00217 FieldContainer<double> value_of_basis_at_minusone(numFields, 1); 00218 FieldContainer<double> bc_neumann(2, numFields); 00219 00220 FieldContainer<double> value_of_basis_at_interp_points(numFields, numInterpPoints); 00221 FieldContainer<double> transformed_value_of_basis_at_interp_points(1, numFields, numInterpPoints); 00222 FieldContainer<double> interpolant(1, numInterpPoints); 00223 00224 FieldContainer<int> ipiv(numFields); 00225 00226 /******************* START COMPUTATION ***********************/ 00227 00228 // get cubature points and weights 00229 lineCub->getCubature(cub_points, cub_weights); 00230 00231 // fill cell vertex array 00232 cell_nodes(0, 0, 0) = -1.0; 00233 cell_nodes(0, 1, 0) = 1.0; 00234 00235 // compute geometric cell information 00236 CellTools<double>::setJacobian(jacobian, cub_points, cell_nodes, line); 00237 CellTools<double>::setJacobianInv(jacobian_inv, jacobian); 00238 CellTools<double>::setJacobianDet(jacobian_det, jacobian); 00239 00240 // compute weighted measure 00241 FunctionSpaceTools::computeCellMeasure<double>(weighted_measure, jacobian_det, cub_weights); 00242 00244 // Computing mass matrices: 00245 // tabulate values of basis functions at (reference) cubature points 00246 lineBasis->getValues(value_of_basis_at_cub_points, cub_points, OPERATOR_VALUE); 00247 00248 // transform values of basis functions 00249 FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points, 00250 value_of_basis_at_cub_points); 00251 00252 // multiply with weighted measure 00253 FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_value_of_basis_at_cub_points, 00254 weighted_measure, 00255 transformed_value_of_basis_at_cub_points); 00256 00257 // compute mass matrices 00258 FunctionSpaceTools::integrate<double>(fe_matrix, 00259 transformed_value_of_basis_at_cub_points, 00260 weighted_transformed_value_of_basis_at_cub_points, 00261 COMP_CPP); 00263 00265 // Computing stiffness matrices: 00266 // tabulate gradients of basis functions at (reference) cubature points 00267 lineBasis->getValues(grad_of_basis_at_cub_points, cub_points, OPERATOR_GRAD); 00268 00269 // transform gradients of basis functions 00270 FunctionSpaceTools::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points, 00271 jacobian_inv, 00272 grad_of_basis_at_cub_points); 00273 00274 // multiply with weighted measure 00275 FunctionSpaceTools::multiplyMeasure<double>(weighted_transformed_grad_of_basis_at_cub_points, 00276 weighted_measure, 00277 transformed_grad_of_basis_at_cub_points); 00278 00279 // compute stiffness matrices and sum into fe_matrix 00280 FunctionSpaceTools::integrate<double>(fe_matrix, 00281 transformed_grad_of_basis_at_cub_points, 00282 weighted_transformed_grad_of_basis_at_cub_points, 00283 COMP_CPP, 00284 true); 00286 00288 // Computing RHS contributions: 00289 // map (reference) cubature points to physical space 00290 CellTools<double>::mapToPhysicalFrame(cub_points_physical, cub_points, cell_nodes, line); 00291 00292 // evaluate rhs function 00293 rhsFunc(rhs_at_cub_points_physical, cub_points_physical, soln_order); 00294 00295 // compute rhs 00296 FunctionSpaceTools::integrate<double>(rhs_and_soln_vector, 00297 rhs_at_cub_points_physical, 00298 weighted_transformed_value_of_basis_at_cub_points, 00299 COMP_CPP); 00300 00301 // compute neumann b.c. contributions and adjust rhs 00302 one_point(0,0) = 1.0; lineBasis->getValues(value_of_basis_at_one, one_point, OPERATOR_VALUE); 00303 one_point(0,0) = -1.0; lineBasis->getValues(value_of_basis_at_minusone, one_point, OPERATOR_VALUE); 00304 neumann(bc_neumann, value_of_basis_at_minusone, value_of_basis_at_one, soln_order); 00305 for (int i=0; i<numFields; i++) { 00306 rhs_and_soln_vector(0, i) -= bc_neumann(0, i); 00307 rhs_and_soln_vector(0, i) += bc_neumann(1, i); 00308 } 00310 00312 // Solution of linear system: 00313 int info = 0; 00314 Teuchos::LAPACK<int, double> solver; 00315 //solver.GESV(numRows, 1, &fe_mat(0,0), numRows, &ipiv(0), &fe_vec(0), numRows, &info); 00316 solver.GESV(numFields, 1, &fe_matrix[0], numFields, &ipiv(0), &rhs_and_soln_vector[0], numFields, &info); 00318 00320 // Building interpolant: 00321 // evaluate basis at interpolation points 00322 lineBasis->getValues(value_of_basis_at_interp_points, interp_points, OPERATOR_VALUE); 00323 // transform values of basis functions 00324 FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_interp_points, 00325 value_of_basis_at_interp_points); 00326 FunctionSpaceTools::evaluate<double>(interpolant, rhs_and_soln_vector, transformed_value_of_basis_at_interp_points); 00328 00329 /******************* END COMPUTATION ***********************/ 00330 00331 RealSpaceTools<double>::subtract(interpolant, exact_solution); 00332 00333 *outStream << "\nNorm-2 difference between exact solution polynomial of order " 00334 << soln_order << " and finite element interpolant of order " << basis_order << ": " 00335 << RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) << "\n"; 00336 00337 if (RealSpaceTools<double>::vectorNorm(&interpolant[0], interpolant.dimension(1), NORM_TWO) > zero) { 00338 *outStream << "\n\nPatch test failed for solution polynomial order " 00339 << soln_order << " and basis order " << basis_order << "\n\n"; 00340 errorFlag++; 00341 } 00342 00343 } // end for basis_order 00344 00345 } // end for soln_order 00346 00347 } 00348 // Catch unexpected errors 00349 catch (std::logic_error err) { 00350 *outStream << err.what() << "\n\n"; 00351 errorFlag = -1000; 00352 }; 00353 00354 if (errorFlag != 0) 00355 std::cout << "End Result: TEST FAILED\n"; 00356 else 00357 std::cout << "End Result: TEST PASSED\n"; 00358 00359 // reset format state of std::cout 00360 std::cout.copyfmt(oldFormatState); 00361 00362 return errorFlag; 00363 }
1.7.4