00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00121
00122 int iprint = argc - 1;
00123 Teuchos::RCP<std::ostream> outStream;
00124 Teuchos::oblackholestream bhs;
00125 if (iprint > 0)
00126 outStream = Teuchos::rcp(&std::cout, false);
00127 else
00128 outStream = Teuchos::rcp(&bhs, false);
00129
00130
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;
00164
00165
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;
00174 shards::CellTopology line(shards::getCellTopologyData< shards::Line<> >());
00175
00176 for (int soln_order=1; soln_order <= max_order; soln_order++) {
00177
00178
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
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
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
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
00227
00228
00229 lineCub->getCubature(cub_points, cub_weights);
00230
00231
00232 cell_nodes(0, 0, 0) = -1.0;
00233 cell_nodes(0, 1, 0) = 1.0;
00234
00235
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
00241 FunctionSpaceTools::computeCellMeasure<double>(weighted_measure, jacobian_det, cub_weights);
00242
00244
00245
00246 lineBasis->getValues(value_of_basis_at_cub_points, cub_points, OPERATOR_VALUE);
00247
00248
00249 FunctionSpaceTools::HGRADtransformVALUE<double>(transformed_value_of_basis_at_cub_points,
00250 value_of_basis_at_cub_points);
00251
00252
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
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
00266
00267 lineBasis->getValues(grad_of_basis_at_cub_points, cub_points, OPERATOR_GRAD);
00268
00269
00270 FunctionSpaceTools::HGRADtransformGRAD<double>(transformed_grad_of_basis_at_cub_points,
00271 jacobian_inv,
00272 grad_of_basis_at_cub_points);
00273
00274
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
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
00289
00290 CellTools<double>::mapToPhysicalFrame(cub_points_physical, cub_points, cell_nodes, line);
00291
00292
00293 rhsFunc(rhs_at_cub_points_physical, cub_points_physical, soln_order);
00294
00295
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
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
00313 int info = 0;
00314 Teuchos::LAPACK<int, double> solver;
00315
00316 solver.GESV(numFields, 1, &fe_matrix[0], numFields, &ipiv(0), &rhs_and_soln_vector[0], numFields, &info);
00318
00320
00321
00322 lineBasis->getValues(value_of_basis_at_interp_points, interp_points, OPERATOR_VALUE);
00323
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
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 }
00344
00345 }
00346
00347 }
00348
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
00360 std::cout.copyfmt(oldFormatState);
00361
00362 return errorFlag;
00363 }