$extrastylesheet
fe_clough_shape_2D.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 // C++ inlcludes
00020 
00021 // Local includes
00022 #include "libmesh/fe.h"
00023 #include "libmesh/elem.h"
00024 
00025 
00026 // Anonymous namespace for persistant variables.
00027 // This allows us to cache the global-to-local mapping transformation
00028 // FIXME: This should also screw up multithreading royally
00029 namespace
00030 {
00031 using namespace libMesh;
00032 
00033 static dof_id_type old_elem_id = DofObject::invalid_id;
00034 // Coefficient naming: d(1)d(2n) is the coefficient of the
00035 // global shape function corresponding to value 1 in terms of the
00036 // local shape function corresponding to normal derivative 2
00037 static Real d1d2n, d1d3n, d2d3n, d2d1n, d3d1n, d3d2n;
00038 static Real d1xd1x, d1xd1y, d1xd2n, d1xd3n;
00039 static Real d1yd1x, d1yd1y, d1yd2n, d1yd3n;
00040 static Real d2xd2x, d2xd2y, d2xd3n, d2xd1n;
00041 static Real d2yd2x, d2yd2y, d2yd3n, d2yd1n;
00042 static Real d3xd3x, d3xd3y, d3xd1n, d3xd2n;
00043 static Real d3yd3x, d3yd3y, d3yd1n, d3yd2n;
00044 static Real d1nd1n, d2nd2n, d3nd3n;
00045 // Normal vector naming: N01x is the x component of the
00046 // unit vector at point 0 normal to (possibly curved) side 01
00047 static Real N01x, N01y, N10x, N10y;
00048 static Real N02x, N02y, N20x, N20y;
00049 static Real N21x, N21y, N12x, N12y;
00050 
00051 Real clough_raw_shape_second_deriv(const unsigned int basis_num,
00052                                    const unsigned int deriv_type,
00053                                    const Point& p);
00054 Real clough_raw_shape_deriv(const unsigned int basis_num,
00055                             const unsigned int deriv_type,
00056                             const Point& p);
00057 Real clough_raw_shape(const unsigned int basis_num,
00058                       const Point& p);
00059 unsigned char subtriangle_lookup(const Point& p);
00060 
00061 
00062 // Compute the static coefficients for an element
00063 void clough_compute_coefs(const Elem* elem)
00064 {
00065   // Using static globals for old_elem_id, etc. will fail
00066   // horribly with more than one thread.
00067   libmesh_assert_equal_to (libMesh::n_threads(), 1);
00068 
00069   // Coefficients are cached from old elements
00070   if (elem->id() == old_elem_id)
00071     return;
00072 
00073   old_elem_id = elem->id();
00074 
00075   const Order mapping_order        (elem->default_order());
00076   const ElemType mapping_elem_type (elem->type());
00077   const int n_mapping_shape_functions =
00078     FE<2,LAGRANGE>::n_shape_functions(mapping_elem_type,
00079                                       mapping_order);
00080 
00081   // Degrees of freedom are at vertices and edge midpoints
00082   std::vector<Point> dofpt;
00083   dofpt.push_back(Point(0,0));
00084   dofpt.push_back(Point(1,0));
00085   dofpt.push_back(Point(0,1));
00086   dofpt.push_back(Point(1/2.,1/2.));
00087   dofpt.push_back(Point(0,1/2.));
00088   dofpt.push_back(Point(1/2.,0));
00089 
00090   // Mapping functions - first derivatives at each dofpt
00091   std::vector<Real> dxdxi(6), dxdeta(6), dydxi(6), dydeta(6);
00092   std::vector<Real> dxidx(6), detadx(6), dxidy(6), detady(6);
00093 
00094   for (int p = 0; p != 6; ++p)
00095     {
00096       //      libMesh::err << p << ' ' << dofpt[p];
00097       for (int i = 0; i != n_mapping_shape_functions; ++i)
00098         {
00099           const Real ddxi = FE<2,LAGRANGE>::shape_deriv
00100             (mapping_elem_type, mapping_order, i, 0, dofpt[p]);
00101           const Real ddeta = FE<2,LAGRANGE>::shape_deriv
00102             (mapping_elem_type, mapping_order, i, 1, dofpt[p]);
00103 
00104           //      libMesh::err << ddxi << ' ';
00105           //      libMesh::err << ddeta << std::endl;
00106 
00107           dxdxi[p] += elem->point(i)(0) * ddxi;
00108           dydxi[p] += elem->point(i)(1) * ddxi;
00109           dxdeta[p] += elem->point(i)(0) * ddeta;
00110           dydeta[p] += elem->point(i)(1) * ddeta;
00111         }
00112 
00113       //      for (int i = 0; i != 12; ++i)
00114       //          libMesh::err << i << ' ' << clough_raw_shape(i, dofpt[p]) << std::endl;
00115 
00116       //      libMesh::err << elem->point(p)(0) << ' ';
00117       //      libMesh::err << elem->point(p)(1) << ' ';
00118       //      libMesh::err << dxdxi[p] << ' ';
00119       //      libMesh::err << dydxi[p] << ' ';
00120       //      libMesh::err << dxdeta[p] << ' ';
00121       //      libMesh::err << dydeta[p] << std::endl << std::endl;
00122 
00123       const Real inv_jac = 1. / (dxdxi[p]*dydeta[p] -
00124                                  dxdeta[p]*dydxi[p]);
00125       dxidx[p] = dydeta[p] * inv_jac;
00126       dxidy[p] = - dxdeta[p] * inv_jac;
00127       detadx[p] = - dydxi[p] * inv_jac;
00128       detady[p] = dxdxi[p] * inv_jac;
00129     }
00130 
00131   // Calculate midpoint normal vectors
00132   Real N1x = dydeta[3] - dydxi[3];
00133   Real N1y = dxdxi[3] - dxdeta[3];
00134   Real Nlength = std::sqrt(static_cast<Real>(N1x*N1x + N1y*N1y));
00135   N1x /= Nlength; N1y /= Nlength;
00136 
00137   Real N2x = - dydeta[4];
00138   Real N2y = dxdeta[4];
00139   Nlength = std::sqrt(static_cast<Real>(N2x*N2x + N2y*N2y));
00140   N2x /= Nlength; N2y /= Nlength;
00141 
00142   Real N3x = dydxi[5];
00143   Real N3y = - dxdxi[5];
00144   Nlength = std::sqrt(static_cast<Real>(N3x*N3x + N3y*N3y));
00145   N3x /= Nlength; N3y /= Nlength;
00146 
00147   // Calculate corner normal vectors (used for reduced element)
00148   N01x = dydxi[0];
00149   N01y = - dxdxi[0];
00150   Nlength = std::sqrt(static_cast<Real>(N01x*N01x + N01y*N01y));
00151   N01x /= Nlength; N01y /= Nlength;
00152 
00153   N10x = dydxi[1];
00154   N10y = - dxdxi[1];
00155   Nlength = std::sqrt(static_cast<Real>(N10x*N10x + N10y*N10y));
00156   N10x /= Nlength; N10y /= Nlength;
00157 
00158   N02x = - dydeta[0];
00159   N02y = dxdeta[0];
00160   Nlength = std::sqrt(static_cast<Real>(N02x*N02x + N02y*N02y));
00161   N02x /= Nlength; N02y /= Nlength;
00162 
00163   N20x = - dydeta[2];
00164   N20y = dxdeta[2];
00165   Nlength = std::sqrt(static_cast<Real>(N20x*N20x + N20y*N20y));
00166   N20x /= Nlength; N20y /= Nlength;
00167 
00168   N12x = dydeta[1] - dydxi[1];
00169   N12y = dxdxi[1] - dxdeta[1];
00170   Nlength = std::sqrt(static_cast<Real>(N12x*N12x + N12y*N12y));
00171   N12x /= Nlength; N12y /= Nlength;
00172 
00173   N21x = dydeta[1] - dydxi[1];
00174   N21y = dxdxi[1] - dxdeta[1];
00175   Nlength = std::sqrt(static_cast<Real>(N21x*N21x + N21y*N21y));
00176   N21x /= Nlength; N21y /= Nlength;
00177 
00178   //  for (int i=0; i != 6; ++i) {
00179   //    libMesh::err << elem->node(i) << ' ';
00180   //  }
00181   //  libMesh::err << std::endl;
00182 
00183   //  for (int i=0; i != 6; ++i) {
00184   //    libMesh::err << elem->point(i)(0) << ' ';
00185   //    libMesh::err << elem->point(i)(1) << ' ';
00186   //  }
00187   //  libMesh::err << std::endl;
00188 
00189 
00190   // give normal vectors a globally unique orientation
00191 
00192   if (elem->point(2) < elem->point(1))
00193     {
00194       //      libMesh::err << "Flipping nodes " << elem->node(2);
00195       //      libMesh::err << " and " << elem->node(1);
00196       //      libMesh::err << " around node " << elem->node(4);
00197       //      libMesh::err << std::endl;
00198       N1x = -N1x; N1y = -N1y;
00199       N12x = -N12x; N12y = -N12y;
00200       N21x = -N21x; N21y = -N21y;
00201     }
00202   else
00203     {
00204       //      libMesh::err << "Not flipping nodes " << elem->node(2);
00205       //      libMesh::err << " and " << elem->node(1);
00206       //      libMesh::err << " around node " << elem->node(4);
00207       //      libMesh::err << std::endl;
00208     }
00209   if (elem->point(0) < elem->point(2))
00210     {
00211       //      libMesh::err << "Flipping nodes " << elem->node(0);
00212       //      libMesh::err << " and " << elem->node(2);
00213       //      libMesh::err << " around node " << elem->node(5);
00214       //      libMesh::err << std::endl;
00215       //      libMesh::err << N2x << ' ' << N2y << std::endl;
00216       N2x = -N2x; N2y = -N2y;
00217       N02x = -N02x; N02y = -N02y;
00218       N20x = -N20x; N20y = -N20y;
00219       //      libMesh::err << N2x << ' ' << N2y << std::endl;
00220     }
00221   else
00222     {
00223       //      libMesh::err << "Not flipping nodes " << elem->node(0);
00224       //      libMesh::err << " and " << elem->node(2);
00225       //      libMesh::err << " around node " << elem->node(5);
00226       //      libMesh::err << std::endl;
00227     }
00228   if (elem->point(1) < elem->point(0))
00229     {
00230       //      libMesh::err << "Flipping nodes " << elem->node(1);
00231       //      libMesh::err << " and " << elem->node(0);
00232       //      libMesh::err << " around node " << elem->node(3);
00233       //      libMesh::err << std::endl;
00234       N3x = -N3x;
00235       N3y = -N3y;
00236       N01x = -N01x; N01y = -N01y;
00237       N10x = -N10x; N10y = -N10y;
00238     }
00239   else
00240     {
00241       //      libMesh::err << "Not flipping nodes " << elem->node(1);
00242       //      libMesh::err << " and " << elem->node(0);
00243       //      libMesh::err << " around node " << elem->node(3);
00244       //      libMesh::err << std::endl;
00245     }
00246 
00247   //  libMesh::err << N2x << ' ' << N2y << std::endl;
00248 
00249   // Cache basis function gradients
00250   // FIXME: the raw_shape calls shouldn't be done on every element!
00251   // FIXME: I should probably be looping, too...
00252   // Gradient naming: d(1)d(2n)d(xi) is the xi component of the
00253   // gradient of the
00254   // local basis function corresponding to value 1 at the node
00255   // corresponding to normal vector 2
00256 
00257   Real d1d2ndxi   = clough_raw_shape_deriv(0, 0, dofpt[4]);
00258   Real d1d2ndeta  = clough_raw_shape_deriv(0, 1, dofpt[4]);
00259   Real d1d2ndx = d1d2ndxi * dxidx[4] + d1d2ndeta * detadx[4];
00260   Real d1d2ndy = d1d2ndxi * dxidy[4] + d1d2ndeta * detady[4];
00261   Real d1d3ndxi   = clough_raw_shape_deriv(0, 0, dofpt[5]);
00262   Real d1d3ndeta  = clough_raw_shape_deriv(0, 1, dofpt[5]);
00263   Real d1d3ndx = d1d3ndxi * dxidx[5] + d1d3ndeta * detadx[5];
00264   Real d1d3ndy = d1d3ndxi * dxidy[5] + d1d3ndeta * detady[5];
00265   Real d2d3ndxi   = clough_raw_shape_deriv(1, 0, dofpt[5]);
00266   Real d2d3ndeta  = clough_raw_shape_deriv(1, 1, dofpt[5]);
00267   Real d2d3ndx = d2d3ndxi * dxidx[5] + d2d3ndeta * detadx[5];
00268   Real d2d3ndy = d2d3ndxi * dxidy[5] + d2d3ndeta * detady[5];
00269   Real d2d1ndxi   = clough_raw_shape_deriv(1, 0, dofpt[3]);
00270   Real d2d1ndeta  = clough_raw_shape_deriv(1, 1, dofpt[3]);
00271   Real d2d1ndx = d2d1ndxi * dxidx[3] + d2d1ndeta * detadx[3];
00272   Real d2d1ndy = d2d1ndxi * dxidy[3] + d2d1ndeta * detady[3];
00273   Real d3d1ndxi   = clough_raw_shape_deriv(2, 0, dofpt[3]);
00274   Real d3d1ndeta  = clough_raw_shape_deriv(2, 1, dofpt[3]);
00275   Real d3d1ndx = d3d1ndxi * dxidx[3] + d3d1ndeta * detadx[3];
00276   Real d3d1ndy = d3d1ndxi * dxidy[3] + d3d1ndeta * detady[3];
00277   Real d3d2ndxi   = clough_raw_shape_deriv(2, 0, dofpt[4]);
00278   Real d3d2ndeta  = clough_raw_shape_deriv(2, 1, dofpt[4]);
00279   Real d3d2ndx = d3d2ndxi * dxidx[4] + d3d2ndeta * detadx[4];
00280   Real d3d2ndy = d3d2ndxi * dxidy[4] + d3d2ndeta * detady[4];
00281   Real d1xd2ndxi  = clough_raw_shape_deriv(3, 0, dofpt[4]);
00282   Real d1xd2ndeta = clough_raw_shape_deriv(3, 1, dofpt[4]);
00283   Real d1xd2ndx = d1xd2ndxi * dxidx[4] + d1xd2ndeta * detadx[4];
00284   Real d1xd2ndy = d1xd2ndxi * dxidy[4] + d1xd2ndeta * detady[4];
00285   Real d1xd3ndxi  = clough_raw_shape_deriv(3, 0, dofpt[5]);
00286   Real d1xd3ndeta = clough_raw_shape_deriv(3, 1, dofpt[5]);
00287   Real d1xd3ndx = d1xd3ndxi * dxidx[5] + d1xd3ndeta * detadx[5];
00288   Real d1xd3ndy = d1xd3ndxi * dxidy[5] + d1xd3ndeta * detady[5];
00289   Real d1yd2ndxi  = clough_raw_shape_deriv(4, 0, dofpt[4]);
00290   Real d1yd2ndeta = clough_raw_shape_deriv(4, 1, dofpt[4]);
00291   Real d1yd2ndx = d1yd2ndxi * dxidx[4] + d1yd2ndeta * detadx[4];
00292   Real d1yd2ndy = d1yd2ndxi * dxidy[4] + d1yd2ndeta * detady[4];
00293   Real d1yd3ndxi  = clough_raw_shape_deriv(4, 0, dofpt[5]);
00294   Real d1yd3ndeta = clough_raw_shape_deriv(4, 1, dofpt[5]);
00295   Real d1yd3ndx = d1yd3ndxi * dxidx[5] + d1yd3ndeta * detadx[5];
00296   Real d1yd3ndy = d1yd3ndxi * dxidy[5] + d1yd3ndeta * detady[5];
00297   Real d2xd3ndxi  = clough_raw_shape_deriv(5, 0, dofpt[5]);
00298   Real d2xd3ndeta = clough_raw_shape_deriv(5, 1, dofpt[5]);
00299   Real d2xd3ndx = d2xd3ndxi * dxidx[5] + d2xd3ndeta * detadx[5];
00300   Real d2xd3ndy = d2xd3ndxi * dxidy[5] + d2xd3ndeta * detady[5];
00301   Real d2xd1ndxi  = clough_raw_shape_deriv(5, 0, dofpt[3]);
00302   Real d2xd1ndeta = clough_raw_shape_deriv(5, 1, dofpt[3]);
00303   Real d2xd1ndx = d2xd1ndxi * dxidx[3] + d2xd1ndeta * detadx[3];
00304   Real d2xd1ndy = d2xd1ndxi * dxidy[3] + d2xd1ndeta * detady[3];
00305   Real d2yd3ndxi  = clough_raw_shape_deriv(6, 0, dofpt[5]);
00306   Real d2yd3ndeta = clough_raw_shape_deriv(6, 1, dofpt[5]);
00307   Real d2yd3ndx = d2yd3ndxi * dxidx[5] + d2yd3ndeta * detadx[5];
00308   Real d2yd3ndy = d2yd3ndxi * dxidy[5] + d2yd3ndeta * detady[5];
00309   Real d2yd1ndxi  = clough_raw_shape_deriv(6, 0, dofpt[3]);
00310   Real d2yd1ndeta = clough_raw_shape_deriv(6, 1, dofpt[3]);
00311   Real d2yd1ndx = d2yd1ndxi * dxidx[3] + d2yd1ndeta * detadx[3];
00312   Real d2yd1ndy = d2yd1ndxi * dxidy[3] + d2yd1ndeta * detady[3];
00313   Real d3xd1ndxi  = clough_raw_shape_deriv(7, 0, dofpt[3]);
00314   Real d3xd1ndeta = clough_raw_shape_deriv(7, 1, dofpt[3]);
00315   Real d3xd1ndx = d3xd1ndxi * dxidx[3] + d3xd1ndeta * detadx[3];
00316   Real d3xd1ndy = d3xd1ndxi * dxidy[3] + d3xd1ndeta * detady[3];
00317   Real d3xd2ndxi  = clough_raw_shape_deriv(7, 0, dofpt[4]);
00318   Real d3xd2ndeta = clough_raw_shape_deriv(7, 1, dofpt[4]);
00319   Real d3xd2ndx = d3xd2ndxi * dxidx[4] + d3xd2ndeta * detadx[4];
00320   Real d3xd2ndy = d3xd2ndxi * dxidy[4] + d3xd2ndeta * detady[4];
00321   Real d3yd1ndxi  = clough_raw_shape_deriv(8, 0, dofpt[3]);
00322   Real d3yd1ndeta = clough_raw_shape_deriv(8, 1, dofpt[3]);
00323   Real d3yd1ndx = d3yd1ndxi * dxidx[3] + d3yd1ndeta * detadx[3];
00324   Real d3yd1ndy = d3yd1ndxi * dxidy[3] + d3yd1ndeta * detady[3];
00325   Real d3yd2ndxi  = clough_raw_shape_deriv(8, 0, dofpt[4]);
00326   Real d3yd2ndeta = clough_raw_shape_deriv(8, 1, dofpt[4]);
00327   Real d3yd2ndx = d3yd2ndxi * dxidx[4] + d3yd2ndeta * detadx[4];
00328   Real d3yd2ndy = d3yd2ndxi * dxidy[4] + d3yd2ndeta * detady[4];
00329   Real d1nd1ndxi  = clough_raw_shape_deriv(9, 0, dofpt[3]);
00330   Real d1nd1ndeta = clough_raw_shape_deriv(9, 1, dofpt[3]);
00331   Real d1nd1ndx = d1nd1ndxi * dxidx[3] + d1nd1ndeta * detadx[3];
00332   Real d1nd1ndy = d1nd1ndxi * dxidy[3] + d1nd1ndeta * detady[3];
00333   Real d2nd2ndxi  = clough_raw_shape_deriv(10, 0, dofpt[4]);
00334   Real d2nd2ndeta = clough_raw_shape_deriv(10, 1, dofpt[4]);
00335   Real d2nd2ndx = d2nd2ndxi * dxidx[4] + d2nd2ndeta * detadx[4];
00336   Real d2nd2ndy = d2nd2ndxi * dxidy[4] + d2nd2ndeta * detady[4];
00337   Real d3nd3ndxi  = clough_raw_shape_deriv(11, 0, dofpt[5]);
00338   Real d3nd3ndeta = clough_raw_shape_deriv(11, 1, dofpt[5]);
00339   Real d3nd3ndx = d3nd3ndxi * dxidx[3] + d3nd3ndeta * detadx[3];
00340   Real d3nd3ndy = d3nd3ndxi * dxidy[3] + d3nd3ndeta * detady[3];
00341 
00342   Real d1xd1dxi   = clough_raw_shape_deriv(3, 0, dofpt[0]);
00343   Real d1xd1deta  = clough_raw_shape_deriv(3, 1, dofpt[0]);
00344   Real d1xd1dx    = d1xd1dxi * dxidx[0] + d1xd1deta * detadx[0];
00345   Real d1xd1dy    = d1xd1dxi * dxidy[0] + d1xd1deta * detady[0];
00346   Real d1yd1dxi   = clough_raw_shape_deriv(4, 0, dofpt[0]);
00347   Real d1yd1deta  = clough_raw_shape_deriv(4, 1, dofpt[0]);
00348   Real d1yd1dx    = d1yd1dxi * dxidx[0] + d1yd1deta * detadx[0];
00349   Real d1yd1dy    = d1yd1dxi * dxidy[0] + d1yd1deta * detady[0];
00350   Real d2xd2dxi   = clough_raw_shape_deriv(5, 0, dofpt[1]);
00351   Real d2xd2deta  = clough_raw_shape_deriv(5, 1, dofpt[1]);
00352   Real d2xd2dx    = d2xd2dxi * dxidx[1] + d2xd2deta * detadx[1];
00353   Real d2xd2dy    = d2xd2dxi * dxidy[1] + d2xd2deta * detady[1];
00354 
00355   //  libMesh::err << dofpt[4](0) << ' ';
00356   //  libMesh::err << dofpt[4](1) << ' ';
00357   //  libMesh::err << (int)subtriangle_lookup(dofpt[5]) << ' ';
00358   //  libMesh::err << dxdxi[4] << ' ';
00359   //  libMesh::err << dxdeta[4] << ' ';
00360   //  libMesh::err << dydxi[4] << ' ';
00361   //  libMesh::err << dydeta[4] << ' ';
00362   //  libMesh::err << dxidx[4] << ' ';
00363   //  libMesh::err << dxidy[4] << ' ';
00364   //  libMesh::err << detadx[4] << ' ';
00365   //  libMesh::err << detady[4] << ' ';
00366   //  libMesh::err << N1x << ' ';
00367   //  libMesh::err << N1y << ' ';
00368   //  libMesh::err << d2yd1ndxi << ' ';
00369   //  libMesh::err << d2yd1ndeta << ' ';
00370   //  libMesh::err << d2yd1ndx << ' ';
00371   //  libMesh::err << d2yd1ndy << std::endl;
00372 
00373   Real d2yd2dxi   = clough_raw_shape_deriv(6, 0, dofpt[1]);
00374   Real d2yd2deta  = clough_raw_shape_deriv(6, 1, dofpt[1]);
00375   Real d2yd2dx    = d2yd2dxi * dxidx[1] + d2yd2deta * detadx[1];
00376   Real d2yd2dy    = d2yd2dxi * dxidy[1] + d2yd2deta * detady[1];
00377   Real d3xd3dxi   = clough_raw_shape_deriv(7, 0, dofpt[2]);
00378   Real d3xd3deta  = clough_raw_shape_deriv(7, 1, dofpt[2]);
00379   Real d3xd3dx    = d3xd3dxi * dxidx[1] + d3xd3deta * detadx[1];
00380   Real d3xd3dy    = d3xd3dxi * dxidy[1] + d3xd3deta * detady[1];
00381   Real d3yd3dxi   = clough_raw_shape_deriv(8, 0, dofpt[2]);
00382   Real d3yd3deta  = clough_raw_shape_deriv(8, 1, dofpt[2]);
00383   Real d3yd3dx    = d3yd3dxi * dxidx[1] + d3yd3deta * detadx[1];
00384   Real d3yd3dy    = d3yd3dxi * dxidy[1] + d3yd3deta * detady[1];
00385 
00386   // Calculate normal derivatives
00387 
00388   Real d1nd1ndn = d1nd1ndx * N1x + d1nd1ndy * N1y;
00389   Real d1xd2ndn = d1xd2ndx * N2x + d1xd2ndy * N2y;
00390   Real d1xd3ndn = d1xd3ndx * N3x + d1xd3ndy * N3y;
00391   Real d1yd2ndn = d1yd2ndx * N2x + d1yd2ndy * N2y;
00392   Real d1yd3ndn = d1yd3ndx * N3x + d1yd3ndy * N3y;
00393 
00394   Real d2nd2ndn = d2nd2ndx * N2x + d2nd2ndy * N2y;
00395   Real d2xd3ndn = d2xd3ndx * N3x + d2xd3ndy * N3y;
00396   Real d2xd1ndn = d2xd1ndx * N1x + d2xd1ndy * N1y;
00397   Real d2yd3ndn = d2yd3ndx * N3x + d2yd3ndy * N3y;
00398   Real d2yd1ndn = d2yd1ndx * N1x + d2yd1ndy * N1y;
00399 
00400   Real d3nd3ndn = d3nd3ndx * N3x + d3nd3ndy * N3y;
00401   Real d3xd1ndn = d3xd1ndx * N1x + d3xd1ndy * N1y;
00402   Real d3xd2ndn = d3xd2ndx * N2x + d3xd2ndy * N2y;
00403   Real d3yd1ndn = d3yd1ndx * N1x + d3yd1ndy * N1y;
00404   Real d3yd2ndn = d3yd2ndx * N2x + d3yd2ndy * N2y;
00405 
00406   // Calculate midpoint scaling factors
00407 
00408   d1nd1n = 1. / d1nd1ndn;
00409   d2nd2n = 1. / d2nd2ndn;
00410   d3nd3n = 1. / d3nd3ndn;
00411 
00412   // Calculate midpoint derivative adjustments to nodal value
00413   // interpolant functions
00414 
00415   d1d2n = -(d1d2ndx * N2x + d1d2ndy * N2y) / d2nd2ndn;
00416   d1d3n = -(d1d3ndx * N3x + d1d3ndy * N3y) / d3nd3ndn;
00417   d2d3n = -(d2d3ndx * N3x + d2d3ndy * N3y) / d3nd3ndn;
00418   d2d1n = -(d2d1ndx * N1x + d2d1ndy * N1y) / d1nd1ndn;
00419   d3d1n = -(d3d1ndx * N1x + d3d1ndy * N1y) / d1nd1ndn;
00420   d3d2n = -(d3d2ndx * N2x + d3d2ndy * N2y) / d2nd2ndn;
00421 
00422   // Calculate nodal derivative scaling factors
00423 
00424   d1xd1x = 1. / (d1xd1dx - d1xd1dy * d1yd1dx / d1yd1dy);
00425   d1xd1y = 1. / (d1yd1dx - d1xd1dx * d1yd1dy / d1xd1dy);
00426   //  d1xd1y = - d1xd1x * (d1xd1dy / d1yd1dy);
00427   d1yd1y = 1. / (d1yd1dy - d1yd1dx * d1xd1dy / d1xd1dx);
00428   d1yd1x = 1. / (d1xd1dy - d1yd1dy * d1xd1dx / d1yd1dx);
00429   //  d1yd1x = - d1yd1y * (d1yd1dx / d1xd1dx);
00430   d2xd2x = 1. / (d2xd2dx - d2xd2dy * d2yd2dx / d2yd2dy);
00431   d2xd2y = 1. / (d2yd2dx - d2xd2dx * d2yd2dy / d2xd2dy);
00432   //  d2xd2y = - d2xd2x * (d2xd2dy / d2yd2dy);
00433   d2yd2y = 1. / (d2yd2dy - d2yd2dx * d2xd2dy / d2xd2dx);
00434   d2yd2x = 1. / (d2xd2dy - d2yd2dy * d2xd2dx / d2yd2dx);
00435   //  d2yd2x = - d2yd2y * (d2yd2dx / d2xd2dx);
00436   d3xd3x = 1. / (d3xd3dx - d3xd3dy * d3yd3dx / d3yd3dy);
00437   d3xd3y = 1. / (d3yd3dx - d3xd3dx * d3yd3dy / d3xd3dy);
00438   //  d3xd3y = - d3xd3x * (d3xd3dy / d3yd3dy);
00439   d3yd3y = 1. / (d3yd3dy - d3yd3dx * d3xd3dy / d3xd3dx);
00440   d3yd3x = 1. / (d3xd3dy - d3yd3dy * d3xd3dx / d3yd3dx);
00441   //  d3yd3x = - d3yd3y * (d3yd3dx / d3xd3dx);
00442 
00443   //  libMesh::err << d1xd1dx << ' ';
00444   //  libMesh::err << d1xd1dy << ' ';
00445   //  libMesh::err << d1yd1dx << ' ';
00446   //  libMesh::err << d1yd1dy << ' ';
00447   //  libMesh::err << d2xd2dx << ' ';
00448   //  libMesh::err << d2xd2dy << ' ';
00449   //  libMesh::err << d2yd2dx << ' ';
00450   //  libMesh::err << d2yd2dy << ' ';
00451   //  libMesh::err << d3xd3dx << ' ';
00452   //  libMesh::err << d3xd3dy << ' ';
00453   //  libMesh::err << d3yd3dx << ' ';
00454   //  libMesh::err << d3yd3dy << std::endl;
00455 
00456   // Calculate midpoint derivative adjustments to nodal derivative
00457   // interpolant functions
00458 
00459   d1xd2n = -(d1xd1x * d1xd2ndn + d1xd1y * d1yd2ndn) / d2nd2ndn;
00460   d1yd2n = -(d1yd1y * d1yd2ndn + d1yd1x * d1xd2ndn) / d2nd2ndn;
00461   d1xd3n = -(d1xd1x * d1xd3ndn + d1xd1y * d1yd3ndn) / d3nd3ndn;
00462   d1yd3n = -(d1yd1y * d1yd3ndn + d1yd1x * d1xd3ndn) / d3nd3ndn;
00463   d2xd3n = -(d2xd2x * d2xd3ndn + d2xd2y * d2yd3ndn) / d3nd3ndn;
00464   d2yd3n = -(d2yd2y * d2yd3ndn + d2yd2x * d2xd3ndn) / d3nd3ndn;
00465   d2xd1n = -(d2xd2x * d2xd1ndn + d2xd2y * d2yd1ndn) / d1nd1ndn;
00466   d2yd1n = -(d2yd2y * d2yd1ndn + d2yd2x * d2xd1ndn) / d1nd1ndn;
00467   d3xd1n = -(d3xd3x * d3xd1ndn + d3xd3y * d3yd1ndn) / d1nd1ndn;
00468   d3yd1n = -(d3yd3y * d3yd1ndn + d3yd3x * d3xd1ndn) / d1nd1ndn;
00469   d3xd2n = -(d3xd3x * d3xd2ndn + d3xd3y * d3yd2ndn) / d2nd2ndn;
00470   d3yd2n = -(d3yd3y * d3yd2ndn + d3yd3x * d3xd2ndn) / d2nd2ndn;
00471 
00472   // Cross your fingers
00473   //  libMesh::err << d1nd1ndn << ' ';
00474   //  libMesh::err << d2xd1ndn << ' ';
00475   //  libMesh::err << d2yd1ndn << ' ';
00476   //  libMesh::err << std::endl;
00477 
00478   //  libMesh::err << "Transform variables: ";
00479   //  libMesh::err << d1nd1n << ' ';
00480   //  libMesh::err << d2nd2n << ' ';
00481   //  libMesh::err << d3nd3n << ' ';
00482   //  libMesh::err << d1d2n << ' ';
00483   //  libMesh::err << d1d3n << ' ';
00484   //  libMesh::err << d2d3n << ' ';
00485   //  libMesh::err << d2d1n << ' ';
00486   //  libMesh::err << d3d1n << ' ';
00487   //  libMesh::err << d3d2n << std::endl;
00488   //  libMesh::err << d1xd1x << ' ';
00489   //  libMesh::err << d1xd1y << ' ';
00490   //  libMesh::err << d1yd1x << ' ';
00491   //  libMesh::err << d1yd1y << ' ';
00492   //  libMesh::err << d2xd2x << ' ';
00493   //  libMesh::err << d2xd2y << ' ';
00494   //  libMesh::err << d2yd2x << ' ';
00495   //  libMesh::err << d2yd2y << ' ';
00496   //  libMesh::err << d3xd3x << ' ';
00497   //  libMesh::err << d3xd3y << ' ';
00498   //  libMesh::err << d3yd3x << ' ';
00499   //  libMesh::err << d3yd3y << std::endl;
00500   //  libMesh::err << d1xd2n << ' ';
00501   //  libMesh::err << d1yd2n << ' ';
00502   //  libMesh::err << d1xd3n << ' ';
00503   //  libMesh::err << d1yd3n << ' ';
00504   //  libMesh::err << d2xd3n << ' ';
00505   //  libMesh::err << d2yd3n << ' ';
00506   //  libMesh::err << d2xd1n << ' ';
00507   //  libMesh::err << d2yd1n << ' ';
00508   //  libMesh::err << d3xd1n << ' ';
00509   //  libMesh::err << d3yd1n << ' ';
00510   //  libMesh::err << d3xd2n << ' ';
00511   //  libMesh::err << d3yd2n << ' ';
00512   //  libMesh::err << std::endl;
00513   //  libMesh::err << std::endl;
00514 }
00515 
00516 
00517 unsigned char subtriangle_lookup(const Point& p)
00518 {
00519   if ((p(0) >= p(1)) && (p(0) + 2 * p(1) <= 1))
00520     return 0;
00521   if ((p(0) <= p(1)) && (p(1) + 2 * p(0) <= 1))
00522     return 2;
00523   return 1;
00524 }
00525 
00526 // Return shape function second derivatives on the unit right
00527 // triangle
00528 Real clough_raw_shape_second_deriv(const unsigned int basis_num,
00529                                    const unsigned int deriv_type,
00530                                    const Point& p)
00531 {
00532   Real xi = p(0), eta = p(1);
00533 
00534   switch (deriv_type)
00535     {
00536 
00537       // second derivative in xi-xi direction
00538     case 0:
00539       switch (basis_num)
00540         {
00541         case 0:
00542           switch (subtriangle_lookup(p))
00543             {
00544             case 0:
00545               return -6 + 12*xi;
00546             case 1:
00547               return -30 + 42*xi + 42*eta;
00548             case 2:
00549               return -6 + 18*xi - 6*eta;
00550 
00551             default:
00552               libmesh_error_msg("Invalid subtriangle lookup = " <<
00553                                 subtriangle_lookup(p));
00554             }
00555         case 1:
00556           switch (subtriangle_lookup(p))
00557             {
00558             case 0:
00559               return 6 - 12*xi;
00560             case 1:
00561               return 18 - 27*xi - 21*eta;
00562             case 2:
00563               return 6 - 15*xi + 3*eta;
00564 
00565             default:
00566               libmesh_error_msg("Invalid subtriangle lookup = " <<
00567                                 subtriangle_lookup(p));
00568             }
00569         case 2:
00570           switch (subtriangle_lookup(p))
00571             {
00572             case 0:
00573               return 0;
00574             case 1:
00575               return 12 - 15*xi - 21*eta;
00576             case 2:
00577               return -3*xi + 3*eta;
00578 
00579             default:
00580               libmesh_error_msg("Invalid subtriangle lookup = " <<
00581                                 subtriangle_lookup(p));
00582             }
00583         case 3:
00584           switch (subtriangle_lookup(p))
00585             {
00586             case 0:
00587               return -4 + 6*xi;
00588             case 1:
00589               return -9 + 13*xi + 8*eta;
00590             case 2:
00591               return -1 - 7*xi + 4*eta;
00592 
00593             default:
00594               libmesh_error_msg("Invalid subtriangle lookup = " <<
00595                                 subtriangle_lookup(p));
00596             }
00597         case 4:
00598           switch (subtriangle_lookup(p))
00599             {
00600             case 0:
00601               return 4*eta;
00602             case 1:
00603               return 1 - 2*xi + 3*eta;
00604             case 2:
00605               return -3 + 14*xi - eta;
00606 
00607             default:
00608               libmesh_error_msg("Invalid subtriangle lookup = " <<
00609                                 subtriangle_lookup(p));
00610             }
00611         case 5:
00612           switch (subtriangle_lookup(p))
00613             {
00614             case 0:
00615               return -2 + 6*xi;
00616             case 1:
00617               return -4 + 17./2.*xi + 7./2.*eta;
00618             case 2:
00619               return -2 + 13./2.*xi - 1./2.*eta;
00620 
00621             default:
00622               libmesh_error_msg("Invalid subtriangle lookup = " <<
00623                                 subtriangle_lookup(p));
00624             }
00625         case 6:
00626           switch (subtriangle_lookup(p))
00627             {
00628             case 0:
00629               return 4*eta;
00630             case 1:
00631               return 9 - 23./2.*xi - 23./2.*eta;
00632             case 2:
00633               return -1 + 5./2.*xi + 9./2.*eta;
00634 
00635             default:
00636               libmesh_error_msg("Invalid subtriangle lookup = " <<
00637                                 subtriangle_lookup(p));
00638             }
00639         case 7:
00640           switch (subtriangle_lookup(p))
00641             {
00642             case 0:
00643               return 0;
00644             case 1:
00645               return 7 - 17./2.*xi - 25./2.*eta;
00646             case 2:
00647               return 1 - 13./2.*xi + 7./2.*eta;
00648 
00649             default:
00650               libmesh_error_msg("Invalid subtriangle lookup = " <<
00651                                 subtriangle_lookup(p));
00652             }
00653         case 8:
00654           switch (subtriangle_lookup(p))
00655             {
00656             case 0:
00657               return 0;
00658             case 1:
00659               return -2 + 5./2.*xi + 7./2.*eta;
00660             case 2:
00661               return 1./2.*xi - 1./2.*eta;
00662 
00663             default:
00664               libmesh_error_msg("Invalid subtriangle lookup = " <<
00665                                 subtriangle_lookup(p));
00666             }
00667         case 9:
00668           switch (subtriangle_lookup(p))
00669             {
00670             case 0:
00671               return 0;
00672             case 1:
00673               return std::sqrt(2.) * (8 - 10*xi - 14*eta);
00674             case 2:
00675               return std::sqrt(2.) * (-2*xi + 2*eta);
00676 
00677             default:
00678               libmesh_error_msg("Invalid subtriangle lookup = " <<
00679                                 subtriangle_lookup(p));
00680             }
00681         case 10:
00682           switch (subtriangle_lookup(p))
00683             {
00684             case 0:
00685               return 0;
00686             case 1:
00687               return -4 + 4*xi + 8*eta;
00688             case 2:
00689               return -4 + 20*xi - 8*eta;
00690 
00691             default:
00692               libmesh_error_msg("Invalid subtriangle lookup = " <<
00693                                 subtriangle_lookup(p));
00694             }
00695         case 11:
00696           switch (subtriangle_lookup(p))
00697             {
00698             case 0:
00699               return -8*eta;
00700             case 1:
00701               return -12 + 16*xi + 12*eta;
00702             case 2:
00703               return 4 - 16*xi - 4*eta;
00704 
00705             default:
00706               libmesh_error_msg("Invalid subtriangle lookup = " <<
00707                                 subtriangle_lookup(p));
00708             }
00709 
00710         default:
00711           libmesh_error_msg("Invalid shape function index i = " <<
00712                             basis_num);
00713         }
00714 
00715       // second derivative in xi-eta direction
00716     case 1:
00717       switch (basis_num)
00718         {
00719         case 0:
00720           switch (subtriangle_lookup(p))
00721             {
00722             case 0:
00723               return -6*eta;
00724             case 1:
00725               return -30 +42*xi
00726                 + 42*eta;
00727             case 2:
00728               return -6*xi;
00729 
00730             default:
00731               libmesh_error_msg("Invalid subtriangle lookup = " <<
00732                                 subtriangle_lookup(p));
00733             }
00734         case 1:
00735           switch (subtriangle_lookup(p))
00736             {
00737             case 0:
00738               return + 3*eta;
00739             case 1:
00740               return 15 - 21*xi - 21*eta;
00741             case 2:
00742               return 3*xi;
00743 
00744             default:
00745               libmesh_error_msg("Invalid subtriangle lookup = " <<
00746                                 subtriangle_lookup(p));
00747             }
00748         case 2:
00749           switch (subtriangle_lookup(p))
00750             {
00751             case 0:
00752               return 3*eta;
00753             case 1:
00754               return 15 - 21*xi - 21*eta;
00755             case 2:
00756               return 3*xi;
00757 
00758             default:
00759               libmesh_error_msg("Invalid subtriangle lookup = " <<
00760                                 subtriangle_lookup(p));
00761             }
00762         case 3:
00763           switch (subtriangle_lookup(p))
00764             {
00765             case 0:
00766               return -eta;
00767             case 1:
00768               return -4 + 8*xi + 3*eta;
00769             case 2:
00770               return -3 + 4*xi + 4*eta;
00771 
00772             default:
00773               libmesh_error_msg("Invalid subtriangle lookup = " <<
00774                                 subtriangle_lookup(p));
00775             }
00776         case 4:
00777           switch (subtriangle_lookup(p))
00778             {
00779             case 0:
00780               return -3 + 4*xi + 4*eta;
00781             case 1:
00782               return - 4 + 3*xi + 8*eta;
00783             case 2:
00784               return -xi;
00785 
00786             default:
00787               libmesh_error_msg("Invalid subtriangle lookup = " <<
00788                                 subtriangle_lookup(p));
00789             }
00790         case 5:
00791           switch (subtriangle_lookup(p))
00792             {
00793             case 0:
00794               return - 1./2.*eta;
00795             case 1:
00796               return -5./2. + 7./2.*xi + 7./2.*eta;
00797             case 2:
00798               return - 1./2.*xi;
00799 
00800             default:
00801               libmesh_error_msg("Invalid subtriangle lookup = " <<
00802                                 subtriangle_lookup(p));
00803             }
00804         case 6:
00805           switch (subtriangle_lookup(p))
00806             {
00807             case 0:
00808               return -1 + 4*xi + 7./2.*eta;
00809             case 1:
00810               return 19./2. - 23./2.*xi - 25./2.*eta;
00811             case 2:
00812               return 9./2.*xi;
00813 
00814             default:
00815               libmesh_error_msg("Invalid subtriangle lookup = " <<
00816                                 subtriangle_lookup(p));
00817             }
00818         case 7:
00819           switch (subtriangle_lookup(p))
00820             {
00821             case 0:
00822               return 9./2.*eta;
00823             case 1:
00824               return 19./2. - 25./2.*xi - 23./2.*eta;
00825             case 2:
00826               return -1 + 7./2.*xi + 4*eta;
00827 
00828             default:
00829               libmesh_error_msg("Invalid subtriangle lookup = " <<
00830                                 subtriangle_lookup(p));
00831             }
00832         case 8:
00833           switch (subtriangle_lookup(p))
00834             {
00835             case 0:
00836               return -1./2.*eta;
00837             case 1:
00838               return -5./2. + 7./2.*xi + 7./2.*eta;
00839             case 2:
00840               return -1./2.*xi;
00841 
00842             default:
00843               libmesh_error_msg("Invalid subtriangle lookup = " <<
00844                                 subtriangle_lookup(p));
00845             }
00846         case 9:
00847           switch (subtriangle_lookup(p))
00848             {
00849             case 0:
00850               return std::sqrt(2.) * (2*eta);
00851             case 1:
00852               return std::sqrt(2.) * (10 - 14*xi - 14*eta);
00853             case 2:
00854               return std::sqrt(2.) * (2*xi);
00855 
00856             default:
00857               libmesh_error_msg("Invalid subtriangle lookup = " <<
00858                                 subtriangle_lookup(p));
00859             }
00860         case 10:
00861           switch (subtriangle_lookup(p))
00862             {
00863             case 0:
00864               return -4*eta;
00865             case 1:
00866               return - 8 + 8*xi + 12*eta;
00867             case 2:
00868               return 4 - 8*xi - 8*eta;
00869 
00870             default:
00871               libmesh_error_msg("Invalid subtriangle lookup = " <<
00872                                 subtriangle_lookup(p));
00873             }
00874         case 11:
00875           switch (subtriangle_lookup(p))
00876             {
00877             case 0:
00878               return 4 - 8*xi - 8*eta;
00879             case 1:
00880               return -8 + 12*xi + 8*eta;
00881             case 2:
00882               return -4*xi;
00883 
00884             default:
00885               libmesh_error_msg("Invalid subtriangle lookup = " <<
00886                                 subtriangle_lookup(p));
00887             }
00888 
00889         default:
00890           libmesh_error_msg("Invalid shape function index i = " <<
00891                             basis_num);
00892         }
00893 
00894       // second derivative in eta-eta direction
00895     case 2:
00896       switch (basis_num)
00897         {
00898         case 0:
00899           switch (subtriangle_lookup(p))
00900             {
00901             case 0:
00902               return -6 - 6*xi + 18*eta;
00903             case 1:
00904               return -30 + 42*xi + 42*eta;
00905             case 2:
00906               return -6 + 12*eta;
00907 
00908             default:
00909               libmesh_error_msg("Invalid subtriangle lookup = " <<
00910                                 subtriangle_lookup(p));
00911             }
00912         case 1:
00913           switch (subtriangle_lookup(p))
00914             {
00915             case 0:
00916               return 3*xi - 3*eta;
00917             case 1:
00918               return 12 - 21*xi - 15*eta;
00919             case 2:
00920               return 0;
00921 
00922             default:
00923               libmesh_error_msg("Invalid subtriangle lookup = " <<
00924                                 subtriangle_lookup(p));
00925             }
00926         case 2:
00927           switch (subtriangle_lookup(p))
00928             {
00929             case 0:
00930               return 6 + 3*xi - 15*eta;
00931             case 1:
00932               return 18 - 21.*xi - 27*eta;
00933             case 2:
00934               return 6 - 12*eta;
00935 
00936             default:
00937               libmesh_error_msg("Invalid subtriangle lookup = " <<
00938                                 subtriangle_lookup(p));
00939             }
00940         case 3:
00941           switch (subtriangle_lookup(p))
00942             {
00943             case 0:
00944               return -3 - xi + 14*eta;
00945             case 1:
00946               return 1 + 3*xi - 2*eta;
00947             case 2:
00948               return 4*xi;
00949 
00950             default:
00951               libmesh_error_msg("Invalid subtriangle lookup = " <<
00952                                 subtriangle_lookup(p));
00953             }
00954         case 4:
00955           switch (subtriangle_lookup(p))
00956             {
00957             case 0:
00958               return -1 + 4*xi - 7*eta;
00959             case 1:
00960               return -9 + 8*xi + 13*eta;
00961             case 2:
00962               return -4 + 6*eta;
00963 
00964             default:
00965               libmesh_error_msg("Invalid subtriangle lookup = " <<
00966                                 subtriangle_lookup(p));
00967             }
00968         case 5:
00969           switch (subtriangle_lookup(p))
00970             {
00971             case 0:
00972               return - 1./2.*xi + 1./2.*eta;
00973             case 1:
00974               return -2 + 7./2.*xi + 5./2.*eta;
00975             case 2:
00976               return 0;
00977 
00978             default:
00979               libmesh_error_msg("Invalid subtriangle lookup = " <<
00980                                 subtriangle_lookup(p));
00981             }
00982         case 6:
00983           switch (subtriangle_lookup(p))
00984             {
00985             case 0:
00986               return 1 + 7./2.*xi - 13./2.*eta;
00987             case 1:
00988               return 7 - 25./2.*xi - 17./2.*eta;
00989             case 2:
00990               return 0;
00991 
00992             default:
00993               libmesh_error_msg("Invalid subtriangle lookup = " <<
00994                                 subtriangle_lookup(p));
00995             }
00996         case 7:
00997           switch (subtriangle_lookup(p))
00998             {
00999             case 0:
01000               return -1 + 9./2.*xi + 5./2.*eta;
01001             case 1:
01002               return 9 - 23./2.*xi - 23./2.*eta;
01003             case 2:
01004               return 4*xi;
01005 
01006             default:
01007               libmesh_error_msg("Invalid subtriangle lookup = " <<
01008                                 subtriangle_lookup(p));
01009             }
01010         case 8:
01011           switch (subtriangle_lookup(p))
01012             {
01013             case 0:
01014               return -2 - 1./2.*xi + 13./2.*eta;
01015             case 1:
01016               return -4 + 7./2.*xi + 17./2.*eta;
01017             case 2:
01018               return -2 + 6*eta;
01019 
01020             default:
01021               libmesh_error_msg("Invalid subtriangle lookup = " <<
01022                                 subtriangle_lookup(p));
01023             }
01024         case 9:
01025           switch (subtriangle_lookup(p))
01026             {
01027             case 0:
01028               return std::sqrt(2.) * (2*xi - 2*eta);
01029             case 1:
01030               return std::sqrt(2.) * (8 - 14*xi - 10*eta);
01031             case 2:
01032               return 0;
01033 
01034             default:
01035               libmesh_error_msg("Invalid subtriangle lookup = " <<
01036                                 subtriangle_lookup(p));
01037             }
01038         case 10:
01039           switch (subtriangle_lookup(p))
01040             {
01041             case 0:
01042               return 4 - 4*xi - 16*eta;
01043             case 1:
01044               return -12 + 12*xi + 16*eta;
01045             case 2:
01046               return -8*xi;
01047 
01048             default:
01049               libmesh_error_msg("Invalid subtriangle lookup = " <<
01050                                 subtriangle_lookup(p));
01051             }
01052         case 11:
01053           switch (subtriangle_lookup(p))
01054             {
01055             case 0:
01056               return -4 - 8*xi + 20*eta;
01057             case 1:
01058               return -4 + 8*xi + 4*eta;
01059             case 2:
01060               return 0;
01061 
01062             default:
01063               libmesh_error_msg("Invalid subtriangle lookup = " <<
01064                                 subtriangle_lookup(p));
01065             }
01066 
01067         default:
01068           libmesh_error_msg("Invalid shape function index i = " <<
01069                             basis_num);
01070         }
01071 
01072     default:
01073       libmesh_error_msg("Invalid shape function derivative j = " <<
01074                         deriv_type);
01075     }
01076 
01077   libmesh_error_msg("We'll never get here!");
01078   return 0.;
01079 }
01080 
01081 
01082 
01083 Real clough_raw_shape_deriv(const unsigned int basis_num,
01084                             const unsigned int deriv_type,
01085                             const Point& p)
01086 {
01087   Real xi = p(0), eta = p(1);
01088 
01089   switch (deriv_type)
01090     {
01091       // derivative in xi direction
01092     case 0:
01093       switch (basis_num)
01094         {
01095         case 0:
01096           switch (subtriangle_lookup(p))
01097             {
01098             case 0:
01099               return -6*xi + 6*xi*xi
01100                 - 3*eta*eta;
01101             case 1:
01102               return 9 - 30*xi + 21*xi*xi
01103                 - 30*eta + 42*xi*eta
01104                 + 21*eta*eta;
01105             case 2:
01106               return -6*xi + 9*xi*xi
01107                 - 6*xi*eta;
01108 
01109             default:
01110               libmesh_error_msg("Invalid subtriangle lookup = " <<
01111                                 subtriangle_lookup(p));
01112             }
01113         case 1:
01114           switch (subtriangle_lookup(p))
01115             {
01116             case 0:
01117               return 6*xi - 6*xi*xi
01118                 + 3./2.*eta*eta;
01119             case 1:
01120               return - 9./2. + 18*xi - 27./2.*xi*xi
01121                 + 15*eta - 21*xi*eta
01122                 - 21./2.*eta*eta;
01123             case 2:
01124               return 6*xi - 15./2.*xi*xi
01125                 + 3*xi*eta;
01126 
01127             default:
01128               libmesh_error_msg("Invalid subtriangle lookup = " <<
01129                                 subtriangle_lookup(p));
01130             }
01131         case 2:
01132           switch (subtriangle_lookup(p))
01133             {
01134             case 0:
01135               return 3./2.*eta*eta;
01136             case 1:
01137               return - 9./2. + 12*xi - 15./2.*xi*xi
01138                 + 15*eta - 21*xi*eta
01139                 - 21./2.*eta*eta;
01140             case 2:
01141               return -3./2.*xi*xi
01142                 + 3*xi*eta;
01143 
01144             default:
01145               libmesh_error_msg("Invalid subtriangle lookup = " <<
01146                                 subtriangle_lookup(p));
01147             }
01148         case 3:
01149           switch (subtriangle_lookup(p))
01150             {
01151             case 0:
01152               return 1 - 4*xi + 3*xi*xi
01153                 - 1./2.*eta*eta;
01154             case 1:
01155               return 5./2. - 9*xi + 13./2.*xi*xi
01156                 - 4*eta + 8*xi*eta
01157                 + 3./2.*eta*eta;
01158             case 2:
01159               return 1 - xi - 7./2.*xi*xi
01160                 - 3*eta + 4*xi*eta
01161                 + 2*eta*eta;
01162 
01163             default:
01164               libmesh_error_msg("Invalid subtriangle lookup = " <<
01165                                 subtriangle_lookup(p));
01166             }
01167         case 4:
01168           switch (subtriangle_lookup(p))
01169             {
01170             case 0:
01171               return - 3*eta + 4*xi*eta
01172                 + 2*eta*eta;
01173             case 1:
01174               return xi - xi*xi
01175                 - 4*eta + 3*xi*eta
01176                 + 4*eta*eta;
01177             case 2:
01178               return -3*xi + 7*xi*xi
01179                 - xi*eta;
01180 
01181             default:
01182               libmesh_error_msg("Invalid subtriangle lookup = " <<
01183                                 subtriangle_lookup(p));
01184             }
01185         case 5:
01186           switch (subtriangle_lookup(p))
01187             {
01188             case 0:
01189               return -2*xi + 3*xi*xi
01190                 - 1./4.*eta*eta;
01191             case 1:
01192               return 3./4. - 4*xi + 17./4.*xi*xi
01193                 - 5./2.*eta + 7./2.*xi*eta
01194                 + 7./4.*eta*eta;
01195             case 2:
01196               return -2*xi + 13./4.*xi*xi
01197                 - 1./2.*xi*eta;
01198 
01199             default:
01200               libmesh_error_msg("Invalid subtriangle lookup = " <<
01201                                 subtriangle_lookup(p));
01202             }
01203         case 6:
01204           switch (subtriangle_lookup(p))
01205             {
01206             case 0:
01207               return -eta + 4*xi*eta
01208                 + 7./4.*eta*eta;
01209             case 1:
01210               return -13./4. + 9*xi - 23./4.*xi*xi
01211                 + 19./2.*eta - 23./2.*xi*eta
01212                 - 25./4.*eta*eta;
01213             case 2:
01214               return -xi + 5./4.*xi*xi
01215                 + 9./2.*xi*eta;
01216 
01217             default:
01218               libmesh_error_msg("Invalid subtriangle lookup = " <<
01219                                 subtriangle_lookup(p));
01220             }
01221         case 7:
01222           switch (subtriangle_lookup(p))
01223             {
01224             case 0:
01225               return 9./4.*eta*eta;
01226             case 1:
01227               return - 11./4. + 7*xi - 17./4.*xi*xi
01228                 + 19./2.*eta - 25./2.*xi*eta
01229                 - 23./4.*eta*eta;
01230             case 2:
01231               return xi - 13./4.*xi*xi
01232                 - eta + 7./2.*xi*eta + 2*eta*eta;
01233 
01234             default:
01235               libmesh_error_msg("Invalid subtriangle lookup = " <<
01236                                 subtriangle_lookup(p));
01237             }
01238         case 8:
01239           switch (subtriangle_lookup(p))
01240             {
01241             case 0:
01242               return - 1./4.*eta*eta;
01243             case 1:
01244               return 3./4. - 2*xi + 5./4.*xi*xi
01245                 - 5./2.*eta + 7./2.*xi*eta
01246                 + 7./4.*eta*eta;
01247             case 2:
01248               return 1./4.*xi*xi
01249                 - 1./2.*xi*eta;
01250 
01251             default:
01252               libmesh_error_msg("Invalid subtriangle lookup = " <<
01253                                 subtriangle_lookup(p));
01254             }
01255         case 9:
01256           switch (subtriangle_lookup(p))
01257             {
01258             case 0:
01259               return std::sqrt(2.) * eta*eta;
01260             case 1:
01261               return std::sqrt(2.) * (-3 + 8*xi - 5*xi*xi
01262                                       + 10*eta - 14*xi*eta
01263                                       - 7*eta*eta);
01264             case 2:
01265               return std::sqrt(2.) * (-xi*xi + 2*xi*eta);
01266 
01267             default:
01268               libmesh_error_msg("Invalid subtriangle lookup = " <<
01269                                 subtriangle_lookup(p));
01270             }
01271         case 10:
01272           switch (subtriangle_lookup(p))
01273             {
01274             case 0:
01275               return -2*eta*eta;
01276             case 1:
01277               return 2 - 4*xi + 2*xi*xi
01278                 - 8*eta + 8*xi*eta
01279                 + 6*eta*eta;
01280             case 2:
01281               return -4*xi + 10*xi*xi
01282                 + 4*eta - 8*xi*eta
01283                 - 4*eta*eta;
01284 
01285             default:
01286               libmesh_error_msg("Invalid subtriangle lookup = " <<
01287                                 subtriangle_lookup(p));
01288             }
01289         case 11:
01290           switch (subtriangle_lookup(p))
01291             {
01292             case 0:
01293               return 4*eta - 8*xi*eta
01294                 - 4*eta*eta;
01295             case 1:
01296               return 4 - 12*xi + 8*xi*xi
01297                 - 8*eta + 12*xi*eta
01298                 + 4*eta*eta;
01299             case 2:
01300               return 4*xi - 8*xi*xi
01301                 - 4*xi*eta;
01302 
01303             default:
01304               libmesh_error_msg("Invalid subtriangle lookup = " <<
01305                                 subtriangle_lookup(p));
01306             }
01307 
01308         default:
01309           libmesh_error_msg("Invalid shape function index i = " <<
01310                             basis_num);
01311         }
01312 
01313       // derivative in eta direction
01314     case 1:
01315       switch (basis_num)
01316         {
01317         case 0:
01318           switch (subtriangle_lookup(p))
01319             {
01320             case 0:
01321               return - 6*eta - 6*xi*eta + 9*eta*eta;
01322             case 1:
01323               return 9 - 30*xi + 21*xi*xi
01324                 - 30*eta + 42*xi*eta + 21*eta*eta;
01325             case 2:
01326               return - 3*xi*xi
01327                 - 6*eta + 6*eta*eta;
01328 
01329             default:
01330               libmesh_error_msg("Invalid subtriangle lookup = " <<
01331                                 subtriangle_lookup(p));
01332             }
01333         case 1:
01334           switch (subtriangle_lookup(p))
01335             {
01336             case 0:
01337               return + 3*xi*eta
01338                 - 3./2.*eta*eta;
01339             case 1:
01340               return - 9./2. + 15*xi - 21./2.*xi*xi
01341                 + 12*eta - 21*xi*eta - 15./2.*eta*eta;
01342             case 2:
01343               return + 3./2.*xi*xi;
01344 
01345             default:
01346               libmesh_error_msg("Invalid subtriangle lookup = " <<
01347                                 subtriangle_lookup(p));
01348             }
01349         case 2:
01350           switch (subtriangle_lookup(p))
01351             {
01352             case 0:
01353               return 6*eta + 3*xi*eta - 15./2.*eta*eta;
01354             case 1:
01355               return - 9./2. + 15*xi - 21./2.*xi*xi
01356                 + 18*eta - 21.*xi*eta - 27./2.*eta*eta;
01357             case 2:
01358               return 3./2.*xi*xi
01359                 + 6*eta - 6*eta*eta;
01360 
01361             default:
01362               libmesh_error_msg("Invalid subtriangle lookup = " <<
01363                                 subtriangle_lookup(p));
01364             }
01365         case 3:
01366           switch (subtriangle_lookup(p))
01367             {
01368             case 0:
01369               return - 3*eta - xi*eta + 7*eta*eta;
01370             case 1:
01371               return - 4*xi + 4*xi*xi
01372                 + eta + 3*xi*eta - eta*eta;
01373             case 2:
01374               return - 3*xi + 2*xi*xi
01375                 + 4*xi*eta;
01376 
01377             default:
01378               libmesh_error_msg("Invalid subtriangle lookup = " <<
01379                                 subtriangle_lookup(p));
01380             }
01381         case 4:
01382           switch (subtriangle_lookup(p))
01383             {
01384             case 0:
01385               return 1 - 3*xi + 2*xi*xi
01386                 - eta + 4*xi*eta - 7./2.*eta*eta;
01387             case 1:
01388               return 5./2. - 4*xi + 3./2.*xi*xi
01389                 - 9.*eta + 8*xi*eta + 13./2.*eta*eta;
01390             case 2:
01391               return 1 - 1./2.*xi*xi - 4*eta + 3*eta*eta;
01392 
01393             default:
01394               libmesh_error_msg("Invalid subtriangle lookup = " <<
01395                                 subtriangle_lookup(p));
01396             }
01397         case 5:
01398           switch (subtriangle_lookup(p))
01399             {
01400             case 0:
01401               return - 1./2.*xi*eta + 1./4.*eta*eta;
01402             case 1:
01403               return 3./4. - 5./2.*xi + 7./4.*xi*xi
01404                 - 2*eta + 7./2.*xi*eta + 5./4.*eta*eta;
01405             case 2:
01406               return - 1./4.*xi*xi;
01407 
01408             default:
01409               libmesh_error_msg("Invalid subtriangle lookup = " <<
01410                                 subtriangle_lookup(p));
01411             }
01412         case 6:
01413           switch (subtriangle_lookup(p))
01414             {
01415             case 0:
01416               return -xi + 2*xi*xi
01417                 + eta + 7./2.*xi*eta - 13./4.*eta*eta;
01418             case 1:
01419               return - 11./4. + 19./2.*xi - 23./4.*xi*xi
01420                 + 7*eta - 25./2.*xi*eta - 17./4.*eta*eta;
01421             case 2:
01422               return 9./4.*xi*xi;
01423 
01424             default:
01425               libmesh_error_msg("Invalid subtriangle lookup = " <<
01426                                 subtriangle_lookup(p));
01427             }
01428         case 7:
01429           switch (subtriangle_lookup(p))
01430             {
01431             case 0:
01432               return -eta + 9./2.*xi*eta + 5./4.*eta*eta;
01433             case 1:
01434               return - 13./4. + 19./2.*xi - 25./4.*xi*xi
01435                 + 9*eta - 23./2.*xi*eta - 23./4.*eta*eta;
01436             case 2:
01437               return - xi + 7./4.*xi*xi + 4*xi*eta;
01438 
01439             default:
01440               libmesh_error_msg("Invalid subtriangle lookup = " <<
01441                                 subtriangle_lookup(p));
01442             }
01443         case 8:
01444           switch (subtriangle_lookup(p))
01445             {
01446             case 0:
01447               return -2*eta - 1./2.*xi*eta + 13./4.*eta*eta;
01448             case 1:
01449               return 3./4. - 5./2.*xi + 7./4.*xi*xi
01450                 - 4*eta + 7./2.*xi*eta + 17./4.*eta*eta;
01451             case 2:
01452               return - 1./4.*xi*xi
01453                 - 2*eta + 3*eta*eta;
01454 
01455             default:
01456               libmesh_error_msg("Invalid subtriangle lookup = " <<
01457                                 subtriangle_lookup(p));
01458             }
01459         case 9:
01460           switch (subtriangle_lookup(p))
01461             {
01462             case 0:
01463               return std::sqrt(2.) * (2*xi*eta - eta*eta);
01464             case 1:
01465               return std::sqrt(2.) * (- 3 + 10*xi - 7*xi*xi
01466                                       + 8*eta - 14*xi*eta - 5*eta*eta);
01467             case 2:
01468               return std::sqrt(2.) * (xi*xi);
01469 
01470             default:
01471               libmesh_error_msg("Invalid subtriangle lookup = " <<
01472                                 subtriangle_lookup(p));
01473             }
01474         case 10:
01475           switch (subtriangle_lookup(p))
01476             {
01477             case 0:
01478               return 4*eta - 4*xi*eta - 8*eta*eta;
01479             case 1:
01480               return 4 - 8*xi + 4*xi*xi
01481                 - 12*eta + 12*xi*eta + 8*eta*eta;
01482             case 2:
01483               return 4*xi - 4*xi*xi
01484                 - 8*xi*eta;
01485 
01486             default:
01487               libmesh_error_msg("Invalid subtriangle lookup = " <<
01488                                 subtriangle_lookup(p));
01489             }
01490         case 11:
01491           switch (subtriangle_lookup(p))
01492             {
01493             case 0:
01494               return 4*xi - 4*xi*xi
01495                 - 4*eta - 8*xi*eta + 10.*eta*eta;
01496             case 1:
01497               return 2 - 8*xi + 6*xi*xi
01498                 - 4*eta + 8*xi*eta + 2*eta*eta;
01499             case 2:
01500               return - 2*xi*xi;
01501 
01502             default:
01503               libmesh_error_msg("Invalid subtriangle lookup = " <<
01504                                 subtriangle_lookup(p));
01505             }
01506 
01507         default:
01508           libmesh_error_msg("Invalid shape function index i = " <<
01509                             basis_num);
01510         }
01511 
01512     default:
01513       libmesh_error_msg("Invalid shape function derivative j = " <<
01514                         deriv_type);
01515     }
01516 
01517   libmesh_error_msg("We'll never get here!");
01518   return 0.;
01519 }
01520 
01521 Real clough_raw_shape(const unsigned int basis_num,
01522                       const Point& p)
01523 {
01524   Real xi = p(0), eta = p(1);
01525 
01526   switch (basis_num)
01527     {
01528     case 0:
01529       switch (subtriangle_lookup(p))
01530         {
01531         case 0:
01532           return 1 - 3*xi*xi + 2*xi*xi*xi
01533             - 3*eta*eta - 3*xi*eta*eta + 3*eta*eta*eta;
01534         case 1:
01535           return -1 + 9*xi - 15*xi*xi + 7*xi*xi*xi
01536             + 9*eta - 30*xi*eta +21*xi*xi*eta
01537             - 15*eta*eta + 21*xi*eta*eta + 7*eta*eta*eta;
01538         case 2:
01539           return 1 - 3*xi*xi + 3*xi*xi*xi
01540             - 3*xi*xi*eta
01541             - 3*eta*eta + 2*eta*eta*eta;
01542 
01543         default:
01544           libmesh_error_msg("Invalid subtriangle lookup = " <<
01545                             subtriangle_lookup(p));
01546         }
01547     case 1:
01548       switch (subtriangle_lookup(p))
01549         {
01550         case 0:
01551           return 3*xi*xi - 2*xi*xi*xi
01552             + 3./2.*xi*eta*eta
01553             - 1./2.*eta*eta*eta;
01554         case 1:
01555           return 1 - 9./2.*xi + 9*xi*xi - 9./2.*xi*xi*xi
01556             - 9./2.*eta + 15*xi*eta - 21./2.*xi*xi*eta
01557             + 6*eta*eta - 21./2.*xi*eta*eta - 5./2.*eta*eta*eta;
01558         case 2:
01559           return 3*xi*xi - 5./2.*xi*xi*xi
01560             + 3./2.*xi*xi*eta;
01561 
01562         default:
01563           libmesh_error_msg("Invalid subtriangle lookup = " <<
01564                             subtriangle_lookup(p));
01565         }
01566     case 2:
01567       switch (subtriangle_lookup(p))
01568         {
01569         case 0:
01570           return 3*eta*eta + 3./2.*xi*eta*eta - 5./2.*eta*eta*eta;
01571         case 1:
01572           return 1 - 9./2.*xi + 6*xi*xi - 5./2.*xi*xi*xi
01573             - 9./2.*eta + 15*xi*eta - 21./2.*xi*xi*eta
01574             + 9*eta*eta - 21./2.*xi*eta*eta - 9./2.*eta*eta*eta;
01575         case 2:
01576           return -1./2.*xi*xi*xi
01577             + 3./2.*xi*xi*eta
01578             + 3*eta*eta - 2*eta*eta*eta;
01579 
01580         default:
01581           libmesh_error_msg("Invalid subtriangle lookup = " <<
01582                             subtriangle_lookup(p));
01583         }
01584     case 3:
01585       switch (subtriangle_lookup(p))
01586         {
01587         case 0:
01588           return xi - 2*xi*xi + xi*xi*xi
01589             - 3./2.*eta*eta - 1./2.*xi*eta*eta + 7./3.*eta*eta*eta;
01590         case 1:
01591           return -1./6. + 5./2.*xi - 9./2.*xi*xi + 13./6.*xi*xi*xi
01592             - 4*xi*eta + 4*xi*xi*eta
01593             + 1./2.*eta*eta + 3./2.*xi*eta*eta - 1./3.*eta*eta*eta;
01594         case 2:
01595           return xi - 1./2.*xi*xi - 7./6.*xi*xi*xi
01596             - 3*xi*eta + 2*xi*xi*eta
01597             + 2*xi*eta*eta;
01598 
01599         default:
01600           libmesh_error_msg("Invalid subtriangle lookup = " <<
01601                             subtriangle_lookup(p));
01602         }
01603     case 4:
01604       switch (subtriangle_lookup(p))
01605         {
01606         case 0:
01607           return eta - 3*xi*eta + 2*xi*xi*eta
01608             - 1./2.*eta*eta + 2*xi*eta*eta - 7./6.*eta*eta*eta;
01609         case 1:
01610           return -1./6. + 1./2.*xi*xi - 1./3.*xi*xi*xi
01611             + 5./2.*eta - 4*xi*eta + 3./2.*xi*xi*eta
01612             - 9./2.*eta*eta + 4*xi*eta*eta + 13./6.*eta*eta*eta;
01613         case 2:
01614           return -3./2.*xi*xi + 7./3.*xi*xi*xi
01615             + eta - 1./2.*xi*xi*eta - 2*eta*eta + eta*eta*eta;
01616 
01617         default:
01618           libmesh_error_msg("Invalid subtriangle lookup = " <<
01619                             subtriangle_lookup(p));
01620         }
01621     case 5:
01622       switch (subtriangle_lookup(p))
01623         {
01624         case 0:
01625           return -xi*xi + xi*xi*xi
01626             - 1./4.*xi*eta*eta + 1./12.*eta*eta*eta;
01627         case 1:
01628           return -1./6. + 3./4.*xi - 2*xi*xi + 17./12.*xi*xi*xi
01629             + 3./4.*eta - 5./2.*xi*eta + 7./4.*xi*xi*eta
01630             - eta*eta + 7./4.*xi*eta*eta + 5./12.*eta*eta*eta;
01631         case 2:
01632           return -xi*xi + 13./12.*xi*xi*xi
01633             - 1./4.*xi*xi*eta;
01634 
01635         default:
01636           libmesh_error_msg("Invalid subtriangle lookup = " <<
01637                             subtriangle_lookup(p));
01638         }
01639     case 6:
01640       switch (subtriangle_lookup(p))
01641         {
01642         case 0:
01643           return -xi*eta + 2*xi*xi*eta
01644             + 1./2.*eta*eta + 7./4.*xi*eta*eta - 13./12.*eta*eta*eta;
01645         case 1:
01646           return 2./3. - 13./4.*xi + 9./2.*xi*xi - 23./12.*xi*xi*xi
01647             - 11./4.*eta + 19./2.*xi*eta - 23./4.*xi*xi*eta
01648             + 7./2.*eta*eta - 25./4.*xi*eta*eta - 17./12.*eta*eta*eta;
01649         case 2:
01650           return -1./2.*xi*xi + 5./12.*xi*xi*xi
01651             + 9./4.*xi*xi*eta;
01652 
01653         default:
01654           libmesh_error_msg("Invalid subtriangle lookup = " <<
01655                             subtriangle_lookup(p));
01656         }
01657     case 7:
01658       switch (subtriangle_lookup(p))
01659         {
01660         case 0:
01661           return -1./2.*eta*eta + 9./4.*xi*eta*eta + 5./12.*eta*eta*eta;
01662         case 1:
01663           return 2./3. - 11./4.*xi + 7./2.*xi*xi - 17./12.*xi*xi*xi
01664             - 13./4.*eta + 19./2.*xi*eta - 25./4.*xi*xi*eta
01665             + 9./2.*eta*eta - 23./4.*xi*eta*eta - 23./12.*eta*eta*eta;
01666         case 2:
01667           return 1./2.*xi*xi - 13./12.*xi*xi*xi
01668             - xi*eta + 7./4.*xi*xi*eta + 2*xi*eta*eta;
01669 
01670         default:
01671           libmesh_error_msg("Invalid subtriangle lookup = " <<
01672                             subtriangle_lookup(p));
01673         }
01674     case 8:
01675       switch (subtriangle_lookup(p))
01676         {
01677         case 0:
01678           return -eta*eta - 1./4.*xi*eta*eta + 13./12.*eta*eta*eta;
01679         case 1:
01680           return -1./6. + 3./4.*xi - xi*xi + 5./12.*xi*xi*xi
01681             + 3./4.*eta - 5./2.*xi*eta + 7./4.*xi*xi*eta
01682             - 2*eta*eta + 7./4.*xi*eta*eta + 17./12.*eta*eta*eta;
01683         case 2:
01684           return 1./12.*xi*xi*xi
01685             - 1./4.*xi*xi*eta
01686             - eta*eta + eta*eta*eta;
01687 
01688         default:
01689           libmesh_error_msg("Invalid subtriangle lookup = " <<
01690                             subtriangle_lookup(p));
01691         }
01692     case 9:
01693       switch (subtriangle_lookup(p))
01694         {
01695         case 0:
01696           return std::sqrt(2.) * (xi*eta*eta - 1./3.*eta*eta*eta);
01697         case 1:
01698           return std::sqrt(2.) * (2./3. - 3*xi + 4*xi*xi - 5./3.*xi*xi*xi
01699                                   - 3*eta + 10*xi*eta - 7*xi*xi*eta
01700                                   + 4*eta*eta - 7*xi*eta*eta - 5./3.*eta*eta*eta);
01701         case 2:
01702           return std::sqrt(2.) * (-1./3.*xi*xi*xi + xi*xi*eta);
01703 
01704         default:
01705           libmesh_error_msg("Invalid subtriangle lookup = " <<
01706                             subtriangle_lookup(p));
01707         }
01708     case 10:
01709       switch (subtriangle_lookup(p))
01710         {
01711         case 0:
01712           return 2*eta*eta - 2*xi*eta*eta - 8./3.*eta*eta*eta;
01713         case 1:
01714           return -2./3. + 2*xi - 2*xi*xi + 2./3.*xi*xi*xi
01715             + 4*eta - 8*xi*eta + 4*xi*xi*eta
01716             - 6*eta*eta + 6*xi*eta*eta + 8./3.*eta*eta*eta;
01717         case 2:
01718           return -2*xi*xi + 10./3.*xi*xi*xi
01719             + 4*xi*eta - 4*xi*xi*eta
01720             - 4*xi*eta*eta;
01721 
01722         default:
01723           libmesh_error_msg("Invalid subtriangle lookup = " <<
01724                             subtriangle_lookup(p));
01725         }
01726     case 11:
01727       switch (subtriangle_lookup(p))
01728         {
01729         case 0:
01730           return 4*xi*eta - 4*xi*xi*eta
01731             - 2*eta*eta - 4*xi*eta*eta + 10./3.*eta*eta*eta;
01732         case 1:
01733           return -2./3. + 4*xi - 6*xi*xi + 8./3.*xi*xi*xi
01734             + 2*eta - 8*xi*eta + 6*xi*xi*eta
01735             - 2*eta*eta + 4*xi*eta*eta + 2./3.*eta*eta*eta;
01736         case 2:
01737           return 2*xi*xi - 8./3.*xi*xi*xi
01738             - 2*xi*xi*eta;
01739 
01740         default:
01741           libmesh_error_msg("Invalid subtriangle lookup = " <<
01742                             subtriangle_lookup(p));
01743         }
01744 
01745     default:
01746       libmesh_error_msg("Invalid shape function index i = " <<
01747                         basis_num);
01748     }
01749 
01750   libmesh_error_msg("We'll never get here!");
01751   return 0.;
01752 }
01753 
01754 
01755 } // end anonymous namespace
01756 
01757 
01758 namespace libMesh
01759 {
01760 
01761 
01762 template <>
01763 Real FE<2,CLOUGH>::shape(const ElemType,
01764                          const Order,
01765                          const unsigned int,
01766                          const Point&)
01767 {
01768   libmesh_error_msg("Clough-Tocher elements require the real element \nto construct gradient-based degrees of freedom.");
01769   return 0.;
01770 }
01771 
01772 
01773 
01774 template <>
01775 Real FE<2,CLOUGH>::shape(const Elem* elem,
01776                          const Order order,
01777                          const unsigned int i,
01778                          const Point& p)
01779 {
01780   libmesh_assert(elem);
01781 
01782   clough_compute_coefs(elem);
01783 
01784   const ElemType type = elem->type();
01785 
01786   const Order totalorder = static_cast<Order>(order + elem->p_level());
01787 
01788   switch (totalorder)
01789     {
01790       // 2nd-order restricted Clough-Tocher element
01791     case SECOND:
01792       {
01793         // There may be a bug in the 2nd order case; the 3rd order
01794         // Clough-Tocher elements are pretty uniformly better anyways
01795         // so use those instead.
01796         libmesh_experimental();
01797         switch (type)
01798           {
01799             // C1 functions on the Clough-Tocher triangle.
01800           case TRI6:
01801             {
01802               libmesh_assert_less (i, 9);
01803               // FIXME: it would be nice to calculate (and cache)
01804               // clough_raw_shape(j,p) only once per triangle, not 1-7
01805               // times
01806               switch (i)
01807                 {
01808                   // Note: these DoF numbers are "scrambled" because my
01809                   // initial numbering conventions didn't match libMesh
01810                 case 0:
01811                   return clough_raw_shape(0, p)
01812                     + d1d2n * clough_raw_shape(10, p)
01813                     + d1d3n * clough_raw_shape(11, p);
01814                 case 3:
01815                   return clough_raw_shape(1, p)
01816                     + d2d3n * clough_raw_shape(11, p)
01817                     + d2d1n * clough_raw_shape(9, p);
01818                 case 6:
01819                   return clough_raw_shape(2, p)
01820                     + d3d1n * clough_raw_shape(9, p)
01821                     + d3d2n * clough_raw_shape(10, p);
01822                 case 1:
01823                   return d1xd1x * clough_raw_shape(3, p)
01824                     + d1xd1y * clough_raw_shape(4, p)
01825                     + d1xd2n * clough_raw_shape(10, p)
01826                     + d1xd3n * clough_raw_shape(11, p)
01827                     + 0.5 * N01x * d3nd3n * clough_raw_shape(11, p)
01828                     + 0.5 * N02x * d2nd2n * clough_raw_shape(10, p);
01829                 case 2:
01830                   return d1yd1y * clough_raw_shape(4, p)
01831                     + d1yd1x * clough_raw_shape(3, p)
01832                     + d1yd2n * clough_raw_shape(10, p)
01833                     + d1yd3n * clough_raw_shape(11, p)
01834                     + 0.5 * N01y * d3nd3n * clough_raw_shape(11, p)
01835                     + 0.5 * N02y * d2nd2n * clough_raw_shape(10, p);
01836                 case 4:
01837                   return d2xd2x * clough_raw_shape(5, p)
01838                     + d2xd2y * clough_raw_shape(6, p)
01839                     + d2xd3n * clough_raw_shape(11, p)
01840                     + d2xd1n * clough_raw_shape(9, p)
01841                     + 0.5 * N10x * d3nd3n * clough_raw_shape(11, p)
01842                     + 0.5 * N12x * d1nd1n * clough_raw_shape(9, p);
01843                 case 5:
01844                   return d2yd2y * clough_raw_shape(6, p)
01845                     + d2yd2x * clough_raw_shape(5, p)
01846                     + d2yd3n * clough_raw_shape(11, p)
01847                     + d2yd1n * clough_raw_shape(9, p)
01848                     + 0.5 * N10y * d3nd3n * clough_raw_shape(11, p)
01849                     + 0.5 * N12y * d1nd1n * clough_raw_shape(9, p);
01850                 case 7:
01851                   return d3xd3x * clough_raw_shape(7, p)
01852                     + d3xd3y * clough_raw_shape(8, p)
01853                     + d3xd1n * clough_raw_shape(9, p)
01854                     + d3xd2n * clough_raw_shape(10, p)
01855                     + 0.5 * N20x * d2nd2n * clough_raw_shape(10, p)
01856                     + 0.5 * N21x * d1nd1n * clough_raw_shape(9, p);
01857                 case 8:
01858                   return d3yd3y * clough_raw_shape(8, p)
01859                     + d3yd3x * clough_raw_shape(7, p)
01860                     + d3yd1n * clough_raw_shape(9, p)
01861                     + d3yd2n * clough_raw_shape(10, p)
01862                     + 0.5 * N20y * d2nd2n * clough_raw_shape(10, p)
01863                     + 0.5 * N21y * d1nd1n * clough_raw_shape(9, p);
01864                 default:
01865                   libmesh_error_msg("Invalid shape function index i = " << i);
01866                 }
01867             }
01868           default:
01869             libmesh_error_msg("ERROR: Unsupported element type = " << type);
01870           }
01871       }
01872       // 3rd-order Clough-Tocher element
01873     case THIRD:
01874       {
01875         switch (type)
01876           {
01877             // C1 functions on the Clough-Tocher triangle.
01878           case TRI6:
01879             {
01880               libmesh_assert_less (i, 12);
01881 
01882               // FIXME: it would be nice to calculate (and cache)
01883               // clough_raw_shape(j,p) only once per triangle, not 1-7
01884               // times
01885               switch (i)
01886                 {
01887                   // Note: these DoF numbers are "scrambled" because my
01888                   // initial numbering conventions didn't match libMesh
01889                 case 0:
01890                   return clough_raw_shape(0, p)
01891                     + d1d2n * clough_raw_shape(10, p)
01892                     + d1d3n * clough_raw_shape(11, p);
01893                 case 3:
01894                   return clough_raw_shape(1, p)
01895                     + d2d3n * clough_raw_shape(11, p)
01896                     + d2d1n * clough_raw_shape(9, p);
01897                 case 6:
01898                   return clough_raw_shape(2, p)
01899                     + d3d1n * clough_raw_shape(9, p)
01900                     + d3d2n * clough_raw_shape(10, p);
01901                 case 1:
01902                   return d1xd1x * clough_raw_shape(3, p)
01903                     + d1xd1y * clough_raw_shape(4, p)
01904                     + d1xd2n * clough_raw_shape(10, p)
01905                     + d1xd3n * clough_raw_shape(11, p);
01906                 case 2:
01907                   return d1yd1y * clough_raw_shape(4, p)
01908                     + d1yd1x * clough_raw_shape(3, p)
01909                     + d1yd2n * clough_raw_shape(10, p)
01910                     + d1yd3n * clough_raw_shape(11, p);
01911                 case 4:
01912                   return d2xd2x * clough_raw_shape(5, p)
01913                     + d2xd2y * clough_raw_shape(6, p)
01914                     + d2xd3n * clough_raw_shape(11, p)
01915                     + d2xd1n * clough_raw_shape(9, p);
01916                 case 5:
01917                   return d2yd2y * clough_raw_shape(6, p)
01918                     + d2yd2x * clough_raw_shape(5, p)
01919                     + d2yd3n * clough_raw_shape(11, p)
01920                     + d2yd1n * clough_raw_shape(9, p);
01921                 case 7:
01922                   return d3xd3x * clough_raw_shape(7, p)
01923                     + d3xd3y * clough_raw_shape(8, p)
01924                     + d3xd1n * clough_raw_shape(9, p)
01925                     + d3xd2n * clough_raw_shape(10, p);
01926                 case 8:
01927                   return d3yd3y * clough_raw_shape(8, p)
01928                     + d3yd3x * clough_raw_shape(7, p)
01929                     + d3yd1n * clough_raw_shape(9, p)
01930                     + d3yd2n * clough_raw_shape(10, p);
01931                 case 10:
01932                   return d1nd1n * clough_raw_shape(9, p);
01933                 case 11:
01934                   return d2nd2n * clough_raw_shape(10, p);
01935                 case 9:
01936                   return d3nd3n * clough_raw_shape(11, p);
01937 
01938                 default:
01939                   libmesh_error_msg("Invalid shape function index i = " << i);
01940                 }
01941             }
01942           default:
01943             libmesh_error_msg("ERROR: Unsupported element type = " << type);
01944           }
01945       }
01946       // by default throw an error
01947     default:
01948       libmesh_error_msg("ERROR: Unsupported polynomial order = " << order);
01949     }
01950 
01951   libmesh_error_msg("We'll never get here!");
01952   return 0.;
01953 }
01954 
01955 
01956 
01957 template <>
01958 Real FE<2,CLOUGH>::shape_deriv(const ElemType,
01959                                const Order,
01960                                const unsigned int,
01961                                const unsigned int,
01962                                const Point&)
01963 {
01964   libmesh_error_msg("Clough-Tocher elements require the real element \nto construct gradient-based degrees of freedom.");
01965   return 0.;
01966 }
01967 
01968 
01969 
01970 template <>
01971 Real FE<2,CLOUGH>::shape_deriv(const Elem* elem,
01972                                const Order order,
01973                                const unsigned int i,
01974                                const unsigned int j,
01975                                const Point& p)
01976 {
01977   libmesh_assert(elem);
01978 
01979   clough_compute_coefs(elem);
01980 
01981   const ElemType type = elem->type();
01982 
01983   const Order totalorder = static_cast<Order>(order + elem->p_level());
01984 
01985   switch (totalorder)
01986     {
01987       // 2nd-order restricted Clough-Tocher element
01988     case SECOND:
01989       {
01990         // There may be a bug in the 2nd order case; the 3rd order
01991         // Clough-Tocher elements are pretty uniformly better anyways
01992         // so use those instead.
01993         libmesh_experimental();
01994         switch (type)
01995           {
01996             // C1 functions on the Clough-Tocher triangle.
01997           case TRI6:
01998             {
01999               libmesh_assert_less (i, 9);
02000               // FIXME: it would be nice to calculate (and cache)
02001               // clough_raw_shape(j,p) only once per triangle, not 1-7
02002               // times
02003               switch (i)
02004                 {
02005                   // Note: these DoF numbers are "scrambled" because my
02006                   // initial numbering conventions didn't match libMesh
02007                 case 0:
02008                   return clough_raw_shape_deriv(0, j, p)
02009                     + d1d2n * clough_raw_shape_deriv(10, j, p)
02010                     + d1d3n * clough_raw_shape_deriv(11, j, p);
02011                 case 3:
02012                   return clough_raw_shape_deriv(1, j, p)
02013                     + d2d3n * clough_raw_shape_deriv(11, j, p)
02014                     + d2d1n * clough_raw_shape_deriv(9, j, p);
02015                 case 6:
02016                   return clough_raw_shape_deriv(2, j, p)
02017                     + d3d1n * clough_raw_shape_deriv(9, j, p)
02018                     + d3d2n * clough_raw_shape_deriv(10, j, p);
02019                 case 1:
02020                   return d1xd1x * clough_raw_shape_deriv(3, j, p)
02021                     + d1xd1y * clough_raw_shape_deriv(4, j, p)
02022                     + d1xd2n * clough_raw_shape_deriv(10, j, p)
02023                     + d1xd3n * clough_raw_shape_deriv(11, j, p)
02024                     + 0.5 * N01x * d3nd3n * clough_raw_shape_deriv(11, j, p)
02025                     + 0.5 * N02x * d2nd2n * clough_raw_shape_deriv(10, j, p);
02026                 case 2:
02027                   return d1yd1y * clough_raw_shape_deriv(4, j, p)
02028                     + d1yd1x * clough_raw_shape_deriv(3, j, p)
02029                     + d1yd2n * clough_raw_shape_deriv(10, j, p)
02030                     + d1yd3n * clough_raw_shape_deriv(11, j, p)
02031                     + 0.5 * N01y * d3nd3n * clough_raw_shape_deriv(11, j, p)
02032                     + 0.5 * N02y * d2nd2n * clough_raw_shape_deriv(10, j, p);
02033                 case 4:
02034                   return d2xd2x * clough_raw_shape_deriv(5, j, p)
02035                     + d2xd2y * clough_raw_shape_deriv(6, j, p)
02036                     + d2xd3n * clough_raw_shape_deriv(11, j, p)
02037                     + d2xd1n * clough_raw_shape_deriv(9, j, p)
02038                     + 0.5 * N10x * d3nd3n * clough_raw_shape_deriv(11, j, p)
02039                     + 0.5 * N12x * d1nd1n * clough_raw_shape_deriv(9, j, p);
02040                 case 5:
02041                   return d2yd2y * clough_raw_shape_deriv(6, j, p)
02042                     + d2yd2x * clough_raw_shape_deriv(5, j, p)
02043                     + d2yd3n * clough_raw_shape_deriv(11, j, p)
02044                     + d2yd1n * clough_raw_shape_deriv(9, j, p)
02045                     + 0.5 * N10y * d3nd3n * clough_raw_shape_deriv(11, j, p)
02046                     + 0.5 * N12y * d1nd1n * clough_raw_shape_deriv(9, j, p);
02047                 case 7:
02048                   return d3xd3x * clough_raw_shape_deriv(7, j, p)
02049                     + d3xd3y * clough_raw_shape_deriv(8, j, p)
02050                     + d3xd1n * clough_raw_shape_deriv(9, j, p)
02051                     + d3xd2n * clough_raw_shape_deriv(10, j, p)
02052                     + 0.5 * N20x * d2nd2n * clough_raw_shape_deriv(10, j, p)
02053                     + 0.5 * N21x * d1nd1n * clough_raw_shape_deriv(9, j, p);
02054                 case 8:
02055                   return d3yd3y * clough_raw_shape_deriv(8, j, p)
02056                     + d3yd3x * clough_raw_shape_deriv(7, j, p)
02057                     + d3yd1n * clough_raw_shape_deriv(9, j, p)
02058                     + d3yd2n * clough_raw_shape_deriv(10, j, p)
02059                     + 0.5 * N20y * d2nd2n * clough_raw_shape_deriv(10, j, p)
02060                     + 0.5 * N21y * d1nd1n * clough_raw_shape_deriv(9, j, p);
02061                 default:
02062                   libmesh_error_msg("Invalid shape function index i = " << i);
02063                 }
02064             }
02065           default:
02066             libmesh_error_msg("ERROR: Unsupported element type = " << type);
02067           }
02068       }
02069       // 3rd-order Clough-Tocher element
02070     case THIRD:
02071       {
02072         switch (type)
02073           {
02074             // C1 functions on the Clough-Tocher triangle.
02075           case TRI6:
02076             {
02077               libmesh_assert_less (i, 12);
02078 
02079               // FIXME: it would be nice to calculate (and cache)
02080               // clough_raw_shape(j,p) only once per triangle, not 1-7
02081               // times
02082               switch (i)
02083                 {
02084                   // Note: these DoF numbers are "scrambled" because my
02085                   // initial numbering conventions didn't match libMesh
02086                 case 0:
02087                   return clough_raw_shape_deriv(0, j, p)
02088                     + d1d2n * clough_raw_shape_deriv(10, j, p)
02089                     + d1d3n * clough_raw_shape_deriv(11, j, p);
02090                 case 3:
02091                   return clough_raw_shape_deriv(1, j, p)
02092                     + d2d3n * clough_raw_shape_deriv(11, j, p)
02093                     + d2d1n * clough_raw_shape_deriv(9, j, p);
02094                 case 6:
02095                   return clough_raw_shape_deriv(2, j, p)
02096                     + d3d1n * clough_raw_shape_deriv(9, j, p)
02097                     + d3d2n * clough_raw_shape_deriv(10, j, p);
02098                 case 1:
02099                   return d1xd1x * clough_raw_shape_deriv(3, j, p)
02100                     + d1xd1y * clough_raw_shape_deriv(4, j, p)
02101                     + d1xd2n * clough_raw_shape_deriv(10, j, p)
02102                     + d1xd3n * clough_raw_shape_deriv(11, j, p);
02103                 case 2:
02104                   return d1yd1y * clough_raw_shape_deriv(4, j, p)
02105                     + d1yd1x * clough_raw_shape_deriv(3, j, p)
02106                     + d1yd2n * clough_raw_shape_deriv(10, j, p)
02107                     + d1yd3n * clough_raw_shape_deriv(11, j, p);
02108                 case 4:
02109                   return d2xd2x * clough_raw_shape_deriv(5, j, p)
02110                     + d2xd2y * clough_raw_shape_deriv(6, j, p)
02111                     + d2xd3n * clough_raw_shape_deriv(11, j, p)
02112                     + d2xd1n * clough_raw_shape_deriv(9, j, p);
02113                 case 5:
02114                   return d2yd2y * clough_raw_shape_deriv(6, j, p)
02115                     + d2yd2x * clough_raw_shape_deriv(5, j, p)
02116                     + d2yd3n * clough_raw_shape_deriv(11, j, p)
02117                     + d2yd1n * clough_raw_shape_deriv(9, j, p);
02118                 case 7:
02119                   return d3xd3x * clough_raw_shape_deriv(7, j, p)
02120                     + d3xd3y * clough_raw_shape_deriv(8, j, p)
02121                     + d3xd1n * clough_raw_shape_deriv(9, j, p)
02122                     + d3xd2n * clough_raw_shape_deriv(10, j, p);
02123                 case 8:
02124                   return d3yd3y * clough_raw_shape_deriv(8, j, p)
02125                     + d3yd3x * clough_raw_shape_deriv(7, j, p)
02126                     + d3yd1n * clough_raw_shape_deriv(9, j, p)
02127                     + d3yd2n * clough_raw_shape_deriv(10, j, p);
02128                 case 10:
02129                   return d1nd1n * clough_raw_shape_deriv(9, j, p);
02130                 case 11:
02131                   return d2nd2n * clough_raw_shape_deriv(10, j, p);
02132                 case 9:
02133                   return d3nd3n * clough_raw_shape_deriv(11, j, p);
02134 
02135                 default:
02136                   libmesh_error_msg("Invalid shape function index i = " << i);
02137                 }
02138             }
02139           default:
02140             libmesh_error_msg("ERROR: Unsupported element type = " << type);
02141           }
02142       }
02143       // by default throw an error
02144     default:
02145       libmesh_error_msg("ERROR: Unsupported polynomial order = " << order);
02146     }
02147 
02148   libmesh_error_msg("We'll never get here!");
02149   return 0.;
02150 }
02151 
02152 
02153 
02154 template <>
02155 Real FE<2,CLOUGH>::shape_second_deriv(const Elem* elem,
02156                                       const Order order,
02157                                       const unsigned int i,
02158                                       const unsigned int j,
02159                                       const Point& p)
02160 {
02161   libmesh_assert(elem);
02162 
02163   clough_compute_coefs(elem);
02164 
02165   const ElemType type = elem->type();
02166 
02167   const Order totalorder = static_cast<Order>(order + elem->p_level());
02168 
02169   switch (totalorder)
02170     {
02171       // 2nd-order restricted Clough-Tocher element
02172     case SECOND:
02173       {
02174         switch (type)
02175           {
02176             // C1 functions on the Clough-Tocher triangle.
02177           case TRI6:
02178             {
02179               libmesh_assert_less (i, 9);
02180               // FIXME: it would be nice to calculate (and cache)
02181               // clough_raw_shape(j,p) only once per triangle, not 1-7
02182               // times
02183               switch (i)
02184                 {
02185                   // Note: these DoF numbers are "scrambled" because my
02186                   // initial numbering conventions didn't match libMesh
02187                 case 0:
02188                   return clough_raw_shape_second_deriv(0, j, p)
02189                     + d1d2n * clough_raw_shape_second_deriv(10, j, p)
02190                     + d1d3n * clough_raw_shape_second_deriv(11, j, p);
02191                 case 3:
02192                   return clough_raw_shape_second_deriv(1, j, p)
02193                     + d2d3n * clough_raw_shape_second_deriv(11, j, p)
02194                     + d2d1n * clough_raw_shape_second_deriv(9, j, p);
02195                 case 6:
02196                   return clough_raw_shape_second_deriv(2, j, p)
02197                     + d3d1n * clough_raw_shape_second_deriv(9, j, p)
02198                     + d3d2n * clough_raw_shape_second_deriv(10, j, p);
02199                 case 1:
02200                   return d1xd1x * clough_raw_shape_second_deriv(3, j, p)
02201                     + d1xd1y * clough_raw_shape_second_deriv(4, j, p)
02202                     + d1xd2n * clough_raw_shape_second_deriv(10, j, p)
02203                     + d1xd3n * clough_raw_shape_second_deriv(11, j, p)
02204                     + 0.5 * N01x * d3nd3n * clough_raw_shape_second_deriv(11, j, p)
02205                     + 0.5 * N02x * d2nd2n * clough_raw_shape_second_deriv(10, j, p);
02206                 case 2:
02207                   return d1yd1y * clough_raw_shape_second_deriv(4, j, p)
02208                     + d1yd1x * clough_raw_shape_second_deriv(3, j, p)
02209                     + d1yd2n * clough_raw_shape_second_deriv(10, j, p)
02210                     + d1yd3n * clough_raw_shape_second_deriv(11, j, p)
02211                     + 0.5 * N01y * d3nd3n * clough_raw_shape_second_deriv(11, j, p)
02212                     + 0.5 * N02y * d2nd2n * clough_raw_shape_second_deriv(10, j, p);
02213                 case 4:
02214                   return d2xd2x * clough_raw_shape_second_deriv(5, j, p)
02215                     + d2xd2y * clough_raw_shape_second_deriv(6, j, p)
02216                     + d2xd3n * clough_raw_shape_second_deriv(11, j, p)
02217                     + d2xd1n * clough_raw_shape_second_deriv(9, j, p)
02218                     + 0.5 * N10x * d3nd3n * clough_raw_shape_second_deriv(11, j, p)
02219                     + 0.5 * N12x * d1nd1n * clough_raw_shape_second_deriv(9, j, p);
02220                 case 5:
02221                   return d2yd2y * clough_raw_shape_second_deriv(6, j, p)
02222                     + d2yd2x * clough_raw_shape_second_deriv(5, j, p)
02223                     + d2yd3n * clough_raw_shape_second_deriv(11, j, p)
02224                     + d2yd1n * clough_raw_shape_second_deriv(9, j, p)
02225                     + 0.5 * N10y * d3nd3n * clough_raw_shape_second_deriv(11, j, p)
02226                     + 0.5 * N12y * d1nd1n * clough_raw_shape_second_deriv(9, j, p);
02227                 case 7:
02228                   return d3xd3x * clough_raw_shape_second_deriv(7, j, p)
02229                     + d3xd3y * clough_raw_shape_second_deriv(8, j, p)
02230                     + d3xd1n * clough_raw_shape_second_deriv(9, j, p)
02231                     + d3xd2n * clough_raw_shape_second_deriv(10, j, p)
02232                     + 0.5 * N20x * d2nd2n * clough_raw_shape_second_deriv(10, j, p)
02233                     + 0.5 * N21x * d1nd1n * clough_raw_shape_second_deriv(9, j, p);
02234                 case 8:
02235                   return d3yd3y * clough_raw_shape_second_deriv(8, j, p)
02236                     + d3yd3x * clough_raw_shape_second_deriv(7, j, p)
02237                     + d3yd1n * clough_raw_shape_second_deriv(9, j, p)
02238                     + d3yd2n * clough_raw_shape_second_deriv(10, j, p)
02239                     + 0.5 * N20y * d2nd2n * clough_raw_shape_second_deriv(10, j, p)
02240                     + 0.5 * N21y * d1nd1n * clough_raw_shape_second_deriv(9, j, p);
02241                 default:
02242                   libmesh_error_msg("Invalid shape function index i = " << i);
02243                 }
02244             }
02245           default:
02246             libmesh_error_msg("ERROR: Unsupported element type = " << type);
02247           }
02248       }
02249       // 3rd-order Clough-Tocher element
02250     case THIRD:
02251       {
02252         switch (type)
02253           {
02254             // C1 functions on the Clough-Tocher triangle.
02255           case TRI6:
02256             {
02257               libmesh_assert_less (i, 12);
02258 
02259               // FIXME: it would be nice to calculate (and cache)
02260               // clough_raw_shape(j,p) only once per triangle, not 1-7
02261               // times
02262               switch (i)
02263                 {
02264                   // Note: these DoF numbers are "scrambled" because my
02265                   // initial numbering conventions didn't match libMesh
02266                 case 0:
02267                   return clough_raw_shape_second_deriv(0, j, p)
02268                     + d1d2n * clough_raw_shape_second_deriv(10, j, p)
02269                     + d1d3n * clough_raw_shape_second_deriv(11, j, p);
02270                 case 3:
02271                   return clough_raw_shape_second_deriv(1, j, p)
02272                     + d2d3n * clough_raw_shape_second_deriv(11, j, p)
02273                     + d2d1n * clough_raw_shape_second_deriv(9, j, p);
02274                 case 6:
02275                   return clough_raw_shape_second_deriv(2, j, p)
02276                     + d3d1n * clough_raw_shape_second_deriv(9, j, p)
02277                     + d3d2n * clough_raw_shape_second_deriv(10, j, p);
02278                 case 1:
02279                   return d1xd1x * clough_raw_shape_second_deriv(3, j, p)
02280                     + d1xd1y * clough_raw_shape_second_deriv(4, j, p)
02281                     + d1xd2n * clough_raw_shape_second_deriv(10, j, p)
02282                     + d1xd3n * clough_raw_shape_second_deriv(11, j, p);
02283                 case 2:
02284                   return d1yd1y * clough_raw_shape_second_deriv(4, j, p)
02285                     + d1yd1x * clough_raw_shape_second_deriv(3, j, p)
02286                     + d1yd2n * clough_raw_shape_second_deriv(10, j, p)
02287                     + d1yd3n * clough_raw_shape_second_deriv(11, j, p);
02288                 case 4:
02289                   return d2xd2x * clough_raw_shape_second_deriv(5, j, p)
02290                     + d2xd2y * clough_raw_shape_second_deriv(6, j, p)
02291                     + d2xd3n * clough_raw_shape_second_deriv(11, j, p)
02292                     + d2xd1n * clough_raw_shape_second_deriv(9, j, p);
02293                 case 5:
02294                   return d2yd2y * clough_raw_shape_second_deriv(6, j, p)
02295                     + d2yd2x * clough_raw_shape_second_deriv(5, j, p)
02296                     + d2yd3n * clough_raw_shape_second_deriv(11, j, p)
02297                     + d2yd1n * clough_raw_shape_second_deriv(9, j, p);
02298                 case 7:
02299                   return d3xd3x * clough_raw_shape_second_deriv(7, j, p)
02300                     + d3xd3y * clough_raw_shape_second_deriv(8, j, p)
02301                     + d3xd1n * clough_raw_shape_second_deriv(9, j, p)
02302                     + d3xd2n * clough_raw_shape_second_deriv(10, j, p);
02303                 case 8:
02304                   return d3yd3y * clough_raw_shape_second_deriv(8, j, p)
02305                     + d3yd3x * clough_raw_shape_second_deriv(7, j, p)
02306                     + d3yd1n * clough_raw_shape_second_deriv(9, j, p)
02307                     + d3yd2n * clough_raw_shape_second_deriv(10, j, p);
02308                 case 10:
02309                   return d1nd1n * clough_raw_shape_second_deriv(9, j, p);
02310                 case 11:
02311                   return d2nd2n * clough_raw_shape_second_deriv(10, j, p);
02312                 case 9:
02313                   return d3nd3n * clough_raw_shape_second_deriv(11, j, p);
02314 
02315                 default:
02316                   libmesh_error_msg("Invalid shape function index i = " << i);
02317                 }
02318             }
02319           default:
02320             libmesh_error_msg("ERROR: Unsupported element type = " << type);
02321           }
02322       }
02323       // by default throw an error
02324     default:
02325       libmesh_error_msg("ERROR: Unsupported polynomial order = " << order);
02326     }
02327 
02328   libmesh_error_msg("We'll never get here!");
02329   return 0.;
02330 }
02331 
02332 } // namespace libMesh