MFEM v2.0
fe.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
00003 // reserved. See file COPYRIGHT for details.
00004 //
00005 // This file is part of the MFEM library. For more information and source code
00006 // availability see http://mfem.googlecode.com.
00007 //
00008 // MFEM is free software; you can redistribute it and/or modify it under the
00009 // terms of the GNU Lesser General Public License (as published by the Free
00010 // Software Foundation) version 2.1 dated February 1999.
00011 
00012 // Finite Element classes
00013 
00014 #include <math.h>
00015 #include "fem.hpp"
00016 
00017 FiniteElement::FiniteElement(int D, int G, int Do, int O, int F)
00018    : Nodes(Do)
00019 {
00020    Dim = D ; GeomType = G ; Dof = Do ; Order = O ; FuncSpace = F;
00021    RangeType = SCALAR;
00022 }
00023 
00024 void FiniteElement::CalcVShape (
00025    const IntegrationPoint &ip, DenseMatrix &shape) const
00026 {
00027    mfem_error ("FiniteElement::CalcVShape (...)\n"
00028                "   is not implemented for this class!");
00029 }
00030 
00031 void FiniteElement::CalcVShape (
00032    ElementTransformation &Trans, DenseMatrix &shape) const
00033 {
00034    mfem_error ("FiniteElement::CalcVShape 2 (...)\n"
00035                "   is not implemented for this class!");
00036 }
00037 
00038 void FiniteElement::CalcDivShape (
00039    const IntegrationPoint &ip, Vector &divshape) const
00040 {
00041    mfem_error ("FiniteElement::CalcDivShape (...)\n"
00042                "   is not implemented for this class!");
00043 }
00044 
00045 void FiniteElement::CalcCurlShape(const IntegrationPoint &ip,
00046                                   DenseMatrix &curl_shape) const
00047 {
00048    mfem_error ("FiniteElement::CalcCurlShape (...)\n"
00049                "   is not implemented for this class!");
00050 }
00051 
00052 void FiniteElement::GetFaceDofs(int face, int **dofs, int *ndofs) const
00053 {
00054    mfem_error ("FiniteElement::GetFaceDofs (...)");
00055 }
00056 
00057 void FiniteElement::CalcHessian (const IntegrationPoint &ip,
00058                                  DenseMatrix &h) const
00059 {
00060    mfem_error ("FiniteElement::CalcHessian (...) is not overloaded !");
00061 }
00062 
00063 void FiniteElement::GetLocalInterpolation (ElementTransformation &Trans,
00064                                            DenseMatrix &I) const
00065 {
00066    mfem_error ("GetLocalInterpolation (...) is not overloaded !");
00067 }
00068 
00069 void FiniteElement::Project (
00070    Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
00071 {
00072    mfem_error ("FiniteElement::Project (...) is not overloaded !");
00073 }
00074 
00075 void FiniteElement::Project (
00076    VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
00077 {
00078    mfem_error ("FiniteElement::Project (...) (vector) is not overloaded !");
00079 }
00080 
00081 void FiniteElement::ProjectDelta(int vertex, Vector &dofs) const
00082 {
00083    mfem_error("FiniteElement::ProjectDelta(...) is not implemented for "
00084               "this element!");
00085 }
00086 
00087 void FiniteElement::Project(
00088    const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
00089 {
00090    mfem_error("FiniteElement::Project(...) (fe version) is not implemented "
00091               "for this element!");
00092 }
00093 
00094 void FiniteElement::ProjectGrad(
00095    const FiniteElement &fe, ElementTransformation &Trans,
00096    DenseMatrix &grad) const
00097 {
00098    mfem_error("FiniteElement::ProjectGrad(...) is not implemented for "
00099               "this element!");
00100 }
00101 
00102 void FiniteElement::ProjectCurl(
00103    const FiniteElement &fe, ElementTransformation &Trans,
00104    DenseMatrix &curl) const
00105 {
00106    mfem_error("FiniteElement::ProjectCurl(...) is not implemented for "
00107               "this element!");
00108 }
00109 
00110 void FiniteElement::ProjectDiv(
00111    const FiniteElement &fe, ElementTransformation &Trans,
00112    DenseMatrix &div) const
00113 {
00114    mfem_error("FiniteElement::ProjectDiv(...) is not implemented for "
00115               "this element!");
00116 }
00117 
00118 
00119 void NodalFiniteElement::NodalLocalInterpolation (
00120    ElementTransformation &Trans, DenseMatrix &I,
00121    const NodalFiniteElement &fine_fe) const
00122 {
00123    double v[3];
00124    Vector vv (v, Dim);
00125    IntegrationPoint f_ip;
00126 
00127 #ifdef MFEM_USE_OPENMP
00128    Vector c_shape(Dof);
00129 #endif
00130 
00131    for (int i = 0; i < fine_fe.Dof; i++)
00132    {
00133       Trans.Transform (fine_fe.Nodes.IntPoint (i), vv);
00134       f_ip.x = v[0];
00135       if (Dim > 1) { f_ip.y = v[1]; if (Dim > 2) f_ip.z = v[2]; }
00136       CalcShape (f_ip, c_shape);
00137       for (int j = 0; j < Dof; j++)
00138          if (fabs (I (i,j) = c_shape (j)) < 1.0e-12)
00139             I (i,j) = 0.0;
00140    }
00141 }
00142 
00143 void NodalFiniteElement::Project (
00144    Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
00145 {
00146    for (int i = 0; i < Dof; i++)
00147    {
00148       const IntegrationPoint &ip = Nodes.IntPoint(i);
00149       // some coefficients expect that Trans.IntPoint is the same
00150       // as the second argument of Eval
00151       Trans.SetIntPoint(&ip);
00152       dofs(i) = coeff.Eval (Trans, ip);
00153    }
00154 }
00155 
00156 void NodalFiniteElement::Project (
00157    VectorCoefficient &vc, ElementTransformation &Trans,
00158    Vector &dofs) const
00159 {
00160    double v[3];
00161    Vector x (v, vc.GetVDim());
00162 
00163    for (int i = 0; i < Dof; i++)
00164    {
00165       const IntegrationPoint &ip = Nodes.IntPoint(i);
00166       Trans.SetIntPoint(&ip);
00167       vc.Eval (x, Trans, ip);
00168       for (int j = 0; j < x.Size(); j++)
00169          dofs(Dof*j+i) = v[j];
00170    }
00171 }
00172 
00173 void NodalFiniteElement::Project(
00174    const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
00175 {
00176    if (fe.GetRangeType() == SCALAR)
00177    {
00178       Vector shape(fe.GetDof());
00179 
00180       I.SetSize(Dof, fe.GetDof());
00181       for (int k = 0; k < Dof; k++)
00182       {
00183          fe.CalcShape(Nodes.IntPoint(k), shape);
00184          for (int j = 0; j < shape.Size(); j++)
00185             I(k,j) = (fabs(shape(j)) < 1e-12) ? 0.0 : shape(j);
00186       }
00187    }
00188    else
00189    {
00190       DenseMatrix vshape(fe.GetDof(), Dim);
00191 
00192       I.SetSize(Dim*Dof, fe.GetDof());
00193       for (int k = 0; k < Dof; k++)
00194       {
00195          Trans.SetIntPoint(&Nodes.IntPoint(k));
00196          fe.CalcVShape(Trans, vshape);
00197          for (int j = 0; j < vshape.Height(); j++)
00198             for (int d = 0; d < vshape.Width(); d++)
00199                I(k+d*Dof,j) = vshape(j,d);
00200       }
00201    }
00202 }
00203 
00204 void NodalFiniteElement::ProjectGrad(
00205    const FiniteElement &fe, ElementTransformation &Trans,
00206    DenseMatrix &grad) const
00207 {
00208    DenseMatrix dshape(fe.GetDof(), Dim), grad_k(fe.GetDof(), Dim), Jinv(Dim);
00209 
00210    grad.SetSize(Dim*Dof, fe.GetDof());
00211    for (int k = 0; k < Dof; k++)
00212    {
00213       const IntegrationPoint &ip = Nodes.IntPoint(k);
00214       fe.CalcDShape(ip, dshape);
00215       Trans.SetIntPoint(&ip);
00216       CalcInverse(Trans.Jacobian(), Jinv);
00217       Mult(dshape, Jinv, grad_k);
00218       for (int j = 0; j < grad_k.Height(); j++)
00219          for (int d = 0; d < Dim; d++)
00220             grad(k+d*Dof,j) = grad_k(j,d);
00221    }
00222 }
00223 
00224 void NodalFiniteElement::ProjectDiv(
00225    const FiniteElement &fe,ElementTransformation &Trans,
00226    DenseMatrix &div) const
00227 {
00228    double detJ;
00229    Vector div_shape(fe.GetDof());
00230 
00231    div.SetSize(Dof, fe.GetDof());
00232    for (int k = 0; k < Dof; k++)
00233    {
00234       const IntegrationPoint &ip = Nodes.IntPoint(k);
00235       fe.CalcDivShape(ip, div_shape);
00236       Trans.SetIntPoint(&ip);
00237       detJ = Trans.Weight();
00238       for (int j = 0; j < div_shape.Size(); j++)
00239          div(k,j) = (fabs(div_shape(j)) < 1e-12) ? 0.0 : div_shape(j)/detJ;
00240    }
00241 }
00242 
00243 void VectorFiniteElement::CalcShape (
00244    const IntegrationPoint &ip, Vector &shape ) const
00245 {
00246    mfem_error ("Error: Cannot use scalar CalcShape(...) function with\n"
00247                "   VectorFiniteElements!");
00248 }
00249 
00250 void VectorFiniteElement::CalcDShape (
00251    const IntegrationPoint &ip, DenseMatrix &dshape ) const
00252 {
00253    mfem_error ("Error: Cannot use scalar CalcDShape(...) function with\n"
00254                "   VectorFiniteElements!");
00255 }
00256 
00257 void VectorFiniteElement::CalcVShape_RT (
00258    ElementTransformation &Trans, DenseMatrix &shape) const
00259 {
00260 #ifdef MFEM_USE_OPENMP
00261    DenseMatrix vshape(Dof, Dim);
00262 #endif
00263    CalcVShape(Trans.GetIntPoint(), vshape);
00264 
00265    MultABt(vshape, Trans.Jacobian(), shape);
00266 
00267    shape *= (1.0 / Trans.Weight());
00268 }
00269 
00270 void VectorFiniteElement::CalcVShape_ND (
00271    ElementTransformation &Trans, DenseMatrix &shape) const
00272 {
00273    const DenseMatrix &J = Trans.Jacobian();
00274 
00275 #ifdef MFEM_USE_OPENMP
00276    DenseMatrix vshape(Dof, Dim);
00277    DenseMatrix Jinv(J.Width(), J.Height());
00278 #else
00279    Jinv.SetSize(J.Width(), J.Height());
00280 #endif
00281 
00282    CalcInverse(J, Jinv);
00283 
00284    CalcVShape(Trans.GetIntPoint(), vshape);
00285 
00286    Mult(vshape, Jinv, shape);
00287 }
00288 
00289 void VectorFiniteElement::Project_RT(
00290    const double *nk, const Array<int> &d2n,
00291    VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
00292 {
00293    double vk[3];
00294    Vector xk(vk, Dim);
00295 #ifdef MFEM_USE_OPENMP
00296    DenseMatrix Jinv(Dim);
00297 #endif
00298 
00299    for (int k = 0; k < Dof; k++)
00300    {
00301       Trans.SetIntPoint(&Nodes.IntPoint(k));
00302       // set Jinv = |J| J^{-1} = adj(J)
00303       CalcAdjugate(Trans.Jacobian(), Jinv);
00304 
00305       vc.Eval(xk, Trans, Nodes.IntPoint(k));
00306       // dof_k = nk^t adj(J) xk
00307       dofs(k) = Jinv.InnerProduct(vk, nk + d2n[k]*Dim);
00308    }
00309 }
00310 
00311 void VectorFiniteElement::Project_RT(
00312    const double *nk, const Array<int> &d2n, const FiniteElement &fe,
00313    ElementTransformation &Trans, DenseMatrix &I) const
00314 {
00315    if (fe.GetRangeType() == SCALAR)
00316    {
00317       double vk[3];
00318       Vector shape(fe.GetDof());
00319 #ifdef MFEM_USE_OPENMP
00320       DenseMatrix Jinv(Dim);
00321 #endif
00322 
00323       I.SetSize(Dof, Dim*fe.GetDof());
00324       for (int k = 0; k < Dof; k++)
00325       {
00326          const IntegrationPoint &ip = Nodes.IntPoint(k);
00327 
00328          fe.CalcShape(ip, shape);
00329          Trans.SetIntPoint(&ip);
00330          CalcAdjugateTranspose(Trans.Jacobian(), Jinv);
00331          Jinv.Mult(nk + d2n[k]*Dim, vk);
00332 
00333          for (int j = 0; j < shape.Size(); j++)
00334          {
00335             double s = shape(j);
00336             if (fabs(s) < 1e-12)
00337                s = 0.0;
00338             for (int d = 0; d < Dim; d++)
00339                I(k,j+d*shape.Size()) = s*vk[d];
00340          }
00341       }
00342    }
00343    else
00344    {
00345       mfem_error("VectorFiniteElement::Project_RT (fe version)");
00346    }
00347 }
00348 
00349 void VectorFiniteElement::ProjectGrad_RT(
00350    const double *nk, const Array<int> &d2n, const FiniteElement &fe,
00351    ElementTransformation &Trans, DenseMatrix &grad) const
00352 {
00353    if (Dim != 2)
00354       mfem_error("VectorFiniteElement::ProjectGrad_RT works only in 2D!");
00355 
00356    DenseMatrix dshape(fe.GetDof(), fe.GetDim());
00357    Vector grad_k(fe.GetDof());
00358    double tk[2];
00359 
00360    grad.SetSize(Dof, fe.GetDof());
00361    for (int k = 0; k < Dof; k++)
00362    {
00363       fe.CalcDShape(Nodes.IntPoint(k), dshape);
00364       tk[0] = nk[d2n[k]*Dim+1];
00365       tk[1] = -nk[d2n[k]*Dim];
00366       dshape.Mult(tk, grad_k);
00367       for (int j = 0; j < grad_k.Size(); j++)
00368          grad(k,j) = (fabs(grad_k(j)) < 1e-12) ? 0.0 : grad_k(j);
00369    }
00370 }
00371 
00372 void VectorFiniteElement::ProjectCurl_RT(
00373    const double *nk, const Array<int> &d2n, const FiniteElement &fe,
00374    ElementTransformation &Trans, DenseMatrix &curl) const
00375 {
00376    DenseMatrix curl_shape(fe.GetDof(), Dim);
00377    Vector curl_k(fe.GetDof());
00378 
00379    curl.SetSize(Dof, fe.GetDof());
00380    for (int k = 0; k < Dof; k++)
00381    {
00382       fe.CalcCurlShape(Nodes.IntPoint(k), curl_shape);
00383       curl_shape.Mult(nk + d2n[k]*Dim, curl_k);
00384       for (int j = 0; j < curl_k.Size(); j++)
00385          curl(k,j) = (fabs(curl_k(j)) < 1e-12) ? 0.0 : curl_k(j);
00386    }
00387 }
00388 
00389 void VectorFiniteElement::Project_ND(
00390    const double *tk, const Array<int> &d2t,
00391    VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
00392 {
00393    double vk[3];
00394    Vector xk(vk, vc.GetVDim());
00395 
00396    for (int k = 0; k < Dof; k++)
00397    {
00398       Trans.SetIntPoint(&Nodes.IntPoint(k));
00399 
00400       vc.Eval(xk, Trans, Nodes.IntPoint(k));
00401       // dof_k = xk^t J tk
00402       dofs(k) = Trans.Jacobian().InnerProduct(tk + d2t[k]*Dim, vk);
00403    }
00404 }
00405 
00406 void VectorFiniteElement::Project_ND(
00407    const double *tk, const Array<int> &d2t, const FiniteElement &fe,
00408    ElementTransformation &Trans, DenseMatrix &I) const
00409 {
00410    if (fe.GetRangeType() == SCALAR)
00411    {
00412       double vk[3];
00413       Vector shape(fe.GetDof());
00414 
00415       I.SetSize(Dof, Dim*fe.GetDof());
00416       for (int k = 0; k < Dof; k++)
00417       {
00418          const IntegrationPoint &ip = Nodes.IntPoint(k);
00419 
00420          fe.CalcShape(ip, shape);
00421          Trans.SetIntPoint(&ip);
00422          Trans.Jacobian().Mult(tk + d2t[k]*Dim, vk);
00423 
00424          for (int j = 0; j < shape.Size(); j++)
00425          {
00426             double s = shape(j);
00427             if (fabs(s) < 1e-12)
00428                s = 0.0;
00429             for (int d = 0; d < Dim; d++)
00430                I(k, j + d*shape.Size()) = s*vk[d];
00431          }
00432       }
00433    }
00434    else
00435    {
00436       mfem_error("VectorFiniteElement::Project_ND (fe version)");
00437    }
00438 }
00439 
00440 void VectorFiniteElement::ProjectGrad_ND(
00441    const double *tk, const Array<int> &d2t, const FiniteElement &fe,
00442    ElementTransformation &Trans, DenseMatrix &grad) const
00443 {
00444    DenseMatrix dshape(fe.GetDof(), fe.GetDim());
00445    Vector grad_k(fe.GetDof());
00446 
00447    grad.SetSize(Dof, fe.GetDof());
00448    for (int k = 0; k < Dof; k++)
00449    {
00450       fe.CalcDShape(Nodes.IntPoint(k), dshape);
00451       dshape.Mult(tk + d2t[k]*Dim, grad_k);
00452       for (int j = 0; j < grad_k.Size(); j++)
00453          grad(k,j) = (fabs(grad_k(j)) < 1e-12) ? 0.0 : grad_k(j);
00454    }
00455 }
00456 
00457 void VectorFiniteElement::LocalInterpolation_RT(
00458    const double *nk, const Array<int> &d2n, ElementTransformation &Trans,
00459    DenseMatrix &I) const
00460 {
00461    double vk[3];
00462    Vector xk(vk, Dim);
00463    IntegrationPoint ip;
00464 #ifdef MFEM_USE_OPENMP
00465    DenseMatrix vshape(Dof, Dim);
00466    DenseMatrix Jinv(Dim);
00467 #endif
00468 
00469    // assuming Trans is linear; this should be ok for all refinement types
00470    Trans.SetIntPoint(&Geometries.GetCenter(GeomType));
00471    // set Jinv = |J| J^{-t} = adj(J)^t
00472    CalcAdjugateTranspose(Trans.Jacobian(), Jinv);
00473    for (int k = 0; k < Dof; k++)
00474    {
00475       Trans.Transform(Nodes.IntPoint(k), xk);
00476       ip.Set3(vk);
00477       CalcVShape(ip, vshape);
00478       // xk = |J| J^{-t} n_k
00479       Jinv.Mult(nk + d2n[k]*Dim, vk);
00480       // I_k = vshape_k.adj(J)^t.n_k, k=1,...,Dof
00481       for (int j = 0; j < Dof; j++)
00482       {
00483          double Ikj = 0.;
00484          for (int i = 0; i < Dim; i++)
00485             Ikj += vshape(j, i) * vk[i];
00486          I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj;
00487       }
00488    }
00489 }
00490 
00491 void VectorFiniteElement::LocalInterpolation_ND(
00492    const double *tk, const Array<int> &d2t, ElementTransformation &Trans,
00493    DenseMatrix &I) const
00494 {
00495    double vk[3];
00496    Vector xk(vk, Dim);
00497    IntegrationPoint ip;
00498 #ifdef MFEM_USE_OPENMP
00499    DenseMatrix vshape(Dof, Dim);
00500 #endif
00501 
00502    // assuming Trans is linear; this should be ok for all refinement types
00503    Trans.SetIntPoint(&Geometries.GetCenter(GeomType));
00504    const DenseMatrix &J = Trans.Jacobian();
00505    for (int k = 0; k < Dof; k++)
00506    {
00507       Trans.Transform(Nodes.IntPoint(k), xk);
00508       ip.Set3(vk);
00509       CalcVShape(ip, vshape);
00510       // xk = J t_k
00511       J.Mult(tk + d2t[k]*Dim, vk);
00512       // I_k = vshape_k.J.t_k, k=1,...,Dof
00513       for (int j = 0; j < Dof; j++)
00514       {
00515          double Ikj = 0.;
00516          for (int i = 0; i < Dim; i++)
00517             Ikj += vshape(j, i) * vk[i];
00518          I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj;
00519       }
00520    }
00521 }
00522 
00523 
00524 PointFiniteElement::PointFiniteElement()
00525    : NodalFiniteElement(0, Geometry::POINT, 1, 0)
00526 {
00527    Nodes.IntPoint(0).x = 0.0;
00528 }
00529 
00530 void PointFiniteElement::CalcShape(const IntegrationPoint &ip,
00531                                    Vector &shape) const
00532 {
00533    shape(0) = 1.;
00534 }
00535 
00536 void PointFiniteElement::CalcDShape(const IntegrationPoint &ip,
00537                                     DenseMatrix &dshape) const
00538 {
00539    // doesn't make sense
00540 }
00541 
00542 Linear1DFiniteElement::Linear1DFiniteElement()
00543    : NodalFiniteElement(1, Geometry::SEGMENT, 2, 1)
00544 {
00545    Nodes.IntPoint(0).x = 0.0;
00546    Nodes.IntPoint(1).x = 1.0;
00547 }
00548 
00549 void Linear1DFiniteElement::CalcShape(const IntegrationPoint &ip,
00550                                       Vector &shape) const
00551 {
00552    shape(0) = 1. - ip.x;
00553    shape(1) = ip.x;
00554 }
00555 
00556 void Linear1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00557                                        DenseMatrix &dshape) const
00558 {
00559    dshape(0,0) = -1.;
00560    dshape(1,0) =  1.;
00561 }
00562 
00563 Linear2DFiniteElement::Linear2DFiniteElement()
00564    : NodalFiniteElement(2, Geometry::TRIANGLE, 3, 1)
00565 {
00566    Nodes.IntPoint(0).x = 0.0;
00567    Nodes.IntPoint(0).y = 0.0;
00568    Nodes.IntPoint(1).x = 1.0;
00569    Nodes.IntPoint(1).y = 0.0;
00570    Nodes.IntPoint(2).x = 0.0;
00571    Nodes.IntPoint(2).y = 1.0;
00572 }
00573 
00574 void Linear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
00575                                       Vector &shape) const
00576 {
00577    shape(0) = 1. - ip.x - ip.y;
00578    shape(1) = ip.x;
00579    shape(2) = ip.y;
00580 }
00581 
00582 void Linear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00583                                        DenseMatrix &dshape) const
00584 {
00585    dshape(0,0) = -1.; dshape(0,1) = -1.;
00586    dshape(1,0) =  1.; dshape(1,1) =  0.;
00587    dshape(2,0) =  0.; dshape(2,1) =  1.;
00588 }
00589 
00590 BiLinear2DFiniteElement::BiLinear2DFiniteElement()
00591    : NodalFiniteElement(2, Geometry::SQUARE , 4, 1, FunctionSpace::Qk)
00592 {
00593    Nodes.IntPoint(0).x = 0.0;
00594    Nodes.IntPoint(0).y = 0.0;
00595    Nodes.IntPoint(1).x = 1.0;
00596    Nodes.IntPoint(1).y = 0.0;
00597    Nodes.IntPoint(2).x = 1.0;
00598    Nodes.IntPoint(2).y = 1.0;
00599    Nodes.IntPoint(3).x = 0.0;
00600    Nodes.IntPoint(3).y = 1.0;
00601 }
00602 
00603 void BiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
00604                                         Vector &shape) const
00605 {
00606    shape(0) = (1. - ip.x) * (1. - ip.y) ;
00607    shape(1) = ip.x * (1. - ip.y) ;
00608    shape(2) = ip.x * ip.y ;
00609    shape(3) = (1. - ip.x) * ip.y ;
00610 }
00611 
00612 void BiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00613                                          DenseMatrix &dshape) const
00614 {
00615    dshape(0,0) = -1. + ip.y; dshape(0,1) = -1. + ip.x ;
00616    dshape(1,0) =  1. - ip.y; dshape(1,1) = -ip.x ;
00617    dshape(2,0) =  ip.y ;     dshape(2,1) = ip.x ;
00618    dshape(3,0) = -ip.y ;     dshape(3,1) = 1. - ip.x ;
00619 }
00620 
00621 void BiLinear2DFiniteElement::CalcHessian(
00622    const IntegrationPoint &ip, DenseMatrix &h) const
00623 {
00624    h( 0,0) = 0.;   h( 0,1) =  1.;   h( 0,2) = 0.;
00625    h( 1,0) = 0.;   h( 1,1) = -1.;   h( 1,2) = 0.;
00626    h( 2,0) = 0.;   h( 2,1) =  1.;   h( 2,2) = 0.;
00627    h( 3,0) = 0.;   h( 3,1) = -1.;   h( 3,2) = 0.;
00628 }
00629 
00630 
00631 GaussLinear2DFiniteElement::GaussLinear2DFiniteElement()
00632    : NodalFiniteElement(2, Geometry::TRIANGLE, 3, 1, FunctionSpace::Pk)
00633 {
00634    Nodes.IntPoint(0).x = 1./6.;
00635    Nodes.IntPoint(0).y = 1./6.;
00636    Nodes.IntPoint(1).x = 2./3.;
00637    Nodes.IntPoint(1).y = 1./6.;
00638    Nodes.IntPoint(2).x = 1./6.;
00639    Nodes.IntPoint(2).y = 2./3.;
00640 }
00641 
00642 void GaussLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
00643                                            Vector &shape) const
00644 {
00645    const double x = ip.x, y = ip.y;
00646 
00647    shape(0) = 5./3. - 2. * (x + y);
00648    shape(1) = 2. * (x - 1./6.);
00649    shape(2) = 2. * (y - 1./6.);
00650 }
00651 
00652 void GaussLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00653                                             DenseMatrix &dshape) const
00654 {
00655    dshape(0,0) = -2.;  dshape(0,1) = -2.;
00656    dshape(1,0) =  2.;  dshape(1,1) =  0.;
00657    dshape(2,0) =  0.;  dshape(2,1) =  2.;
00658 }
00659 
00660 void GaussLinear2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
00661 {
00662    dofs(vertex)       = 2./3.;
00663    dofs((vertex+1)%3) = 1./6.;
00664    dofs((vertex+2)%3) = 1./6.;
00665 }
00666 
00667 
00668 // 0.5-0.5/sqrt(3) and 0.5+0.5/sqrt(3)
00669 const double GaussBiLinear2DFiniteElement::p[] =
00670 { 0.2113248654051871177454256, 0.7886751345948128822545744 };
00671 
00672 GaussBiLinear2DFiniteElement::GaussBiLinear2DFiniteElement()
00673    : NodalFiniteElement(2, Geometry::SQUARE, 4, 1, FunctionSpace::Qk)
00674 {
00675    Nodes.IntPoint(0).x = p[0];
00676    Nodes.IntPoint(0).y = p[0];
00677    Nodes.IntPoint(1).x = p[1];
00678    Nodes.IntPoint(1).y = p[0];
00679    Nodes.IntPoint(2).x = p[1];
00680    Nodes.IntPoint(2).y = p[1];
00681    Nodes.IntPoint(3).x = p[0];
00682    Nodes.IntPoint(3).y = p[1];
00683 }
00684 
00685 void GaussBiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
00686                                              Vector &shape) const
00687 {
00688    const double x = ip.x, y = ip.y;
00689 
00690    shape(0) = 3. * (p[1] - x) * (p[1] - y);
00691    shape(1) = 3. * (x - p[0]) * (p[1] - y);
00692    shape(2) = 3. * (x - p[0]) * (y - p[0]);
00693    shape(3) = 3. * (p[1] - x) * (y - p[0]);
00694 }
00695 
00696 void GaussBiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00697                                               DenseMatrix &dshape) const
00698 {
00699    const double x = ip.x, y = ip.y;
00700 
00701    dshape(0,0) = 3. * (y - p[1]);  dshape(0,1) = 3. * (x - p[1]);
00702    dshape(1,0) = 3. * (p[1] - y);  dshape(1,1) = 3. * (p[0] - x);
00703    dshape(2,0) = 3. * (y - p[0]);  dshape(2,1) = 3. * (x - p[0]);
00704    dshape(3,0) = 3. * (p[0] - y);  dshape(3,1) = 3. * (p[1] - x);
00705 }
00706 
00707 void GaussBiLinear2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
00708 {
00709 #if 1
00710    dofs(vertex)       = p[1]*p[1];
00711    dofs((vertex+1)%4) = p[0]*p[1];
00712    dofs((vertex+2)%4) = p[0]*p[0];
00713    dofs((vertex+3)%4) = p[0]*p[1];
00714 #else
00715    dofs = 1.0;
00716 #endif
00717 }
00718 
00719 
00720 P1OnQuadFiniteElement::P1OnQuadFiniteElement()
00721    : NodalFiniteElement(2, Geometry::SQUARE , 3, 1, FunctionSpace::Qk)
00722 {
00723    Nodes.IntPoint(0).x = 0.0;
00724    Nodes.IntPoint(0).y = 0.0;
00725    Nodes.IntPoint(1).x = 1.0;
00726    Nodes.IntPoint(1).y = 0.0;
00727    Nodes.IntPoint(2).x = 0.0;
00728    Nodes.IntPoint(2).y = 1.0;
00729 }
00730 
00731 void P1OnQuadFiniteElement::CalcShape(const IntegrationPoint &ip,
00732                                       Vector &shape) const
00733 {
00734    shape(0) = 1. - ip.x - ip.y;
00735    shape(1) = ip.x;
00736    shape(2) = ip.y;
00737 }
00738 
00739 void P1OnQuadFiniteElement::CalcDShape(const IntegrationPoint &ip,
00740                                        DenseMatrix &dshape) const
00741 {
00742    dshape(0,0) = -1.; dshape(0,1) = -1.;
00743    dshape(1,0) =  1.; dshape(1,1) =  0.;
00744    dshape(2,0) =  0.; dshape(2,1) =  1.;
00745 }
00746 
00747 
00748 Quad1DFiniteElement::Quad1DFiniteElement()
00749    : NodalFiniteElement(1, Geometry::SEGMENT, 3, 2)
00750 {
00751    Nodes.IntPoint(0).x = 0.0;
00752    Nodes.IntPoint(1).x = 1.0;
00753    Nodes.IntPoint(2).x = 0.5;
00754 }
00755 
00756 void Quad1DFiniteElement::CalcShape(const IntegrationPoint &ip,
00757                                     Vector &shape) const
00758 {
00759    double x = ip.x;
00760    double l1 = 1.0 - x, l2 = x, l3 = 2. * x - 1.;
00761 
00762    shape(0) = l1 * (-l3);
00763    shape(1) = l2 * l3;
00764    shape(2) = 4. * l1 * l2;
00765 }
00766 
00767 void Quad1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00768                                      DenseMatrix &dshape) const
00769 {
00770    double x = ip.x;
00771 
00772    dshape(0,0) = 4. * x - 3.;
00773    dshape(1,0) = 4. * x - 1.;
00774    dshape(2,0) = 4. - 8. * x;
00775 }
00776 
00777 
00778 QuadPos1DFiniteElement::QuadPos1DFiniteElement()
00779    : FiniteElement(1, Geometry::SEGMENT, 3, 2)
00780 {
00781    Nodes.IntPoint(0).x = 0.0;
00782    Nodes.IntPoint(1).x = 1.0;
00783    Nodes.IntPoint(2).x = 0.5;
00784 }
00785 
00786 void QuadPos1DFiniteElement::CalcShape(const IntegrationPoint &ip,
00787                                        Vector &shape) const
00788 {
00789    const double x = ip.x, x1 = 1. - x;
00790 
00791    shape(0) = x1 * x1;
00792    shape(1) = x * x;
00793    shape(2) = 2. * x * x1;
00794 }
00795 
00796 void QuadPos1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00797                                         DenseMatrix &dshape) const
00798 {
00799    const double x = ip.x;
00800 
00801    dshape(0,0) = 2. * x - 2.;
00802    dshape(1,0) = 2. * x;
00803    dshape(2,0) = 2. - 4. * x;
00804 }
00805 
00806 Quad2DFiniteElement::Quad2DFiniteElement()
00807    : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 2)
00808 {
00809    Nodes.IntPoint(0).x = 0.0;
00810    Nodes.IntPoint(0).y = 0.0;
00811    Nodes.IntPoint(1).x = 1.0;
00812    Nodes.IntPoint(1).y = 0.0;
00813    Nodes.IntPoint(2).x = 0.0;
00814    Nodes.IntPoint(2).y = 1.0;
00815    Nodes.IntPoint(3).x = 0.5;
00816    Nodes.IntPoint(3).y = 0.0;
00817    Nodes.IntPoint(4).x = 0.5;
00818    Nodes.IntPoint(4).y = 0.5;
00819    Nodes.IntPoint(5).x = 0.0;
00820    Nodes.IntPoint(5).y = 0.5;
00821 }
00822 
00823 void Quad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
00824                                     Vector &shape) const
00825 {
00826    double x = ip.x, y = ip.y;
00827    double l1 = 1.-x-y, l2 = x, l3 = y;
00828 
00829    shape(0) = l1 * (2. * l1 - 1.);
00830    shape(1) = l2 * (2. * l2 - 1.);
00831    shape(2) = l3 * (2. * l3 - 1.);
00832    shape(3) = 4. * l1 * l2;
00833    shape(4) = 4. * l2 * l3;
00834    shape(5) = 4. * l3 * l1;
00835 }
00836 
00837 void Quad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00838                                      DenseMatrix &dshape) const
00839 {
00840    double x = ip.x, y = ip.y;
00841 
00842    dshape(0,0) =
00843       dshape(0,1) = 4. * (x + y) - 3.;
00844 
00845    dshape(1,0) = 4. * x - 1.;
00846    dshape(1,1) = 0.;
00847 
00848    dshape(2,0) = 0.;
00849    dshape(2,1) = 4. * y - 1.;
00850 
00851    dshape(3,0) = -4. * (2. * x + y - 1.);
00852    dshape(3,1) = -4. * x;
00853 
00854    dshape(4,0) = 4. * y;
00855    dshape(4,1) = 4. * x;
00856 
00857    dshape(5,0) = -4. * y;
00858    dshape(5,1) = -4. * (x + 2. * y - 1.);
00859 }
00860 
00861 void Quad2DFiniteElement::CalcHessian (const IntegrationPoint &ip,
00862                                        DenseMatrix &h) const
00863 {
00864    h(0,0) = 4.;
00865    h(0,1) = 4.;
00866    h(0,2) = 4.;
00867 
00868    h(1,0) = 4.;
00869    h(1,1) = 0.;
00870    h(1,2) = 0.;
00871 
00872    h(2,0) = 0.;
00873    h(2,1) = 0.;
00874    h(2,2) = 4.;
00875 
00876    h(3,0) = -8.;
00877    h(3,1) = -4.;
00878    h(3,2) =  0.;
00879 
00880    h(4,0) = 0.;
00881    h(4,1) = 4.;
00882    h(4,2) = 0.;
00883 
00884    h(5,0) =  0.;
00885    h(5,1) = -4.;
00886    h(5,2) = -8.;
00887 }
00888 
00889 void Quad2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
00890 {
00891 #if 0
00892    dofs = 1.;
00893 #else
00894    dofs = 0.;
00895    dofs(vertex) = 1.;
00896    switch (vertex)
00897    {
00898    case 0: dofs(3) = 0.25; dofs(5) = 0.25; break;
00899    case 1: dofs(3) = 0.25; dofs(4) = 0.25; break;
00900    case 2: dofs(4) = 0.25; dofs(5) = 0.25; break;
00901    }
00902 #endif
00903 }
00904 
00905 
00906 const double GaussQuad2DFiniteElement::p[] =
00907 { 0.0915762135097707434595714634022015, 0.445948490915964886318329253883051 };
00908 
00909 GaussQuad2DFiniteElement::GaussQuad2DFiniteElement()
00910    : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 2), A(6), D(6,2), pol(6)
00911 {
00912    Nodes.IntPoint(0).x = p[0];
00913    Nodes.IntPoint(0).y = p[0];
00914    Nodes.IntPoint(1).x = 1. - 2. * p[0];
00915    Nodes.IntPoint(1).y = p[0];
00916    Nodes.IntPoint(2).x = p[0];
00917    Nodes.IntPoint(2).y = 1. - 2. * p[0];
00918    Nodes.IntPoint(3).x = p[1];
00919    Nodes.IntPoint(3).y = p[1];
00920    Nodes.IntPoint(4).x = 1. - 2. * p[1];
00921    Nodes.IntPoint(4).y = p[1];
00922    Nodes.IntPoint(5).x = p[1];
00923    Nodes.IntPoint(5).y = 1. - 2. * p[1];
00924 
00925    for (int i = 0; i < 6; i++)
00926    {
00927       const double x = Nodes.IntPoint(i).x, y = Nodes.IntPoint(i).y;
00928       A(0,i) = 1.;
00929       A(1,i) = x;
00930       A(2,i) = y;
00931       A(3,i) = x * x;
00932       A(4,i) = x * y;
00933       A(5,i) = y * y;
00934    }
00935 
00936    A.Invert();
00937 }
00938 
00939 void GaussQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
00940                                          Vector &shape) const
00941 {
00942    const double x = ip.x, y = ip.y;
00943    pol(0) = 1.;
00944    pol(1) = x;
00945    pol(2) = y;
00946    pol(3) = x * x;
00947    pol(4) = x * y;
00948    pol(5) = y * y;
00949 
00950    A.Mult(pol, shape);
00951 }
00952 
00953 void GaussQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
00954                                           DenseMatrix &dshape) const
00955 {
00956    const double x = ip.x, y = ip.y;
00957    D(0,0) = 0.;      D(0,1) = 0.;
00958    D(1,0) = 1.;      D(1,1) = 0.;
00959    D(2,0) = 0.;      D(2,1) = 1.;
00960    D(3,0) = 2. *  x; D(3,1) = 0.;
00961    D(4,0) = y;       D(4,1) = x;
00962    D(5,0) = 0.;      D(5,1) = 2. * y;
00963 
00964    Mult(A, D, dshape);
00965 }
00966 
00967 
00968 BiQuad2DFiniteElement::BiQuad2DFiniteElement()
00969    : NodalFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk)
00970 {
00971    Nodes.IntPoint(0).x = 0.0;
00972    Nodes.IntPoint(0).y = 0.0;
00973    Nodes.IntPoint(1).x = 1.0;
00974    Nodes.IntPoint(1).y = 0.0;
00975    Nodes.IntPoint(2).x = 1.0;
00976    Nodes.IntPoint(2).y = 1.0;
00977    Nodes.IntPoint(3).x = 0.0;
00978    Nodes.IntPoint(3).y = 1.0;
00979    Nodes.IntPoint(4).x = 0.5;
00980    Nodes.IntPoint(4).y = 0.0;
00981    Nodes.IntPoint(5).x = 1.0;
00982    Nodes.IntPoint(5).y = 0.5;
00983    Nodes.IntPoint(6).x = 0.5;
00984    Nodes.IntPoint(6).y = 1.0;
00985    Nodes.IntPoint(7).x = 0.0;
00986    Nodes.IntPoint(7).y = 0.5;
00987    Nodes.IntPoint(8).x = 0.5;
00988    Nodes.IntPoint(8).y = 0.5;
00989 }
00990 
00991 void BiQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
00992                                       Vector &shape) const
00993 {
00994    double x = ip.x, y = ip.y;
00995    double l1x, l2x, l3x, l1y, l2y, l3y;
00996 
00997    l1x = (x - 1.) * (2. * x - 1);
00998    l2x = 4. * x * (1. - x);
00999    l3x = x * (2. * x - 1.);
01000    l1y = (y - 1.) * (2. * y - 1);
01001    l2y = 4. * y * (1. - y);
01002    l3y = y * (2. * y - 1.);
01003 
01004    shape(0) = l1x * l1y;
01005    shape(4) = l2x * l1y;
01006    shape(1) = l3x * l1y;
01007    shape(7) = l1x * l2y;
01008    shape(8) = l2x * l2y;
01009    shape(5) = l3x * l2y;
01010    shape(3) = l1x * l3y;
01011    shape(6) = l2x * l3y;
01012    shape(2) = l3x * l3y;
01013 }
01014 
01015 void BiQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01016                                        DenseMatrix &dshape) const
01017 {
01018    double x = ip.x, y = ip.y;
01019    double l1x, l2x, l3x, l1y, l2y, l3y;
01020    double d1x, d2x, d3x, d1y, d2y, d3y;
01021 
01022    l1x = (x - 1.) * (2. * x - 1);
01023    l2x = 4. * x * (1. - x);
01024    l3x = x * (2. * x - 1.);
01025    l1y = (y - 1.) * (2. * y - 1);
01026    l2y = 4. * y * (1. - y);
01027    l3y = y * (2. * y - 1.);
01028 
01029    d1x = 4. * x - 3.;
01030    d2x = 4. - 8. * x;
01031    d3x = 4. * x - 1.;
01032    d1y = 4. * y - 3.;
01033    d2y = 4. - 8. * y;
01034    d3y = 4. * y - 1.;
01035 
01036    dshape(0,0) = d1x * l1y;
01037    dshape(0,1) = l1x * d1y;
01038 
01039    dshape(4,0) = d2x * l1y;
01040    dshape(4,1) = l2x * d1y;
01041 
01042    dshape(1,0) = d3x * l1y;
01043    dshape(1,1) = l3x * d1y;
01044 
01045    dshape(7,0) = d1x * l2y;
01046    dshape(7,1) = l1x * d2y;
01047 
01048    dshape(8,0) = d2x * l2y;
01049    dshape(8,1) = l2x * d2y;
01050 
01051    dshape(5,0) = d3x * l2y;
01052    dshape(5,1) = l3x * d2y;
01053 
01054    dshape(3,0) = d1x * l3y;
01055    dshape(3,1) = l1x * d3y;
01056 
01057    dshape(6,0) = d2x * l3y;
01058    dshape(6,1) = l2x * d3y;
01059 
01060    dshape(2,0) = d3x * l3y;
01061    dshape(2,1) = l3x * d3y;
01062 }
01063 
01064 void BiQuad2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
01065 {
01066 #if 0
01067    dofs = 1.;
01068 #else
01069    dofs = 0.;
01070    dofs(vertex) = 1.;
01071    switch (vertex)
01072    {
01073    case 0: dofs(4) = 0.25; dofs(7) = 0.25; break;
01074    case 1: dofs(4) = 0.25; dofs(5) = 0.25; break;
01075    case 2: dofs(5) = 0.25; dofs(6) = 0.25; break;
01076    case 3: dofs(6) = 0.25; dofs(7) = 0.25; break;
01077    }
01078    dofs(8) = 1./16.;
01079 #endif
01080 }
01081 
01082 BiQuadPos2DFiniteElement::BiQuadPos2DFiniteElement()
01083    : FiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk)
01084 {
01085    Nodes.IntPoint(0).x = 0.0;
01086    Nodes.IntPoint(0).y = 0.0;
01087    Nodes.IntPoint(1).x = 1.0;
01088    Nodes.IntPoint(1).y = 0.0;
01089    Nodes.IntPoint(2).x = 1.0;
01090    Nodes.IntPoint(2).y = 1.0;
01091    Nodes.IntPoint(3).x = 0.0;
01092    Nodes.IntPoint(3).y = 1.0;
01093    Nodes.IntPoint(4).x = 0.5;
01094    Nodes.IntPoint(4).y = 0.0;
01095    Nodes.IntPoint(5).x = 1.0;
01096    Nodes.IntPoint(5).y = 0.5;
01097    Nodes.IntPoint(6).x = 0.5;
01098    Nodes.IntPoint(6).y = 1.0;
01099    Nodes.IntPoint(7).x = 0.0;
01100    Nodes.IntPoint(7).y = 0.5;
01101    Nodes.IntPoint(8).x = 0.5;
01102    Nodes.IntPoint(8).y = 0.5;
01103 }
01104 
01105 void BiQuadPos2DFiniteElement::CalcShape(const IntegrationPoint &ip,
01106                                          Vector &shape) const
01107 {
01108    double x = ip.x, y = ip.y;
01109    double l1x, l2x, l3x, l1y, l2y, l3y;
01110 
01111    l1x = (1. - x) * (1. - x);
01112    l2x = 2. * x * (1. - x);
01113    l3x = x * x;
01114    l1y = (1. - y) * (1. - y);
01115    l2y = 2. * y * (1. - y);
01116    l3y = y * y;
01117 
01118    shape(0) = l1x * l1y;
01119    shape(4) = l2x * l1y;
01120    shape(1) = l3x * l1y;
01121    shape(7) = l1x * l2y;
01122    shape(8) = l2x * l2y;
01123    shape(5) = l3x * l2y;
01124    shape(3) = l1x * l3y;
01125    shape(6) = l2x * l3y;
01126    shape(2) = l3x * l3y;
01127 }
01128 
01129 void BiQuadPos2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01130                                           DenseMatrix &dshape) const
01131 {
01132    double x = ip.x, y = ip.y;
01133    double l1x, l2x, l3x, l1y, l2y, l3y;
01134    double d1x, d2x, d3x, d1y, d2y, d3y;
01135 
01136    l1x = (1. - x) * (1. - x);
01137    l2x = 2. * x * (1. - x);
01138    l3x = x * x;
01139    l1y = (1. - y) * (1. - y);
01140    l2y = 2. * y * (1. - y);
01141    l3y = y * y;
01142 
01143    d1x = 2. * x - 2.;
01144    d2x = 2. - 4. * x;
01145    d3x = 2. * x;
01146    d1y = 2. * y - 2.;
01147    d2y = 2. - 4. * y;
01148    d3y = 2. * y;
01149 
01150    dshape(0,0) = d1x * l1y;
01151    dshape(0,1) = l1x * d1y;
01152 
01153    dshape(4,0) = d2x * l1y;
01154    dshape(4,1) = l2x * d1y;
01155 
01156    dshape(1,0) = d3x * l1y;
01157    dshape(1,1) = l3x * d1y;
01158 
01159    dshape(7,0) = d1x * l2y;
01160    dshape(7,1) = l1x * d2y;
01161 
01162    dshape(8,0) = d2x * l2y;
01163    dshape(8,1) = l2x * d2y;
01164 
01165    dshape(5,0) = d3x * l2y;
01166    dshape(5,1) = l3x * d2y;
01167 
01168    dshape(3,0) = d1x * l3y;
01169    dshape(3,1) = l1x * d3y;
01170 
01171    dshape(6,0) = d2x * l3y;
01172    dshape(6,1) = l2x * d3y;
01173 
01174    dshape(2,0) = d3x * l3y;
01175    dshape(2,1) = l3x * d3y;
01176 }
01177 
01178 void BiQuadPos2DFiniteElement::Project(
01179    Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
01180 {
01181    double *d = dofs;
01182 
01183    for (int i = 0; i < 9; i++)
01184    {
01185       const IntegrationPoint &ip = Nodes.IntPoint(i);
01186       Trans.SetIntPoint(&ip);
01187       d[i] = coeff.Eval(Trans, ip);
01188    }
01189    d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
01190    d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
01191    d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
01192    d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
01193    d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
01194       0.25 * (d[0] + d[1] + d[2] + d[3]);
01195 }
01196 
01197 void BiQuadPos2DFiniteElement::Project (
01198    VectorCoefficient &vc, ElementTransformation &Trans,
01199    Vector &dofs) const
01200 {
01201    double v[3];
01202    Vector x (v, vc.GetVDim());
01203 
01204    for (int i = 0; i < 9; i++)
01205    {
01206       const IntegrationPoint &ip = Nodes.IntPoint(i);
01207       Trans.SetIntPoint(&ip);
01208       vc.Eval (x, Trans, ip);
01209       for (int j = 0; j < x.Size(); j++)
01210          dofs(9*j+i) = v[j];
01211    }
01212    for (int j = 0; j < x.Size(); j++)
01213    {
01214       double *d = &dofs(9*j);
01215 
01216       d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
01217       d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
01218       d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
01219       d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
01220       d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
01221          0.25 * (d[0] + d[1] + d[2] + d[3]);
01222    }
01223 }
01224 
01225 
01226 GaussBiQuad2DFiniteElement::GaussBiQuad2DFiniteElement()
01227    : NodalFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk)
01228 {
01229    const double p1 = 0.5*(1.-sqrt(3./5.));
01230 
01231    Nodes.IntPoint(0).x = p1;
01232    Nodes.IntPoint(0).y = p1;
01233    Nodes.IntPoint(4).x = 0.5;
01234    Nodes.IntPoint(4).y = p1;
01235    Nodes.IntPoint(1).x = 1.-p1;
01236    Nodes.IntPoint(1).y = p1;
01237    Nodes.IntPoint(7).x = p1;
01238    Nodes.IntPoint(7).y = 0.5;
01239    Nodes.IntPoint(8).x = 0.5;
01240    Nodes.IntPoint(8).y = 0.5;
01241    Nodes.IntPoint(5).x = 1.-p1;
01242    Nodes.IntPoint(5).y = 0.5;
01243    Nodes.IntPoint(3).x = p1;
01244    Nodes.IntPoint(3).y = 1.-p1;
01245    Nodes.IntPoint(6).x = 0.5;
01246    Nodes.IntPoint(6).y = 1.-p1;
01247    Nodes.IntPoint(2).x = 1.-p1;
01248    Nodes.IntPoint(2).y = 1.-p1;
01249 }
01250 
01251 void GaussBiQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
01252                                            Vector &shape) const
01253 {
01254    const double a = sqrt(5./3.);
01255    const double p1 = 0.5*(1.-sqrt(3./5.));
01256 
01257    double x = a*(ip.x-p1), y = a*(ip.y-p1);
01258    double l1x, l2x, l3x, l1y, l2y, l3y;
01259 
01260    l1x = (x - 1.) * (2. * x - 1);
01261    l2x = 4. * x * (1. - x);
01262    l3x = x * (2. * x - 1.);
01263    l1y = (y - 1.) * (2. * y - 1);
01264    l2y = 4. * y * (1. - y);
01265    l3y = y * (2. * y - 1.);
01266 
01267    shape(0) = l1x * l1y;
01268    shape(4) = l2x * l1y;
01269    shape(1) = l3x * l1y;
01270    shape(7) = l1x * l2y;
01271    shape(8) = l2x * l2y;
01272    shape(5) = l3x * l2y;
01273    shape(3) = l1x * l3y;
01274    shape(6) = l2x * l3y;
01275    shape(2) = l3x * l3y;
01276 }
01277 
01278 void GaussBiQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01279                                             DenseMatrix &dshape) const
01280 {
01281    const double a = sqrt(5./3.);
01282    const double p1 = 0.5*(1.-sqrt(3./5.));
01283 
01284    double x = a*(ip.x-p1), y = a*(ip.y-p1);
01285    double l1x, l2x, l3x, l1y, l2y, l3y;
01286    double d1x, d2x, d3x, d1y, d2y, d3y;
01287 
01288    l1x = (x - 1.) * (2. * x - 1);
01289    l2x = 4. * x * (1. - x);
01290    l3x = x * (2. * x - 1.);
01291    l1y = (y - 1.) * (2. * y - 1);
01292    l2y = 4. * y * (1. - y);
01293    l3y = y * (2. * y - 1.);
01294 
01295    d1x = a * (4. * x - 3.);
01296    d2x = a * (4. - 8. * x);
01297    d3x = a * (4. * x - 1.);
01298    d1y = a * (4. * y - 3.);
01299    d2y = a * (4. - 8. * y);
01300    d3y = a * (4. * y - 1.);
01301 
01302    dshape(0,0) = d1x * l1y;
01303    dshape(0,1) = l1x * d1y;
01304 
01305    dshape(4,0) = d2x * l1y;
01306    dshape(4,1) = l2x * d1y;
01307 
01308    dshape(1,0) = d3x * l1y;
01309    dshape(1,1) = l3x * d1y;
01310 
01311    dshape(7,0) = d1x * l2y;
01312    dshape(7,1) = l1x * d2y;
01313 
01314    dshape(8,0) = d2x * l2y;
01315    dshape(8,1) = l2x * d2y;
01316 
01317    dshape(5,0) = d3x * l2y;
01318    dshape(5,1) = l3x * d2y;
01319 
01320    dshape(3,0) = d1x * l3y;
01321    dshape(3,1) = l1x * d3y;
01322 
01323    dshape(6,0) = d2x * l3y;
01324    dshape(6,1) = l2x * d3y;
01325 
01326    dshape(2,0) = d3x * l3y;
01327    dshape(2,1) = l3x * d3y;
01328 }
01329 
01330 BiCubic2DFiniteElement::BiCubic2DFiniteElement()
01331    : NodalFiniteElement (2, Geometry::SQUARE, 16, 3, FunctionSpace::Qk)
01332 {
01333    Nodes.IntPoint(0).x = 0.;
01334    Nodes.IntPoint(0).y = 0.;
01335    Nodes.IntPoint(1).x = 1.;
01336    Nodes.IntPoint(1).y = 0.;
01337    Nodes.IntPoint(2).x = 1.;
01338    Nodes.IntPoint(2).y = 1.;
01339    Nodes.IntPoint(3).x = 0.;
01340    Nodes.IntPoint(3).y = 1.;
01341    Nodes.IntPoint(4).x = 1./3.;
01342    Nodes.IntPoint(4).y = 0.;
01343    Nodes.IntPoint(5).x = 2./3.;
01344    Nodes.IntPoint(5).y = 0.;
01345    Nodes.IntPoint(6).x = 1.;
01346    Nodes.IntPoint(6).y = 1./3.;
01347    Nodes.IntPoint(7).x = 1.;
01348    Nodes.IntPoint(7).y = 2./3.;
01349    Nodes.IntPoint(8).x = 2./3.;
01350    Nodes.IntPoint(8).y = 1.;
01351    Nodes.IntPoint(9).x = 1./3.;
01352    Nodes.IntPoint(9).y = 1.;
01353    Nodes.IntPoint(10).x = 0.;
01354    Nodes.IntPoint(10).y = 2./3.;
01355    Nodes.IntPoint(11).x = 0.;
01356    Nodes.IntPoint(11).y = 1./3.;
01357    Nodes.IntPoint(12).x = 1./3.;
01358    Nodes.IntPoint(12).y = 1./3.;
01359    Nodes.IntPoint(13).x = 2./3.;
01360    Nodes.IntPoint(13).y = 1./3.;
01361    Nodes.IntPoint(14).x = 1./3.;
01362    Nodes.IntPoint(14).y = 2./3.;
01363    Nodes.IntPoint(15).x = 2./3.;
01364    Nodes.IntPoint(15).y = 2./3.;
01365 }
01366 
01367 void BiCubic2DFiniteElement::CalcShape(
01368    const IntegrationPoint &ip, Vector &shape) const
01369 {
01370    double x = ip.x, y = ip.y;
01371 
01372    double w1x, w2x, w3x, w1y, w2y, w3y;
01373    double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y;
01374 
01375    w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.;
01376    w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.;
01377 
01378    l0x = (- 4.5) * w1x * w2x * w3x;
01379    l1x = ( 13.5) *   x * w2x * w3x;
01380    l2x = (-13.5) *   x * w1x * w3x;
01381    l3x = (  4.5) *   x * w1x * w2x;
01382 
01383    l0y = (- 4.5) * w1y * w2y * w3y;
01384    l1y = ( 13.5) *   y * w2y * w3y;
01385    l2y = (-13.5) *   y * w1y * w3y;
01386    l3y = (  4.5) *   y * w1y * w2y;
01387 
01388    shape(0)  = l0x * l0y;
01389    shape(1)  = l3x * l0y;
01390    shape(2)  = l3x * l3y;
01391    shape(3)  = l0x * l3y;
01392    shape(4)  = l1x * l0y;
01393    shape(5)  = l2x * l0y;
01394    shape(6)  = l3x * l1y;
01395    shape(7)  = l3x * l2y;
01396    shape(8)  = l2x * l3y;
01397    shape(9)  = l1x * l3y;
01398    shape(10) = l0x * l2y;
01399    shape(11) = l0x * l1y;
01400    shape(12) = l1x * l1y;
01401    shape(13) = l2x * l1y;
01402    shape(14) = l1x * l2y;
01403    shape(15) = l2x * l2y;
01404 }
01405 
01406 void BiCubic2DFiniteElement::CalcDShape(
01407    const IntegrationPoint &ip, DenseMatrix &dshape) const
01408 {
01409    double x = ip.x, y = ip.y;
01410 
01411    double w1x, w2x, w3x, w1y, w2y, w3y;
01412    double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y;
01413    double d0x, d1x, d2x, d3x, d0y, d1y, d2y, d3y;
01414 
01415    w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.;
01416    w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.;
01417 
01418    l0x = (- 4.5) * w1x * w2x * w3x;
01419    l1x = ( 13.5) *   x * w2x * w3x;
01420    l2x = (-13.5) *   x * w1x * w3x;
01421    l3x = (  4.5) *   x * w1x * w2x;
01422 
01423    l0y = (- 4.5) * w1y * w2y * w3y;
01424    l1y = ( 13.5) *   y * w2y * w3y;
01425    l2y = (-13.5) *   y * w1y * w3y;
01426    l3y = (  4.5) *   y * w1y * w2y;
01427 
01428    d0x = -5.5 + ( 18. - 13.5 * x) * x;
01429    d1x =  9.  + (-45. + 40.5 * x) * x;
01430    d2x = -4.5 + ( 36. - 40.5 * x) * x;
01431    d3x =  1.  + (- 9. + 13.5 * x) * x;
01432 
01433    d0y = -5.5 + ( 18. - 13.5 * y) * y;
01434    d1y =  9.  + (-45. + 40.5 * y) * y;
01435    d2y = -4.5 + ( 36. - 40.5 * y) * y;
01436    d3y =  1.  + (- 9. + 13.5 * y) * y;
01437 
01438    dshape( 0,0) = d0x * l0y;   dshape( 0,1) = l0x * d0y;
01439    dshape( 1,0) = d3x * l0y;   dshape( 1,1) = l3x * d0y;
01440    dshape( 2,0) = d3x * l3y;   dshape( 2,1) = l3x * d3y;
01441    dshape( 3,0) = d0x * l3y;   dshape( 3,1) = l0x * d3y;
01442    dshape( 4,0) = d1x * l0y;   dshape( 4,1) = l1x * d0y;
01443    dshape( 5,0) = d2x * l0y;   dshape( 5,1) = l2x * d0y;
01444    dshape( 6,0) = d3x * l1y;   dshape( 6,1) = l3x * d1y;
01445    dshape( 7,0) = d3x * l2y;   dshape( 7,1) = l3x * d2y;
01446    dshape( 8,0) = d2x * l3y;   dshape( 8,1) = l2x * d3y;
01447    dshape( 9,0) = d1x * l3y;   dshape( 9,1) = l1x * d3y;
01448    dshape(10,0) = d0x * l2y;   dshape(10,1) = l0x * d2y;
01449    dshape(11,0) = d0x * l1y;   dshape(11,1) = l0x * d1y;
01450    dshape(12,0) = d1x * l1y;   dshape(12,1) = l1x * d1y;
01451    dshape(13,0) = d2x * l1y;   dshape(13,1) = l2x * d1y;
01452    dshape(14,0) = d1x * l2y;   dshape(14,1) = l1x * d2y;
01453    dshape(15,0) = d2x * l2y;   dshape(15,1) = l2x * d2y;
01454 }
01455 
01456 void BiCubic2DFiniteElement::CalcHessian(
01457    const IntegrationPoint &ip, DenseMatrix &h) const
01458 {
01459    double x = ip.x, y = ip.y;
01460 
01461    double w1x, w2x, w3x, w1y, w2y, w3y;
01462    double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y;
01463    double d0x, d1x, d2x, d3x, d0y, d1y, d2y, d3y;
01464    double h0x, h1x, h2x, h3x, h0y, h1y, h2y, h3y;
01465 
01466    w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.;
01467    w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.;
01468 
01469    l0x = (- 4.5) * w1x * w2x * w3x;
01470    l1x = ( 13.5) *   x * w2x * w3x;
01471    l2x = (-13.5) *   x * w1x * w3x;
01472    l3x = (  4.5) *   x * w1x * w2x;
01473 
01474    l0y = (- 4.5) * w1y * w2y * w3y;
01475    l1y = ( 13.5) *   y * w2y * w3y;
01476    l2y = (-13.5) *   y * w1y * w3y;
01477    l3y = (  4.5) *   y * w1y * w2y;
01478 
01479    d0x = -5.5 + ( 18. - 13.5 * x) * x;
01480    d1x =  9.  + (-45. + 40.5 * x) * x;
01481    d2x = -4.5 + ( 36. - 40.5 * x) * x;
01482    d3x =  1.  + (- 9. + 13.5 * x) * x;
01483 
01484    d0y = -5.5 + ( 18. - 13.5 * y) * y;
01485    d1y =  9.  + (-45. + 40.5 * y) * y;
01486    d2y = -4.5 + ( 36. - 40.5 * y) * y;
01487    d3y =  1.  + (- 9. + 13.5 * y) * y;
01488 
01489    h0x = -27. * x + 18.;
01490    h1x =  81. * x - 45.;
01491    h2x = -81. * x + 36.;
01492    h3x =  27. * x -  9.;
01493 
01494    h0y = -27. * y + 18.;
01495    h1y =  81. * y - 45.;
01496    h2y = -81. * y + 36.;
01497    h3y =  27. * y -  9.;
01498 
01499    h( 0,0) = h0x * l0y;   h( 0,1) = d0x * d0y;   h( 0,2) = l0x * h0y;
01500    h( 1,0) = h3x * l0y;   h( 1,1) = d3x * d0y;   h( 1,2) = l3x * h0y;
01501    h( 2,0) = h3x * l3y;   h( 2,1) = d3x * d3y;   h( 2,2) = l3x * h3y;
01502    h( 3,0) = h0x * l3y;   h( 3,1) = d0x * d3y;   h( 3,2) = l0x * h3y;
01503    h( 4,0) = h1x * l0y;   h( 4,1) = d1x * d0y;   h( 4,2) = l1x * h0y;
01504    h( 5,0) = h2x * l0y;   h( 5,1) = d2x * d0y;   h( 5,2) = l2x * h0y;
01505    h( 6,0) = h3x * l1y;   h( 6,1) = d3x * d1y;   h( 6,2) = l3x * h1y;
01506    h( 7,0) = h3x * l2y;   h( 7,1) = d3x * d2y;   h( 7,2) = l3x * h2y;
01507    h( 8,0) = h2x * l3y;   h( 8,1) = d2x * d3y;   h( 8,2) = l2x * h3y;
01508    h( 9,0) = h1x * l3y;   h( 9,1) = d1x * d3y;   h( 9,2) = l1x * h3y;
01509    h(10,0) = h0x * l2y;   h(10,1) = d0x * d2y;   h(10,2) = l0x * h2y;
01510    h(11,0) = h0x * l1y;   h(11,1) = d0x * d1y;   h(11,2) = l0x * h1y;
01511    h(12,0) = h1x * l1y;   h(12,1) = d1x * d1y;   h(12,2) = l1x * h1y;
01512    h(13,0) = h2x * l1y;   h(13,1) = d2x * d1y;   h(13,2) = l2x * h1y;
01513    h(14,0) = h1x * l2y;   h(14,1) = d1x * d2y;   h(14,2) = l1x * h2y;
01514    h(15,0) = h2x * l2y;   h(15,1) = d2x * d2y;   h(15,2) = l2x * h2y;
01515 }
01516 
01517 
01518 Cubic1DFiniteElement::Cubic1DFiniteElement()
01519    : NodalFiniteElement(1, Geometry::SEGMENT, 4, 3)
01520 {
01521    Nodes.IntPoint(0).x = 0.0;
01522    Nodes.IntPoint(1).x = 1.0;
01523    Nodes.IntPoint(2).x = 0.33333333333333333333;
01524    Nodes.IntPoint(3).x = 0.66666666666666666667;
01525 }
01526 
01527 void Cubic1DFiniteElement::CalcShape(const IntegrationPoint &ip,
01528                                      Vector &shape) const
01529 {
01530    double x = ip.x;
01531    double l1 = x,
01532       l2 = (1.0-x),
01533       l3 = (0.33333333333333333333-x),
01534       l4 = (0.66666666666666666667-x);
01535 
01536    shape(0) =   4.5 * l2 * l3 * l4;
01537    shape(1) =   4.5 * l1 * l3 * l4;
01538    shape(2) =  13.5 * l1 * l2 * l4;
01539    shape(3) = -13.5 * l1 * l2 * l3;
01540 }
01541 
01542 void Cubic1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01543                                       DenseMatrix &dshape) const
01544 {
01545    double x = ip.x;
01546 
01547    dshape(0,0) = -5.5 + x * (18. - 13.5 * x);
01548    dshape(1,0) = 1. - x * (9. - 13.5 * x);
01549    dshape(2,0) = 9. - x * (45. - 40.5 * x);
01550    dshape(3,0) = -4.5 + x * (36. - 40.5 * x);
01551 }
01552 
01553 
01554 Cubic2DFiniteElement::Cubic2DFiniteElement()
01555    : NodalFiniteElement(2, Geometry::TRIANGLE, 10, 3)
01556 {
01557    Nodes.IntPoint(0).x = 0.0;
01558    Nodes.IntPoint(0).y = 0.0;
01559    Nodes.IntPoint(1).x = 1.0;
01560    Nodes.IntPoint(1).y = 0.0;
01561    Nodes.IntPoint(2).x = 0.0;
01562    Nodes.IntPoint(2).y = 1.0;
01563    Nodes.IntPoint(3).x = 0.33333333333333333333;
01564    Nodes.IntPoint(3).y = 0.0;
01565    Nodes.IntPoint(4).x = 0.66666666666666666667;
01566    Nodes.IntPoint(4).y = 0.0;
01567    Nodes.IntPoint(5).x = 0.66666666666666666667;
01568    Nodes.IntPoint(5).y = 0.33333333333333333333;
01569    Nodes.IntPoint(6).x = 0.33333333333333333333;
01570    Nodes.IntPoint(6).y = 0.66666666666666666667;
01571    Nodes.IntPoint(7).x = 0.0;
01572    Nodes.IntPoint(7).y = 0.66666666666666666667;
01573    Nodes.IntPoint(8).x = 0.0;
01574    Nodes.IntPoint(8).y = 0.33333333333333333333;
01575    Nodes.IntPoint(9).x = 0.33333333333333333333;
01576    Nodes.IntPoint(9).y = 0.33333333333333333333;
01577 }
01578 
01579 void Cubic2DFiniteElement::CalcShape(const IntegrationPoint &ip,
01580                                      Vector &shape) const
01581 {
01582    double x = ip.x, y = ip.y;
01583    double l1 = (-1. + x + y),
01584       lx = (-1. + 3.*x),
01585       ly = (-1. + 3.*y);
01586 
01587    shape(0) = -0.5*l1*(3.*l1 + 1.)*(3.*l1 + 2.);
01588    shape(1) =  0.5*x*(lx - 1.)*lx;
01589    shape(2) =  0.5*y*(-1. + ly)*ly;
01590    shape(3) =  4.5*x*l1*(3.*l1 + 1.);
01591    shape(4) = -4.5*x*lx*l1;
01592    shape(5) =  4.5*x*lx*y;
01593    shape(6) =  4.5*x*y*ly;
01594    shape(7) = -4.5*y*l1*ly;
01595    shape(8) =  4.5*y*l1*(1. + 3.*l1);
01596    shape(9) = -27.*x*y*l1;
01597 }
01598 
01599 void Cubic2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01600                                       DenseMatrix &dshape) const
01601 {
01602    double x = ip.x, y = ip.y;
01603 
01604    dshape(0,0) =  0.5*(-11. + 36.*y - 9.*(x*(-4. + 3.*x) + 6.*x*y + 3.*y*y));
01605    dshape(1,0) =  1. + 4.5*x*(-2. + 3.*x);
01606    dshape(2,0) =  0.;
01607    dshape(3,0) =  4.5*(2. + 9.*x*x - 5.*y + 3.*y*y + 2.*x*(-5. + 6.*y));
01608    dshape(4,0) = -4.5*(1. - 1.*y + x*(-8. + 9.*x + 6.*y));
01609    dshape(5,0) =  4.5*(-1. + 6.*x)*y;
01610    dshape(6,0) =  4.5*y*(-1. + 3.*y);
01611    dshape(7,0) =  4.5*(1. - 3.*y)*y;
01612    dshape(8,0) =  4.5*y*(-5. + 6.*x + 6.*y);
01613    dshape(9,0) =  -27.*y*(-1. + 2.*x + y);
01614 
01615    dshape(0,1) =  0.5*(-11. + 36.*y - 9.*(x*(-4. + 3.*x) + 6.*x*y + 3.*y*y));
01616    dshape(1,1) =  0.;
01617    dshape(2,1) =  1. + 4.5*y*(-2. + 3.*y);
01618    dshape(3,1) =  4.5*x*(-5. + 6.*x + 6.*y);
01619    dshape(4,1) =  4.5*(1. - 3.*x)*x;
01620    dshape(5,1) =  4.5*x*(-1. + 3.*x);
01621    dshape(6,1) =  4.5*x*(-1. + 6.*y);
01622    dshape(7,1) = -4.5*(1. + x*(-1. + 6.*y) + y*(-8. + 9.*y));
01623    dshape(8,1) =  4.5*(2. + 3.*x*x + y*(-10. + 9.*y) + x*(-5. + 12.*y));
01624    dshape(9,1) = -27.*x*(-1. + x + 2.*y);
01625 }
01626 
01627 void Cubic2DFiniteElement::CalcHessian (const IntegrationPoint &ip,
01628                                         DenseMatrix &h) const
01629 {
01630    double x = ip.x, y = ip.y;
01631 
01632    h(0,0) = 18.-27.*(x+y);
01633    h(0,1) = 18.-27.*(x+y);
01634    h(0,2) = 18.-27.*(x+y);
01635 
01636    h(1,0) = -9.+27.*x;
01637    h(1,1) = 0.;
01638    h(1,2) = 0.;
01639 
01640    h(2,0) = 0.;
01641    h(2,1) = 0.;
01642    h(2,2) = -9.+27.*y;
01643 
01644    h(3,0) = -45.+81.*x+54.*y;
01645    h(3,1) = -22.5+54.*x+27.*y;
01646    h(3,2) = 27.*x;
01647 
01648    h(4,0) = 36.-81.*x-27.*y;
01649    h(4,1) = 4.5-27.*x;
01650    h(4,2) = 0.;
01651 
01652    h(5,0) = 27.*y;
01653    h(5,1) = -4.5+27.*x;
01654    h(5,2) = 0.;
01655 
01656    h(6,0) = 0.;
01657    h(6,1) = -4.5+27.*y;
01658    h(6,2) = 27.*x;
01659 
01660    h(7,0) = 0.;
01661    h(7,1) = 4.5-27.*y;
01662    h(7,2) = 36.-27.*x-81.*y;
01663 
01664    h(8,0) = 27.*y;
01665    h(8,1) = -22.5+27.*x+54.*y;
01666    h(8,2) = -45.+54.*x+81.*y;
01667 
01668    h(9,0) = -54.*y;
01669    h(9,1) = 27.-54.*(x+y);
01670    h(9,2) = -54.*x;
01671 }
01672 
01673 
01674 Cubic3DFiniteElement::Cubic3DFiniteElement()
01675    : NodalFiniteElement(3, Geometry::TETRAHEDRON, 20, 3)
01676 {
01677    Nodes.IntPoint(0).x = 0;
01678    Nodes.IntPoint(0).y = 0;
01679    Nodes.IntPoint(0).z = 0;
01680    Nodes.IntPoint(1).x = 1.;
01681    Nodes.IntPoint(1).y = 0;
01682    Nodes.IntPoint(1).z = 0;
01683    Nodes.IntPoint(2).x = 0;
01684    Nodes.IntPoint(2).y = 1.;
01685    Nodes.IntPoint(2).z = 0;
01686    Nodes.IntPoint(3).x = 0;
01687    Nodes.IntPoint(3).y = 0;
01688    Nodes.IntPoint(3).z = 1.;
01689    Nodes.IntPoint(4).x = 0.3333333333333333333333333333;
01690    Nodes.IntPoint(4).y = 0;
01691    Nodes.IntPoint(4).z = 0;
01692    Nodes.IntPoint(5).x = 0.6666666666666666666666666667;
01693    Nodes.IntPoint(5).y = 0;
01694    Nodes.IntPoint(5).z = 0;
01695    Nodes.IntPoint(6).x = 0;
01696    Nodes.IntPoint(6).y = 0.3333333333333333333333333333;
01697    Nodes.IntPoint(6).z = 0;
01698    Nodes.IntPoint(7).x = 0;
01699    Nodes.IntPoint(7).y = 0.6666666666666666666666666667;
01700    Nodes.IntPoint(7).z = 0;
01701    Nodes.IntPoint(8).x = 0;
01702    Nodes.IntPoint(8).y = 0;
01703    Nodes.IntPoint(8).z = 0.3333333333333333333333333333;
01704    Nodes.IntPoint(9).x = 0;
01705    Nodes.IntPoint(9).y = 0;
01706    Nodes.IntPoint(9).z = 0.6666666666666666666666666667;
01707    Nodes.IntPoint(10).x = 0.6666666666666666666666666667;
01708    Nodes.IntPoint(10).y = 0.3333333333333333333333333333;
01709    Nodes.IntPoint(10).z = 0;
01710    Nodes.IntPoint(11).x = 0.3333333333333333333333333333;
01711    Nodes.IntPoint(11).y = 0.6666666666666666666666666667;
01712    Nodes.IntPoint(11).z = 0;
01713    Nodes.IntPoint(12).x = 0.6666666666666666666666666667;
01714    Nodes.IntPoint(12).y = 0;
01715    Nodes.IntPoint(12).z = 0.3333333333333333333333333333;
01716    Nodes.IntPoint(13).x = 0.3333333333333333333333333333;
01717    Nodes.IntPoint(13).y = 0;
01718    Nodes.IntPoint(13).z = 0.6666666666666666666666666667;
01719    Nodes.IntPoint(14).x = 0;
01720    Nodes.IntPoint(14).y = 0.6666666666666666666666666667;
01721    Nodes.IntPoint(14).z = 0.3333333333333333333333333333;
01722    Nodes.IntPoint(15).x = 0;
01723    Nodes.IntPoint(15).y = 0.3333333333333333333333333333;
01724    Nodes.IntPoint(15).z = 0.6666666666666666666666666667;
01725    Nodes.IntPoint(16).x = 0.3333333333333333333333333333;
01726    Nodes.IntPoint(16).y = 0.3333333333333333333333333333;
01727    Nodes.IntPoint(16).z = 0.3333333333333333333333333333;
01728    Nodes.IntPoint(17).x = 0;
01729    Nodes.IntPoint(17).y = 0.3333333333333333333333333333;
01730    Nodes.IntPoint(17).z = 0.3333333333333333333333333333;
01731    Nodes.IntPoint(18).x = 0.3333333333333333333333333333;
01732    Nodes.IntPoint(18).y = 0;
01733    Nodes.IntPoint(18).z = 0.3333333333333333333333333333;
01734    Nodes.IntPoint(19).x = 0.3333333333333333333333333333;
01735    Nodes.IntPoint(19).y = 0.3333333333333333333333333333;
01736    Nodes.IntPoint(19).z = 0;
01737 }
01738 
01739 void Cubic3DFiniteElement::CalcShape(const IntegrationPoint &ip,
01740                                      Vector &shape) const
01741 {
01742    double x = ip.x, y = ip.y, z = ip.z;
01743 
01744    shape(0) = -((-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z)*
01745                 (-1 + 3*x + 3*y + 3*z))/2.;
01746    shape(4) = (9*x*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.;
01747    shape(5) = (-9*x*(-1 + 3*x)*(-1 + x + y + z))/2.;
01748    shape(1) = (x*(2 + 9*(-1 + x)*x))/2.;
01749    shape(6) = (9*y*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.;
01750    shape(19) = -27*x*y*(-1 + x + y + z);
01751    shape(10) = (9*x*(-1 + 3*x)*y)/2.;
01752    shape(7) = (-9*y*(-1 + 3*y)*(-1 + x + y + z))/2.;
01753    shape(11) = (9*x*y*(-1 + 3*y))/2.;
01754    shape(2) = (y*(2 + 9*(-1 + y)*y))/2.;
01755    shape(8) = (9*z*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.;
01756    shape(18) = -27*x*z*(-1 + x + y + z);
01757    shape(12) = (9*x*(-1 + 3*x)*z)/2.;
01758    shape(17) = -27*y*z*(-1 + x + y + z);
01759    shape(16) = 27*x*y*z;
01760    shape(14) = (9*y*(-1 + 3*y)*z)/2.;
01761    shape(9) = (-9*z*(-1 + x + y + z)*(-1 + 3*z))/2.;
01762    shape(13) = (9*x*z*(-1 + 3*z))/2.;
01763    shape(15) = (9*y*z*(-1 + 3*z))/2.;
01764    shape(3) = (z*(2 + 9*(-1 + z)*z))/2.;
01765 }
01766 
01767 void Cubic3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01768                                       DenseMatrix &dshape) const
01769 {
01770    double x = ip.x, y = ip.y, z = ip.z;
01771 
01772    dshape(0,0) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) +
01773                                          x*(-4 + 6*y + 6*z)))/2.;
01774    dshape(0,1) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) +
01775                                          x*(-4 + 6*y + 6*z)))/2.;
01776    dshape(0,2) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) +
01777                                          x*(-4 + 6*y + 6*z)))/2.;
01778    dshape(4,0) = (9*(9*pow(x,2) + (-1 + y + z)*(-2 + 3*y + 3*z) +
01779                      2*x*(-5 + 6*y + 6*z)))/2.;
01780    dshape(4,1) = (9*x*(-5 + 6*x + 6*y + 6*z))/2.;
01781    dshape(4,2) = (9*x*(-5 + 6*x + 6*y + 6*z))/2.;
01782    dshape(5,0) = (-9*(1 - y - z + x*(-8 + 9*x + 6*y + 6*z)))/2.;
01783    dshape(5,1) = (9*(1 - 3*x)*x)/2.;
01784    dshape(5,2) = (9*(1 - 3*x)*x)/2.;
01785    dshape(1,0) = 1 + (9*x*(-2 + 3*x))/2.;
01786    dshape(1,1) = 0;
01787    dshape(1,2) = 0;
01788    dshape(6,0) = (9*y*(-5 + 6*x + 6*y + 6*z))/2.;
01789    dshape(6,1) = (9*(2 + 3*pow(x,2) - 10*y - 5*z + 3*(y + z)*(3*y + z) +
01790                      x*(-5 + 12*y + 6*z)))/2.;
01791    dshape(6,2) = (9*y*(-5 + 6*x + 6*y + 6*z))/2.;
01792    dshape(19,0) = -27*y*(-1 + 2*x + y + z);
01793    dshape(19,1) = -27*x*(-1 + x + 2*y + z);
01794    dshape(19,2) = -27*x*y;
01795    dshape(10,0) = (9*(-1 + 6*x)*y)/2.;
01796    dshape(10,1) = (9*x*(-1 + 3*x))/2.;
01797    dshape(10,2) = 0;
01798    dshape(7,0) = (9*(1 - 3*y)*y)/2.;
01799    dshape(7,1) = (-9*(1 + x*(-1 + 6*y) - z + y*(-8 + 9*y + 6*z)))/2.;
01800    dshape(7,2) = (9*(1 - 3*y)*y)/2.;
01801    dshape(11,0) = (9*y*(-1 + 3*y))/2.;
01802    dshape(11,1) = (9*x*(-1 + 6*y))/2.;
01803    dshape(11,2) = 0;
01804    dshape(2,0) = 0;
01805    dshape(2,1) = 1 + (9*y*(-2 + 3*y))/2.;
01806    dshape(2,2) = 0;
01807    dshape(8,0) = (9*z*(-5 + 6*x + 6*y + 6*z))/2.;
01808    dshape(8,1) = (9*z*(-5 + 6*x + 6*y + 6*z))/2.;
01809    dshape(8,2) = (9*(2 + 3*pow(x,2) - 5*y - 10*z + 3*(y + z)*(y + 3*z) +
01810                      x*(-5 + 6*y + 12*z)))/2.;
01811    dshape(18,0) = -27*z*(-1 + 2*x + y + z);
01812    dshape(18,1) = -27*x*z;
01813    dshape(18,2) = -27*x*(-1 + x + y + 2*z);
01814    dshape(12,0) = (9*(-1 + 6*x)*z)/2.;
01815    dshape(12,1) = 0;
01816    dshape(12,2) = (9*x*(-1 + 3*x))/2.;
01817    dshape(17,0) = -27*y*z;
01818    dshape(17,1) = -27*z*(-1 + x + 2*y + z);
01819    dshape(17,2) = -27*y*(-1 + x + y + 2*z);
01820    dshape(16,0) = 27*y*z;
01821    dshape(16,1) = 27*x*z;
01822    dshape(16,2) = 27*x*y;
01823    dshape(14,0) = 0;
01824    dshape(14,1) = (9*(-1 + 6*y)*z)/2.;
01825    dshape(14,2) = (9*y*(-1 + 3*y))/2.;
01826    dshape(9,0) = (9*(1 - 3*z)*z)/2.;
01827    dshape(9,1) = (9*(1 - 3*z)*z)/2.;
01828    dshape(9,2) = (9*(-1 + x + y + 8*z - 6*(x + y)*z - 9*pow(z,2)))/2.;
01829    dshape(13,0) = (9*z*(-1 + 3*z))/2.;
01830    dshape(13,1) = 0;
01831    dshape(13,2) = (9*x*(-1 + 6*z))/2.;
01832    dshape(15,0) = 0;
01833    dshape(15,1) = (9*z*(-1 + 3*z))/2.;
01834    dshape(15,2) = (9*y*(-1 + 6*z))/2.;
01835    dshape(3,0) = 0;
01836    dshape(3,1) = 0;
01837    dshape(3,2) = 1 + (9*z*(-2 + 3*z))/2.;
01838 }
01839 
01840 
01841 P0TriangleFiniteElement::P0TriangleFiniteElement()
01842    : NodalFiniteElement(2, Geometry::TRIANGLE , 1, 0)
01843 {
01844    Nodes.IntPoint(0).x = 0.333333333333333333;
01845    Nodes.IntPoint(0).y = 0.333333333333333333;
01846 }
01847 
01848 void P0TriangleFiniteElement::CalcShape(const IntegrationPoint &ip,
01849                                         Vector &shape) const
01850 {
01851    shape(0) = 1.0;
01852 }
01853 
01854 void P0TriangleFiniteElement::CalcDShape(const IntegrationPoint &ip,
01855                                          DenseMatrix &dshape) const
01856 {
01857    dshape(0,0) = 0.0;
01858    dshape(0,1) = 0.0;
01859 }
01860 
01861 
01862 P0QuadFiniteElement::P0QuadFiniteElement()
01863    : NodalFiniteElement(2, Geometry::SQUARE , 1, 0, FunctionSpace::Qk)
01864 {
01865    Nodes.IntPoint(0).x = 0.5;
01866    Nodes.IntPoint(0).y = 0.5;
01867 }
01868 
01869 void P0QuadFiniteElement::CalcShape(const IntegrationPoint &ip,
01870                                     Vector &shape) const
01871 {
01872    shape(0) = 1.0;
01873 }
01874 
01875 void P0QuadFiniteElement::CalcDShape(const IntegrationPoint &ip,
01876                                      DenseMatrix &dshape) const
01877 {
01878    dshape(0,0) = 0.0;
01879    dshape(0,1) = 0.0;
01880 }
01881 
01882 
01883 Linear3DFiniteElement::Linear3DFiniteElement()
01884    : NodalFiniteElement(3, Geometry::TETRAHEDRON, 4, 1)
01885 {
01886    Nodes.IntPoint(0).x = 0.0;
01887    Nodes.IntPoint(0).y = 0.0;
01888    Nodes.IntPoint(0).z = 0.0;
01889    Nodes.IntPoint(1).x = 1.0;
01890    Nodes.IntPoint(1).y = 0.0;
01891    Nodes.IntPoint(1).z = 0.0;
01892    Nodes.IntPoint(2).x = 0.0;
01893    Nodes.IntPoint(2).y = 1.0;
01894    Nodes.IntPoint(2).z = 0.0;
01895    Nodes.IntPoint(3).x = 0.0;
01896    Nodes.IntPoint(3).y = 0.0;
01897    Nodes.IntPoint(3).z = 1.0;
01898 }
01899 
01900 void Linear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
01901                                       Vector &shape) const
01902 {
01903    shape(0) = 1. - ip.x - ip.y - ip.z;
01904    shape(1) = ip.x;
01905    shape(2) = ip.y;
01906    shape(3) = ip.z;
01907 }
01908 
01909 void Linear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01910                                        DenseMatrix &dshape) const
01911 {
01912    if (dshape.Height() == 4)
01913    {
01914       double *A = &dshape(0,0);
01915       A[0] = -1.; A[4] = -1.; A[8]  = -1.;
01916       A[1] =  1.; A[5] =  0.; A[9]  =  0.;
01917       A[2] =  0.; A[6] =  1.; A[10] =  0.;
01918       A[3] =  0.; A[7] =  0.; A[11] =  1.;
01919    }
01920    else
01921    {
01922       dshape(0,0) = -1.; dshape(0,1) = -1.; dshape(0,2) = -1.;
01923       dshape(1,0) =  1.; dshape(1,1) =  0.; dshape(1,2) =  0.;
01924       dshape(2,0) =  0.; dshape(2,1) =  1.; dshape(2,2) =  0.;
01925       dshape(3,0) =  0.; dshape(3,1) =  0.; dshape(3,2) =  1.;
01926    }
01927 }
01928 
01929 void Linear3DFiniteElement::GetFaceDofs (int face, int **dofs, int *ndofs)
01930    const
01931 {
01932    static int face_dofs[4][3] = {{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}};
01933 
01934    *ndofs = 3;
01935    *dofs  = face_dofs[face];
01936 }
01937 
01938 
01939 Quadratic3DFiniteElement::Quadratic3DFiniteElement()
01940    : NodalFiniteElement(3, Geometry::TETRAHEDRON, 10, 2)
01941 {
01942    Nodes.IntPoint(0).x = 0.0;
01943    Nodes.IntPoint(0).y = 0.0;
01944    Nodes.IntPoint(0).z = 0.0;
01945    Nodes.IntPoint(1).x = 1.0;
01946    Nodes.IntPoint(1).y = 0.0;
01947    Nodes.IntPoint(1).z = 0.0;
01948    Nodes.IntPoint(2).x = 0.0;
01949    Nodes.IntPoint(2).y = 1.0;
01950    Nodes.IntPoint(2).z = 0.0;
01951    Nodes.IntPoint(3).x = 0.0;
01952    Nodes.IntPoint(3).y = 0.0;
01953    Nodes.IntPoint(3).z = 1.0;
01954    Nodes.IntPoint(4).x = 0.5;
01955    Nodes.IntPoint(4).y = 0.0;
01956    Nodes.IntPoint(4).z = 0.0;
01957    Nodes.IntPoint(5).x = 0.0;
01958    Nodes.IntPoint(5).y = 0.5;
01959    Nodes.IntPoint(5).z = 0.0;
01960    Nodes.IntPoint(6).x = 0.0;
01961    Nodes.IntPoint(6).y = 0.0;
01962    Nodes.IntPoint(6).z = 0.5;
01963    Nodes.IntPoint(7).x = 0.5;
01964    Nodes.IntPoint(7).y = 0.5;
01965    Nodes.IntPoint(7).z = 0.0;
01966    Nodes.IntPoint(8).x = 0.5;
01967    Nodes.IntPoint(8).y = 0.0;
01968    Nodes.IntPoint(8).z = 0.5;
01969    Nodes.IntPoint(9).x = 0.0;
01970    Nodes.IntPoint(9).y = 0.5;
01971    Nodes.IntPoint(9).z = 0.5;
01972 }
01973 
01974 void Quadratic3DFiniteElement::CalcShape(const IntegrationPoint &ip,
01975                                          Vector &shape) const
01976 {
01977    double L0, L1, L2, L3;
01978 
01979    L0 = 1. - ip.x - ip.y - ip.z;
01980    L1 = ip.x;
01981    L2 = ip.y;
01982    L3 = ip.z;
01983 
01984    shape(0) = L0 * ( 2.0 * L0 - 1.0 );
01985    shape(1) = L1 * ( 2.0 * L1 - 1.0 );
01986    shape(2) = L2 * ( 2.0 * L2 - 1.0 );
01987    shape(3) = L3 * ( 2.0 * L3 - 1.0 );
01988    shape(4) = 4.0 * L0 * L1;
01989    shape(5) = 4.0 * L0 * L2;
01990    shape(6) = 4.0 * L0 * L3;
01991    shape(7) = 4.0 * L1 * L2;
01992    shape(8) = 4.0 * L1 * L3;
01993    shape(9) = 4.0 * L2 * L3;
01994 }
01995 
01996 void Quadratic3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
01997                                           DenseMatrix &dshape) const
01998 {
01999    double x, y, z, L0;
02000 
02001    x = ip.x;
02002    y = ip.y;
02003    z = ip.z;
02004    L0 = 1.0 - x - y - z;
02005 
02006    dshape(0,0) = dshape(0,1) = dshape(0,2) = 1.0 - 4.0 * L0;
02007    dshape(1,0) = -1.0 + 4.0 * x; dshape(1,1) = 0.0; dshape(1,2) = 0.0;
02008    dshape(2,0) = 0.0; dshape(2,1) = -1.0 + 4.0 * y; dshape(2,2) = 0.0;
02009    dshape(3,0) = dshape(3,1) = 0.0; dshape(3,2) = -1.0 + 4.0 * z;
02010    dshape(4,0) = 4.0 * (L0 - x); dshape(4,1) = dshape(4,2) = -4.0 * x;
02011    dshape(5,0) = dshape(5,2) = -4.0 * y; dshape(5,1) = 4.0 * (L0 - y);
02012    dshape(6,0) = dshape(6,1) = -4.0 * z; dshape(6,2) = 4.0 * (L0 - z);
02013    dshape(7,0) = 4.0 * y; dshape(7,1) = 4.0 * x; dshape(7,2) = 0.0;
02014    dshape(8,0) = 4.0 * z; dshape(8,1) = 0.0; dshape(8,2) = 4.0 * x;
02015    dshape(9,0) = 0.0; dshape(9,1) = 4.0 * z; dshape(9,2) = 4.0 * y;
02016 }
02017 
02018 TriLinear3DFiniteElement::TriLinear3DFiniteElement()
02019    : NodalFiniteElement(3, Geometry::CUBE, 8, 1, FunctionSpace::Qk)
02020 {
02021    Nodes.IntPoint(0).x = 0.0;
02022    Nodes.IntPoint(0).y = 0.0;
02023    Nodes.IntPoint(0).z = 0.0;
02024 
02025    Nodes.IntPoint(1).x = 1.0;
02026    Nodes.IntPoint(1).y = 0.0;
02027    Nodes.IntPoint(1).z = 0.0;
02028 
02029    Nodes.IntPoint(2).x = 1.0;
02030    Nodes.IntPoint(2).y = 1.0;
02031    Nodes.IntPoint(2).z = 0.0;
02032 
02033    Nodes.IntPoint(3).x = 0.0;
02034    Nodes.IntPoint(3).y = 1.0;
02035    Nodes.IntPoint(3).z = 0.0;
02036 
02037    Nodes.IntPoint(4).x = 0.0;
02038    Nodes.IntPoint(4).y = 0.0;
02039    Nodes.IntPoint(4).z = 1.0;
02040 
02041    Nodes.IntPoint(5).x = 1.0;
02042    Nodes.IntPoint(5).y = 0.0;
02043    Nodes.IntPoint(5).z = 1.0;
02044 
02045    Nodes.IntPoint(6).x = 1.0;
02046    Nodes.IntPoint(6).y = 1.0;
02047    Nodes.IntPoint(6).z = 1.0;
02048 
02049    Nodes.IntPoint(7).x = 0.0;
02050    Nodes.IntPoint(7).y = 1.0;
02051    Nodes.IntPoint(7).z = 1.0;
02052 }
02053 
02054 void TriLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
02055                                          Vector &shape) const
02056 {
02057    double x = ip.x, y = ip.y, z = ip.z;
02058    double ox = 1.-x, oy = 1.-y, oz = 1.-z;
02059 
02060    shape(0) = ox * oy * oz;
02061    shape(1) =  x * oy * oz;
02062    shape(2) =  x *  y * oz;
02063    shape(3) = ox *  y * oz;
02064    shape(4) = ox * oy *  z;
02065    shape(5) =  x * oy *  z;
02066    shape(6) =  x *  y *  z;
02067    shape(7) = ox *  y *  z;
02068 }
02069 
02070 void TriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
02071                                           DenseMatrix &dshape) const
02072 {
02073    double x = ip.x, y = ip.y, z = ip.z;
02074    double ox = 1.-x, oy = 1.-y, oz = 1.-z;
02075 
02076    dshape(0,0) = - oy * oz;
02077    dshape(0,1) = - ox * oz;
02078    dshape(0,2) = - ox * oy;
02079 
02080    dshape(1,0) =   oy * oz;
02081    dshape(1,1) = -  x * oz;
02082    dshape(1,2) = -  x * oy;
02083 
02084    dshape(2,0) =    y * oz;
02085    dshape(2,1) =    x * oz;
02086    dshape(2,2) = -  x *  y;
02087 
02088    dshape(3,0) = -  y * oz;
02089    dshape(3,1) =   ox * oz;
02090    dshape(3,2) = - ox *  y;
02091 
02092    dshape(4,0) = - oy *  z;
02093    dshape(4,1) = - ox *  z;
02094    dshape(4,2) =   ox * oy;
02095 
02096    dshape(5,0) =   oy *  z;
02097    dshape(5,1) = -  x *  z;
02098    dshape(5,2) =    x * oy;
02099 
02100    dshape(6,0) =    y *  z;
02101    dshape(6,1) =    x *  z;
02102    dshape(6,2) =    x *  y;
02103 
02104    dshape(7,0) = -  y *  z;
02105    dshape(7,1) =   ox *  z;
02106    dshape(7,2) =   ox *  y;
02107 }
02108 
02109 P0SegmentFiniteElement::P0SegmentFiniteElement(int Ord)
02110    : NodalFiniteElement(1, Geometry::SEGMENT , 1, Ord)  // defaul Ord = 0
02111 {
02112    Nodes.IntPoint(0).x = 0.5;
02113 }
02114 
02115 void P0SegmentFiniteElement::CalcShape(const IntegrationPoint &ip,
02116                                        Vector &shape) const
02117 {
02118    shape(0) = 1.0;
02119 }
02120 
02121 void P0SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip,
02122                                         DenseMatrix &dshape) const
02123 {
02124    dshape(0,0) = 0.0;
02125 }
02126 
02127 CrouzeixRaviartFiniteElement::CrouzeixRaviartFiniteElement()
02128    : NodalFiniteElement(2, Geometry::TRIANGLE , 3, 1)
02129 {
02130    Nodes.IntPoint(0).x = 0.5;
02131    Nodes.IntPoint(0).y = 0.0;
02132    Nodes.IntPoint(1).x = 0.5;
02133    Nodes.IntPoint(1).y = 0.5;
02134    Nodes.IntPoint(2).x = 0.0;
02135    Nodes.IntPoint(2).y = 0.5;
02136 }
02137 
02138 void CrouzeixRaviartFiniteElement::CalcShape(const IntegrationPoint &ip,
02139                                              Vector &shape) const
02140 {
02141    shape(0) =  1.0 - 2.0 * ip.y;
02142    shape(1) = -1.0 + 2.0 * ( ip.x + ip.y );
02143    shape(2) =  1.0 - 2.0 * ip.x;
02144 }
02145 
02146 void CrouzeixRaviartFiniteElement::CalcDShape(const IntegrationPoint &ip,
02147                                               DenseMatrix &dshape) const
02148 {
02149    dshape(0,0) =  0.0; dshape(0,1) = -2.0;
02150    dshape(1,0) =  2.0; dshape(1,1) =  2.0;
02151    dshape(2,0) = -2.0; dshape(2,1) =  0.0;
02152 }
02153 
02154 CrouzeixRaviartQuadFiniteElement::CrouzeixRaviartQuadFiniteElement()
02155 // the FunctionSpace should be rotated (45 degrees) Q_1
02156 // i.e. the span of { 1, x, y, x^2 - y^2 }
02157    : NodalFiniteElement(2, Geometry::SQUARE , 4, 2, FunctionSpace::Qk)
02158 
02159 {
02160    Nodes.IntPoint(0).x = 0.5;
02161    Nodes.IntPoint(0).y = 0.0;
02162    Nodes.IntPoint(1).x = 1.0;
02163    Nodes.IntPoint(1).y = 0.5;
02164    Nodes.IntPoint(2).x = 0.5;
02165    Nodes.IntPoint(2).y = 1.0;
02166    Nodes.IntPoint(3).x = 0.0;
02167    Nodes.IntPoint(3).y = 0.5;
02168 }
02169 
02170 void CrouzeixRaviartQuadFiniteElement::CalcShape(const IntegrationPoint &ip,
02171                                                  Vector &shape) const
02172 {
02173    const double l1 = ip.x+ip.y-0.5, l2 = 1.-l1, l3 = ip.x-ip.y+0.5, l4 = 1.-l3;
02174 
02175    shape(0) = l2 * l3;
02176    shape(1) = l1 * l3;
02177    shape(2) = l1 * l4;
02178    shape(3) = l2 * l4;
02179 }
02180 
02181 void CrouzeixRaviartQuadFiniteElement::CalcDShape(const IntegrationPoint &ip,
02182                                                   DenseMatrix &dshape) const
02183 {
02184    const double x2 = 2.*ip.x, y2 = 2.*ip.y;
02185 
02186    dshape(0,0) =  1. - x2; dshape(0,1) = -2. + y2;
02187    dshape(1,0) =       x2; dshape(1,1) =  1. - y2;
02188    dshape(2,0) =  1. - x2; dshape(2,1) =       y2;
02189    dshape(3,0) = -2. + x2; dshape(3,1) =  1. - y2;
02190 }
02191 
02192 
02193 RT0TriangleFiniteElement::RT0TriangleFiniteElement()
02194    : VectorFiniteElement (2, Geometry::TRIANGLE, 3, 1)
02195 {
02196    Nodes.IntPoint(0).x = 0.5;
02197    Nodes.IntPoint(0).y = 0.0;
02198    Nodes.IntPoint(1).x = 0.5;
02199    Nodes.IntPoint(1).y = 0.5;
02200    Nodes.IntPoint(2).x = 0.0;
02201    Nodes.IntPoint(2).y = 0.5;
02202 }
02203 
02204 void RT0TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip,
02205                                           DenseMatrix &shape) const
02206 {
02207    double x = ip.x, y = ip.y;
02208 
02209    shape(0,0) = x;
02210    shape(0,1) = y - 1.;
02211    shape(1,0) = x;
02212    shape(1,1) = y;
02213    shape(2,0) = x - 1.;
02214    shape(2,1) = y;
02215 }
02216 
02217 void RT0TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip,
02218                                             Vector &divshape) const
02219 {
02220    divshape(0) = 2.;
02221    divshape(1) = 2.;
02222    divshape(2) = 2.;
02223 }
02224 
02225 const double RT0TriangleFiniteElement::nk[3][2] =
02226 { {0, -1}, {1, 1}, {-1, 0} };
02227 
02228 void RT0TriangleFiniteElement::GetLocalInterpolation (
02229    ElementTransformation &Trans, DenseMatrix &I) const
02230 {
02231    int k, j;
02232 #ifdef MFEM_USE_OPENMP
02233    DenseMatrix vshape(Dof, Dim);
02234    DenseMatrix Jinv(Dim);
02235 #endif
02236 
02237 #ifdef MFEM_DEBUG
02238    for (k = 0; k < 3; k++)
02239    {
02240       CalcVShape (Nodes.IntPoint(k), vshape);
02241       for (j = 0; j < 3; j++)
02242       {
02243          double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
02244          if (j == k) d -= 1.0;
02245          if (fabs(d) > 1.0e-12)
02246          {
02247             cerr << "RT0TriangleFiniteElement::GetLocalInterpolation (...)\n"
02248                " k = " << k << ", j = " << j << ", d = " << d << endl;
02249             mfem_error();
02250          }
02251       }
02252    }
02253 #endif
02254 
02255    IntegrationPoint ip;
02256    ip.x = ip.y = 0.0;
02257    Trans.SetIntPoint (&ip);
02258    // Trans must be linear
02259    // set Jinv = |J| J^{-t} = adj(J)^t
02260    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02261    double vk[2];
02262    Vector xk (vk, 2);
02263 
02264    for (k = 0; k < 3; k++)
02265    {
02266       Trans.Transform (Nodes.IntPoint (k), xk);
02267       ip.x = vk[0]; ip.y = vk[1];
02268       CalcVShape (ip, vshape);
02269       //  vk = |J| J^{-t} nk
02270       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
02271       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
02272       for (j = 0; j < 3; j++)
02273          if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
02274             I(k,j) = 0.0;
02275    }
02276 }
02277 
02278 void RT0TriangleFiniteElement::Project (
02279    VectorCoefficient &vc, ElementTransformation &Trans,
02280    Vector &dofs) const
02281 {
02282    double vk[2];
02283    Vector xk (vk, 2);
02284 #ifdef MFEM_USE_OPENMP
02285    DenseMatrix Jinv(Dim);
02286 #endif
02287 
02288    for (int k = 0; k < 3; k++)
02289    {
02290       Trans.SetIntPoint (&Nodes.IntPoint (k));
02291       // set Jinv = |J| J^{-t} = adj(J)^t
02292       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02293 
02294       vc.Eval (xk, Trans, Nodes.IntPoint (k));
02295       //  xk^t |J| J^{-t} nk
02296       dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
02297                  vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
02298    }
02299 }
02300 
02301 RT0QuadFiniteElement::RT0QuadFiniteElement()
02302    : VectorFiniteElement (2, Geometry::SQUARE, 4, 1, FunctionSpace::Qk)
02303 {
02304    Nodes.IntPoint(0).x = 0.5;
02305    Nodes.IntPoint(0).y = 0.0;
02306    Nodes.IntPoint(1).x = 1.0;
02307    Nodes.IntPoint(1).y = 0.5;
02308    Nodes.IntPoint(2).x = 0.5;
02309    Nodes.IntPoint(2).y = 1.0;
02310    Nodes.IntPoint(3).x = 0.0;
02311    Nodes.IntPoint(3).y = 0.5;
02312 }
02313 
02314 void RT0QuadFiniteElement::CalcVShape(const IntegrationPoint &ip,
02315                                       DenseMatrix &shape) const
02316 {
02317    double x = ip.x, y = ip.y;
02318 
02319    shape(0,0) = 0;
02320    shape(0,1) = y - 1.;
02321    shape(1,0) = x;
02322    shape(1,1) = 0;
02323    shape(2,0) = 0;
02324    shape(2,1) = y;
02325    shape(3,0) = x - 1.;
02326    shape(3,1) = 0;
02327 }
02328 
02329 void RT0QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip,
02330                                         Vector &divshape) const
02331 {
02332    divshape(0) = 1.;
02333    divshape(1) = 1.;
02334    divshape(2) = 1.;
02335    divshape(3) = 1.;
02336 }
02337 
02338 const double RT0QuadFiniteElement::nk[4][2] =
02339 { {0, -1}, {1, 0}, {0, 1}, {-1, 0} };
02340 
02341 void RT0QuadFiniteElement::GetLocalInterpolation (
02342    ElementTransformation &Trans, DenseMatrix &I) const
02343 {
02344    int k, j;
02345 #ifdef MFEM_USE_OPENMP
02346    DenseMatrix vshape(Dof, Dim);
02347    DenseMatrix Jinv(Dim);
02348 #endif
02349 
02350 #ifdef MFEM_DEBUG
02351    for (k = 0; k < 4; k++)
02352    {
02353       CalcVShape (Nodes.IntPoint(k), vshape);
02354       for (j = 0; j < 4; j++)
02355       {
02356          double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
02357          if (j == k) d -= 1.0;
02358          if (fabs(d) > 1.0e-12)
02359          {
02360             cerr << "RT0QuadFiniteElement::GetLocalInterpolation (...)\n"
02361                " k = " << k << ", j = " << j << ", d = " << d << endl;
02362             mfem_error();
02363          }
02364       }
02365    }
02366 #endif
02367 
02368    IntegrationPoint ip;
02369    ip.x = ip.y = 0.0;
02370    Trans.SetIntPoint (&ip);
02371    // Trans must be linear (more to have embedding?)
02372    // set Jinv = |J| J^{-t} = adj(J)^t
02373    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02374    double vk[2];
02375    Vector xk (vk, 2);
02376 
02377    for (k = 0; k < 4; k++)
02378    {
02379       Trans.Transform (Nodes.IntPoint (k), xk);
02380       ip.x = vk[0]; ip.y = vk[1];
02381       CalcVShape (ip, vshape);
02382       //  vk = |J| J^{-t} nk
02383       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
02384       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
02385       for (j = 0; j < 4; j++)
02386          if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
02387             I(k,j) = 0.0;
02388    }
02389 }
02390 
02391 void RT0QuadFiniteElement::Project (
02392    VectorCoefficient &vc, ElementTransformation &Trans,
02393    Vector &dofs) const
02394 {
02395    double vk[2];
02396    Vector xk (vk, 2);
02397 #ifdef MFEM_USE_OPENMP
02398    DenseMatrix Jinv(Dim);
02399 #endif
02400 
02401    for (int k = 0; k < 4; k++)
02402    {
02403       Trans.SetIntPoint (&Nodes.IntPoint (k));
02404       // set Jinv = |J| J^{-t} = adj(J)^t
02405       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02406 
02407       vc.Eval (xk, Trans, Nodes.IntPoint (k));
02408       //  xk^t |J| J^{-t} nk
02409       dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
02410                  vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
02411    }
02412 }
02413 
02414 RT1TriangleFiniteElement::RT1TriangleFiniteElement()
02415    : VectorFiniteElement (2, Geometry::TRIANGLE, 8, 2)
02416 {
02417    Nodes.IntPoint(0).x = 0.33333333333333333333;
02418    Nodes.IntPoint(0).y = 0.0;
02419    Nodes.IntPoint(1).x = 0.66666666666666666667;
02420    Nodes.IntPoint(1).y = 0.0;
02421    Nodes.IntPoint(2).x = 0.66666666666666666667;
02422    Nodes.IntPoint(2).y = 0.33333333333333333333;
02423    Nodes.IntPoint(3).x = 0.33333333333333333333;
02424    Nodes.IntPoint(3).y = 0.66666666666666666667;
02425    Nodes.IntPoint(4).x = 0.0;
02426    Nodes.IntPoint(4).y = 0.66666666666666666667;
02427    Nodes.IntPoint(5).x = 0.0;
02428    Nodes.IntPoint(5).y = 0.33333333333333333333;
02429    Nodes.IntPoint(6).x = 0.33333333333333333333;
02430    Nodes.IntPoint(6).y = 0.33333333333333333333;
02431    Nodes.IntPoint(7).x = 0.33333333333333333333;
02432    Nodes.IntPoint(7).y = 0.33333333333333333333;
02433 }
02434 
02435 void RT1TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip,
02436                                           DenseMatrix &shape) const
02437 {
02438    double x = ip.x, y = ip.y;
02439 
02440    shape(0,0) = -2 * x * (-1 + x + 2 * y);
02441    shape(0,1) = -2 * (-1 + y) * (-1 + x + 2 * y);
02442    shape(1,0) =  2 * x * (x - y);
02443    shape(1,1) =  2 * (x - y) * (-1 + y);
02444    shape(2,0) =  2 * x * (-1 + 2 * x + y);
02445    shape(2,1) =  2 * y * (-1 + 2 * x + y);
02446    shape(3,0) =  2 * x * (-1 + x + 2 * y);
02447    shape(3,1) =  2 * y * (-1 + x + 2 * y);
02448    shape(4,0) = -2 * (-1 + x) * (x - y);
02449    shape(4,1) =  2 * y * (-x + y);
02450    shape(5,0) = -2 * (-1 + x) * (-1 + 2 * x + y);
02451    shape(5,1) = -2 * y * (-1 + 2 * x + y);
02452    shape(6,0) = -3 * x * (-2 + 2 * x + y);
02453    shape(6,1) = -3 * y * (-1 + 2 * x + y);
02454    shape(7,0) = -3 * x * (-1 + x + 2 * y);
02455    shape(7,1) = -3 * y * (-2 + x + 2 * y);
02456 }
02457 
02458 void RT1TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip,
02459                                             Vector &divshape) const
02460 {
02461    double x = ip.x, y = ip.y;
02462 
02463    divshape(0) = -2 * (-4 + 3 * x + 6 * y);
02464    divshape(1) =  2 + 6 * x - 6 * y;
02465    divshape(2) = -4 + 12 * x + 6 * y;
02466    divshape(3) = -4 + 6 * x + 12 * y;
02467    divshape(4) =  2 - 6 * x + 6 * y;
02468    divshape(5) = -2 * (-4 + 6 * x + 3 * y);
02469    divshape(6) = -9 * (-1 + 2 * x + y);
02470    divshape(7) = -9 * (-1 + x + 2 * y);
02471 }
02472 
02473 const double RT1TriangleFiniteElement::nk[8][2] =
02474 {
02475    { 0,-1}, { 0,-1},
02476    { 1, 1}, { 1, 1},
02477    {-1, 0}, {-1, 0},
02478    { 1, 0}, { 0, 1}
02479 };
02480 
02481 void RT1TriangleFiniteElement::GetLocalInterpolation (
02482    ElementTransformation &Trans, DenseMatrix &I) const
02483 {
02484    int k, j;
02485 #ifdef MFEM_USE_OPENMP
02486    DenseMatrix vshape(Dof, Dim);
02487    DenseMatrix Jinv(Dim);
02488 #endif
02489 
02490 #ifdef MFEM_DEBUG
02491    for (k = 0; k < 8; k++)
02492    {
02493       CalcVShape (Nodes.IntPoint(k), vshape);
02494       for (j = 0; j < 8; j++)
02495       {
02496          double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
02497          if (j == k) d -= 1.0;
02498          if (fabs(d) > 1.0e-12)
02499          {
02500             cerr << "RT1QuadFiniteElement::GetLocalInterpolation (...)\n"
02501                " k = " << k << ", j = " << j << ", d = " << d << endl;
02502             mfem_error();
02503          }
02504       }
02505    }
02506 #endif
02507 
02508    IntegrationPoint ip;
02509    ip.x = ip.y = 0.0;
02510    Trans.SetIntPoint (&ip);
02511    // Trans must be linear (more to have embedding?)
02512    // set Jinv = |J| J^{-t} = adj(J)^t
02513    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02514    double vk[2];
02515    Vector xk (vk, 2);
02516 
02517    for (k = 0; k < 8; k++)
02518    {
02519       Trans.Transform (Nodes.IntPoint (k), xk);
02520       ip.x = vk[0]; ip.y = vk[1];
02521       CalcVShape (ip, vshape);
02522       //  vk = |J| J^{-t} nk
02523       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
02524       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
02525       for (j = 0; j < 8; j++)
02526          if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
02527             I(k,j) = 0.0;
02528    }
02529 }
02530 
02531 void RT1TriangleFiniteElement::Project (
02532    VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
02533 {
02534    double vk[2];
02535    Vector xk (vk, 2);
02536 #ifdef MFEM_USE_OPENMP
02537    DenseMatrix Jinv(Dim);
02538 #endif
02539 
02540    for (int k = 0; k < 8; k++)
02541    {
02542       Trans.SetIntPoint (&Nodes.IntPoint (k));
02543       // set Jinv = |J| J^{-t} = adj(J)^t
02544       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02545 
02546       vc.Eval (xk, Trans, Nodes.IntPoint (k));
02547       //  xk^t |J| J^{-t} nk
02548       dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
02549                  vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
02550       dofs(k) *= 0.5;
02551    }
02552 }
02553 
02554 RT1QuadFiniteElement::RT1QuadFiniteElement()
02555    : VectorFiniteElement (2, Geometry::SQUARE, 12, 2, FunctionSpace::Qk)
02556 {
02557    // y = 0
02558    Nodes.IntPoint(0).x  = 1./3.;
02559    Nodes.IntPoint(0).y  = 0.0;
02560    Nodes.IntPoint(1).x  = 2./3.;
02561    Nodes.IntPoint(1).y  = 0.0;
02562    // x = 1
02563    Nodes.IntPoint(2).x  = 1.0;
02564    Nodes.IntPoint(2).y  = 1./3.;
02565    Nodes.IntPoint(3).x  = 1.0;
02566    Nodes.IntPoint(3).y  = 2./3.;
02567    // y = 1
02568    Nodes.IntPoint(4).x  = 2./3.;
02569    Nodes.IntPoint(4).y  = 1.0;
02570    Nodes.IntPoint(5).x  = 1./3.;
02571    Nodes.IntPoint(5).y  = 1.0;
02572    // x = 0
02573    Nodes.IntPoint(6).x  = 0.0;
02574    Nodes.IntPoint(6).y  = 2./3.;
02575    Nodes.IntPoint(7).x  = 0.0;
02576    Nodes.IntPoint(7).y  = 1./3.;
02577    // x = 0.5 (interior)
02578    Nodes.IntPoint(8).x  = 0.5;
02579    Nodes.IntPoint(8).y  = 1./3.;
02580    Nodes.IntPoint(9).x  = 0.5;
02581    Nodes.IntPoint(9).y  = 2./3.;
02582    // y = 0.5 (interior)
02583    Nodes.IntPoint(10).x = 1./3.;
02584    Nodes.IntPoint(10).y = 0.5;
02585    Nodes.IntPoint(11).x = 2./3.;
02586    Nodes.IntPoint(11).y = 0.5;
02587 }
02588 
02589 void RT1QuadFiniteElement::CalcVShape(const IntegrationPoint &ip,
02590                                       DenseMatrix &shape) const
02591 {
02592    double x = ip.x, y = ip.y;
02593 
02594    // y = 0
02595    shape(0,0)  = 0;
02596    shape(0,1)  = -( 1. - 3.*y + 2.*y*y)*( 2. - 3.*x);
02597    shape(1,0)  = 0;
02598    shape(1,1)  = -( 1. - 3.*y + 2.*y*y)*(-1. + 3.*x);
02599    // x = 1
02600    shape(2,0)  = (-x + 2.*x*x)*( 2. - 3.*y);
02601    shape(2,1)  = 0;
02602    shape(3,0)  = (-x + 2.*x*x)*(-1. + 3.*y);
02603    shape(3,1)  = 0;
02604    // y = 1
02605    shape(4,0)  = 0;
02606    shape(4,1)  = (-y + 2.*y*y)*(-1. + 3.*x);
02607    shape(5,0)  = 0;
02608    shape(5,1)  = (-y + 2.*y*y)*( 2. - 3.*x);
02609    // x = 0
02610    shape(6,0)  = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y);
02611    shape(6,1)  = 0;
02612    shape(7,0)  = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y);
02613    shape(7,1)  = 0;
02614    // x = 0.5 (interior)
02615    shape(8,0)  = (4.*x - 4.*x*x)*( 2. - 3.*y);
02616    shape(8,1)  = 0;
02617    shape(9,0)  = (4.*x - 4.*x*x)*(-1. + 3.*y);
02618    shape(9,1)  = 0;
02619    // y = 0.5 (interior)
02620    shape(10,0) = 0;
02621    shape(10,1) = (4.*y - 4.*y*y)*( 2. - 3.*x);
02622    shape(11,0) = 0;
02623    shape(11,1) = (4.*y - 4.*y*y)*(-1. + 3.*x);
02624 }
02625 
02626 void RT1QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip,
02627                                         Vector &divshape) const
02628 {
02629    double x = ip.x, y = ip.y;
02630 
02631    divshape(0)  = -(-3. + 4.*y)*( 2. - 3.*x);
02632    divshape(1)  = -(-3. + 4.*y)*(-1. + 3.*x);
02633    divshape(2)  = (-1. + 4.*x)*( 2. - 3.*y);
02634    divshape(3)  = (-1. + 4.*x)*(-1. + 3.*y);
02635    divshape(4)  = (-1. + 4.*y)*(-1. + 3.*x);
02636    divshape(5)  = (-1. + 4.*y)*( 2. - 3.*x);
02637    divshape(6)  = -(-3. + 4.*x)*(-1. + 3.*y);
02638    divshape(7)  = -(-3. + 4.*x)*( 2. - 3.*y);
02639    divshape(8)  = ( 4. - 8.*x)*( 2. - 3.*y);
02640    divshape(9)  = ( 4. - 8.*x)*(-1. + 3.*y);
02641    divshape(10) = ( 4. - 8.*y)*( 2. - 3.*x);
02642    divshape(11) = ( 4. - 8.*y)*(-1. + 3.*x);
02643 }
02644 
02645 const double RT1QuadFiniteElement::nk[12][2] =
02646 {
02647    // y = 0
02648    {0,-1}, {0,-1},
02649    // X = 1
02650    {1, 0}, {1, 0},
02651    // y = 1
02652    {0, 1}, {0, 1},
02653    // x = 0
02654    {-1,0}, {-1,0},
02655    // x = 0.5 (interior)
02656    {1, 0}, {1, 0},
02657    // y = 0.5 (interior)
02658    {0, 1}, {0, 1}
02659 };
02660 
02661 void RT1QuadFiniteElement::GetLocalInterpolation (
02662    ElementTransformation &Trans, DenseMatrix &I) const
02663 {
02664    int k, j;
02665 #ifdef MFEM_USE_OPENMP
02666    DenseMatrix vshape(Dof, Dim);
02667    DenseMatrix Jinv(Dim);
02668 #endif
02669 
02670 #ifdef MFEM_DEBUG
02671    for (k = 0; k < 12; k++)
02672    {
02673       CalcVShape (Nodes.IntPoint(k), vshape);
02674       for (j = 0; j < 12; j++)
02675       {
02676          double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
02677          if (j == k) d -= 1.0;
02678          if (fabs(d) > 1.0e-12)
02679          {
02680             cerr << "RT1QuadFiniteElement::GetLocalInterpolation (...)\n"
02681                " k = " << k << ", j = " << j << ", d = " << d << endl;
02682             mfem_error();
02683          }
02684       }
02685    }
02686 #endif
02687 
02688    IntegrationPoint ip;
02689    ip.x = ip.y = 0.0;
02690    Trans.SetIntPoint (&ip);
02691    // Trans must be linear (more to have embedding?)
02692    // set Jinv = |J| J^{-t} = adj(J)^t
02693    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02694    double vk[2];
02695    Vector xk (vk, 2);
02696 
02697    for (k = 0; k < 12; k++)
02698    {
02699       Trans.Transform (Nodes.IntPoint (k), xk);
02700       ip.x = vk[0]; ip.y = vk[1];
02701       CalcVShape (ip, vshape);
02702       //  vk = |J| J^{-t} nk
02703       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
02704       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
02705       for (j = 0; j < 12; j++)
02706          if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
02707             I(k,j) = 0.0;
02708    }
02709 }
02710 
02711 void RT1QuadFiniteElement::Project (
02712    VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
02713 {
02714    double vk[2];
02715    Vector xk (vk, 2);
02716 #ifdef MFEM_USE_OPENMP
02717    DenseMatrix Jinv(Dim);
02718 #endif
02719 
02720    for (int k = 0; k < 12; k++)
02721    {
02722       Trans.SetIntPoint (&Nodes.IntPoint (k));
02723       // set Jinv = |J| J^{-t} = adj(J)^t
02724       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
02725 
02726       vc.Eval (xk, Trans, Nodes.IntPoint (k));
02727       //  xk^t |J| J^{-t} nk
02728       dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
02729                  vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
02730    }
02731 }
02732 
02733 const double RT2TriangleFiniteElement::M[15][15] =
02734 {{ 0, -5.3237900077244501311, 5.3237900077244501311, 16.647580015448900262,
02735    0, 24.442740046346700787, -16.647580015448900262, -12.,
02736    -19.118950038622250656, -47.237900077244501311, 0, -34.414110069520051180,
02737    12., 30.590320061795601049, 15.295160030897800524},
02738  { 0, 1.5, -1.5, -15., 0, 2.625, 15., 15., -4.125, 30., 0, -14.625, -15.,
02739    -15., 10.5},
02740  { 0, -0.67620999227554986889, 0.67620999227554986889, 7.3524199845510997378,
02741    0, -3.4427400463467007866, -7.3524199845510997378, -12.,
02742    4.1189500386222506555, -0.76209992275549868892, 0, 7.4141100695200511800,
02743    12., -6.5903200617956010489, -3.2951600308978005244},
02744  { 0, 0, 1.5, 0, 0, 1.5, -11.471370023173350393, 0, 2.4713700231733503933,
02745    -11.471370023173350393, 0, 2.4713700231733503933, 15.295160030897800524,
02746    0, -3.2951600308978005244},
02747  { 0, 0, 4.875, 0, 0, 4.875, -16.875, 0, -16.875, -16.875, 0, -16.875, 10.5,
02748    36., 10.5},
02749  { 0, 0, 1.5, 0, 0, 1.5, 2.4713700231733503933, 0, -11.471370023173350393,
02750    2.4713700231733503933, 0, -11.471370023173350393, -3.2951600308978005244,
02751    0, 15.295160030897800524},
02752  { -0.67620999227554986889, 0, -3.4427400463467007866, 0,
02753    7.3524199845510997378, 0.67620999227554986889, 7.4141100695200511800, 0,
02754    -0.76209992275549868892, 4.1189500386222506555, -12.,
02755    -7.3524199845510997378, -3.2951600308978005244, -6.5903200617956010489,
02756    12.},
02757  { 1.5, 0, 2.625, 0, -15., -1.5, -14.625, 0, 30., -4.125, 15., 15., 10.5,
02758    -15., -15.},
02759  { -5.3237900077244501311, 0, 24.442740046346700787, 0, 16.647580015448900262,
02760    5.3237900077244501311, -34.414110069520051180, 0, -47.237900077244501311,
02761    -19.118950038622250656, -12., -16.647580015448900262, 15.295160030897800524,
02762    30.590320061795601049, 12.},
02763  { 0, 0, 18., 0, 0, 6., -42., 0, -30., -26., 0, -14., 24., 32., 8.},
02764  { 0, 0, 6., 0, 0, 18., -14., 0, -26., -30., 0, -42., 8., 32., 24.},
02765  { 0, 0, -6., 0, 0, -4., 30., 0, 4., 22., 0, 4., -24., -16., 0},
02766  { 0, 0, -4., 0, 0, -8., 20., 0, 8., 36., 0, 8., -16., -32., 0},
02767  { 0, 0, -8., 0, 0, -4., 8., 0, 36., 8., 0, 20., 0, -32., -16.},
02768  { 0, 0, -4., 0, 0, -6., 4., 0, 22., 4., 0, 30., 0, -16., -24.}
02769 };
02770 
02771 RT2TriangleFiniteElement::RT2TriangleFiniteElement()
02772    : VectorFiniteElement (2, Geometry::TRIANGLE, 15, 3)
02773 {
02774    const double p = 0.11270166537925831148;
02775 
02776    Nodes.IntPoint(0).x = p;
02777    Nodes.IntPoint(0).y = 0.0;
02778    Nodes.IntPoint(1).x = 0.5;
02779    Nodes.IntPoint(1).y = 0.0;
02780    Nodes.IntPoint(2).x = 1.-p;
02781    Nodes.IntPoint(2).y = 0.0;
02782    Nodes.IntPoint(3).x = 1.-p;
02783    Nodes.IntPoint(3).y = p;
02784    Nodes.IntPoint(4).x = 0.5;
02785    Nodes.IntPoint(4).y = 0.5;
02786    Nodes.IntPoint(5).x = p;
02787    Nodes.IntPoint(5).y = 1.-p;
02788    Nodes.IntPoint(6).x = 0.0;
02789    Nodes.IntPoint(6).y = 1.-p;
02790    Nodes.IntPoint(7).x = 0.0;
02791    Nodes.IntPoint(7).y = 0.5;
02792    Nodes.IntPoint(8).x = 0.0;
02793    Nodes.IntPoint(8).y = p;
02794    Nodes.IntPoint(9).x  = 0.25;
02795    Nodes.IntPoint(9).y  = 0.25;
02796    Nodes.IntPoint(10).x = 0.25;
02797    Nodes.IntPoint(10).y = 0.25;
02798    Nodes.IntPoint(11).x = 0.5;
02799    Nodes.IntPoint(11).y = 0.25;
02800    Nodes.IntPoint(12).x = 0.5;
02801    Nodes.IntPoint(12).y = 0.25;
02802    Nodes.IntPoint(13).x = 0.25;
02803    Nodes.IntPoint(13).y = 0.5;
02804    Nodes.IntPoint(14).x = 0.25;
02805    Nodes.IntPoint(14).y = 0.5;
02806 }
02807 
02808 void RT2TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip,
02809                                           DenseMatrix &shape) const
02810 {
02811    double x = ip.x, y = ip.y;
02812 
02813    double Bx[15] = {1., 0., x, 0., y, 0., x*x, 0., x*y, 0., y*y, 0., x*x*x,
02814                     x*x*y, x*y*y};
02815    double By[15] = {0., 1., 0., x, 0., y, 0., x*x, 0., x*y, 0., y*y,
02816                     x*x*y, x*y*y, y*y*y};
02817 
02818    for (int i = 0; i < 15; i++)
02819    {
02820       double cx = 0.0, cy = 0.0;
02821       for (int j = 0; j < 15; j++)
02822       {
02823          cx += M[i][j] * Bx[j];
02824          cy += M[i][j] * By[j];
02825       }
02826       shape(i,0) = cx;
02827       shape(i,1) = cy;
02828    }
02829 }
02830 
02831 void RT2TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip,
02832                                             Vector &divshape) const
02833 {
02834    double x = ip.x, y = ip.y;
02835 
02836    double DivB[15] = {0., 0., 1., 0., 0., 1., 2.*x, 0., y, x, 0., 2.*y,
02837                       4.*x*x, 4.*x*y, 4.*y*y};
02838 
02839    for (int i = 0; i < 15; i++)
02840    {
02841       double div = 0.0;
02842       for (int j = 0; j < 15; j++)
02843          div += M[i][j] * DivB[j];
02844       divshape(i) = div;
02845    }
02846 }
02847 
02848 const double RT2QuadFiniteElement::pt[4] = {0.,1./3.,2./3.,1.};
02849 
02850 const double RT2QuadFiniteElement::dpt[3] = {0.25,0.5,0.75};
02851 
02852 RT2QuadFiniteElement::RT2QuadFiniteElement()
02853    : VectorFiniteElement (2, Geometry::SQUARE, 24, 3, FunctionSpace::Qk)
02854 {
02855    // y = 0 (pt[0])
02856    Nodes.IntPoint(0).x  = dpt[0];  Nodes.IntPoint(0).y  =  pt[0];
02857    Nodes.IntPoint(1).x  = dpt[1];  Nodes.IntPoint(1).y  =  pt[0];
02858    Nodes.IntPoint(2).x  = dpt[2];  Nodes.IntPoint(2).y  =  pt[0];
02859    // x = 1 (pt[3])
02860    Nodes.IntPoint(3).x  =  pt[3];  Nodes.IntPoint(3).y  = dpt[0];
02861    Nodes.IntPoint(4).x  =  pt[3];  Nodes.IntPoint(4).y  = dpt[1];
02862    Nodes.IntPoint(5).x  =  pt[3];  Nodes.IntPoint(5).y  = dpt[2];
02863    // y = 1 (pt[3])
02864    Nodes.IntPoint(6).x  = dpt[2];  Nodes.IntPoint(6).y  =  pt[3];
02865    Nodes.IntPoint(7).x  = dpt[1];  Nodes.IntPoint(7).y  =  pt[3];
02866    Nodes.IntPoint(8).x  = dpt[0];  Nodes.IntPoint(8).y  =  pt[3];
02867    // x = 0 (pt[0])
02868    Nodes.IntPoint(9).x  =  pt[0];  Nodes.IntPoint(9).y  = dpt[2];
02869    Nodes.IntPoint(10).x =  pt[0];  Nodes.IntPoint(10).y = dpt[1];
02870    Nodes.IntPoint(11).x =  pt[0];  Nodes.IntPoint(11).y = dpt[0];
02871    // x = pt[1] (interior)
02872    Nodes.IntPoint(12).x =  pt[1];  Nodes.IntPoint(12).y = dpt[0];
02873    Nodes.IntPoint(13).x =  pt[1];  Nodes.IntPoint(13).y = dpt[1];
02874    Nodes.IntPoint(14).x =  pt[1];  Nodes.IntPoint(14).y = dpt[2];
02875    // x = pt[2] (interior)
02876    Nodes.IntPoint(15).x =  pt[2];  Nodes.IntPoint(15).y = dpt[0];
02877    Nodes.IntPoint(16).x =  pt[2];  Nodes.IntPoint(16).y = dpt[1];
02878    Nodes.IntPoint(17).x =  pt[2];  Nodes.IntPoint(17).y = dpt[2];
02879    // y = pt[1] (interior)
02880    Nodes.IntPoint(18).x = dpt[0];  Nodes.IntPoint(18).y =  pt[1];
02881    Nodes.IntPoint(19).x = dpt[1];  Nodes.IntPoint(19).y =  pt[1];
02882    Nodes.IntPoint(20).x = dpt[2];  Nodes.IntPoint(20).y =  pt[1];
02883    // y = pt[2] (interior)
02884    Nodes.IntPoint(21).x = dpt[0];  Nodes.IntPoint(21).y =  pt[2];
02885    Nodes.IntPoint(22).x = dpt[1];  Nodes.IntPoint(22).y =  pt[2];
02886    Nodes.IntPoint(23).x = dpt[2];  Nodes.IntPoint(23).y =  pt[2];
02887 }
02888 
02889 void RT2QuadFiniteElement::CalcVShape(const IntegrationPoint &ip,
02890                                       DenseMatrix &shape) const
02891 {
02892    double x = ip.x, y = ip.y;
02893 
02894    double ax0 =  pt[0] - x;
02895    double ax1 =  pt[1] - x;
02896    double ax2 =  pt[2] - x;
02897    double ax3 =  pt[3] - x;
02898 
02899    double by0 = dpt[0] - y;
02900    double by1 = dpt[1] - y;
02901    double by2 = dpt[2] - y;
02902 
02903    double ay0 =  pt[0] - y;
02904    double ay1 =  pt[1] - y;
02905    double ay2 =  pt[2] - y;
02906    double ay3 =  pt[3] - y;
02907 
02908    double bx0 = dpt[0] - x;
02909    double bx1 = dpt[1] - x;
02910    double bx2 = dpt[2] - x;
02911 
02912    double A01 =  pt[0] -  pt[1];
02913    double A02 =  pt[0] -  pt[2];
02914    double A12 =  pt[1] -  pt[2];
02915    double A03 =  pt[0] -  pt[3];
02916    double A13 =  pt[1] -  pt[3];
02917    double A23 =  pt[2] -  pt[3];
02918 
02919    double B01 = dpt[0] - dpt[1];
02920    double B02 = dpt[0] - dpt[2];
02921    double B12 = dpt[1] - dpt[2];
02922 
02923    double tx0 =  (bx1*bx2)/(B01*B02);
02924    double tx1 = -(bx0*bx2)/(B01*B12);
02925    double tx2 =  (bx0*bx1)/(B02*B12);
02926 
02927    double ty0 =  (by1*by2)/(B01*B02);
02928    double ty1 = -(by0*by2)/(B01*B12);
02929    double ty2 =  (by0*by1)/(B02*B12);
02930 
02931    // y = 0 (p[0])
02932    shape(0,  0) =  0;
02933    shape(0,  1) =  (ay1*ay2*ay3)/(A01*A02*A03)*tx0;
02934    shape(1,  0) =  0;
02935    shape(1,  1) =  (ay1*ay2*ay3)/(A01*A02*A03)*tx1;
02936    shape(2,  0) =  0;
02937    shape(2,  1) =  (ay1*ay2*ay3)/(A01*A02*A03)*tx2;
02938    // x = 1 (p[3])
02939    shape(3,  0) =  (ax0*ax1*ax2)/(A03*A13*A23)*ty0;
02940    shape(3,  1) =  0;
02941    shape(4,  0) =  (ax0*ax1*ax2)/(A03*A13*A23)*ty1;
02942    shape(4,  1) =  0;
02943    shape(5,  0) =  (ax0*ax1*ax2)/(A03*A13*A23)*ty2;
02944    shape(5,  1) =  0;
02945    // y = 1 (p[3])
02946    shape(6,  0) =  0;
02947    shape(6,  1) =  (ay0*ay1*ay2)/(A03*A13*A23)*tx2;
02948    shape(7,  0) =  0;
02949    shape(7,  1) =  (ay0*ay1*ay2)/(A03*A13*A23)*tx1;
02950    shape(8,  0) =  0;
02951    shape(8,  1) =  (ay0*ay1*ay2)/(A03*A13*A23)*tx0;
02952    // x = 0 (p[0])
02953    shape(9,  0) =  (ax1*ax2*ax3)/(A01*A02*A03)*ty2;
02954    shape(9,  1) =  0;
02955    shape(10, 0) =  (ax1*ax2*ax3)/(A01*A02*A03)*ty1;
02956    shape(10, 1) =  0;
02957    shape(11, 0) =  (ax1*ax2*ax3)/(A01*A02*A03)*ty0;
02958    shape(11, 1) =  0;
02959    // x = p[1] (interior)
02960    shape(12, 0) =  (ax0*ax2*ax3)/(A01*A12*A13)*ty0;
02961    shape(12, 1) =  0;
02962    shape(13, 0) =  (ax0*ax2*ax3)/(A01*A12*A13)*ty1;
02963    shape(13, 1) =  0;
02964    shape(14, 0) =  (ax0*ax2*ax3)/(A01*A12*A13)*ty2;
02965    shape(14, 1) =  0;
02966    // x = p[2] (interior)
02967    shape(15, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty0;
02968    shape(15, 1) =  0;
02969    shape(16, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty1;
02970    shape(16, 1) =  0;
02971    shape(17, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty2;
02972    shape(17, 1) =  0;
02973    // y = p[1] (interior)
02974    shape(18, 0) =  0;
02975    shape(18, 1) =  (ay0*ay2*ay3)/(A01*A12*A13)*tx0;
02976    shape(19, 0) =  0;
02977    shape(19, 1) =  (ay0*ay2*ay3)/(A01*A12*A13)*tx1;
02978    shape(20, 0) =  0;
02979    shape(20, 1) =  (ay0*ay2*ay3)/(A01*A12*A13)*tx2;
02980    // y = p[2] (interior)
02981    shape(21, 0) =  0;
02982    shape(21, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx0;
02983    shape(22, 0) =  0;
02984    shape(22, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx1;
02985    shape(23, 0) =  0;
02986    shape(23, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx2;
02987 }
02988 
02989 void RT2QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip,
02990                                         Vector &divshape) const
02991 {
02992    double x = ip.x, y = ip.y;
02993 
02994    double a01 =  pt[0]*pt[1];
02995    double a02 =  pt[0]*pt[2];
02996    double a12 =  pt[1]*pt[2];
02997    double a03 =  pt[0]*pt[3];
02998    double a13 =  pt[1]*pt[3];
02999    double a23 =  pt[2]*pt[3];
03000 
03001    double bx0 = dpt[0] - x;
03002    double bx1 = dpt[1] - x;
03003    double bx2 = dpt[2] - x;
03004 
03005    double by0 = dpt[0] - y;
03006    double by1 = dpt[1] - y;
03007    double by2 = dpt[2] - y;
03008 
03009    double A01 =  pt[0] -  pt[1];
03010    double A02 =  pt[0] -  pt[2];
03011    double A12 =  pt[1] -  pt[2];
03012    double A03 =  pt[0] -  pt[3];
03013    double A13 =  pt[1] -  pt[3];
03014    double A23 =  pt[2] -  pt[3];
03015 
03016    double A012 = pt[0] + pt[1] + pt[2];
03017    double A013 = pt[0] + pt[1] + pt[3];
03018    double A023 = pt[0] + pt[2] + pt[3];
03019    double A123 = pt[1] + pt[2] + pt[3];
03020 
03021    double B01 = dpt[0] - dpt[1];
03022    double B02 = dpt[0] - dpt[2];
03023    double B12 = dpt[1] - dpt[2];
03024 
03025    double tx0 =  (bx1*bx2)/(B01*B02);
03026    double tx1 = -(bx0*bx2)/(B01*B12);
03027    double tx2 =  (bx0*bx1)/(B02*B12);
03028 
03029    double ty0 =  (by1*by2)/(B01*B02);
03030    double ty1 = -(by0*by2)/(B01*B12);
03031    double ty2 =  (by0*by1)/(B02*B12);
03032 
03033    // y = 0 (p[0])
03034    divshape(0)  = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx0;
03035    divshape(1)  = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx1;
03036    divshape(2)  = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx2;
03037    // x = 1 (p[3])
03038    divshape(3)  = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty0;
03039    divshape(4)  = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty1;
03040    divshape(5)  = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty2;
03041    // y = 1 (p[3])
03042    divshape(6)  = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx2;
03043    divshape(7)  = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx1;
03044    divshape(8)  = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx0;
03045    // x = 0 (p[0])
03046    divshape(9)  = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty2;
03047    divshape(10) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty1;
03048    divshape(11) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty0;
03049    // x = p[1] (interior)
03050    divshape(12) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty0;
03051    divshape(13) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty1;
03052    divshape(14) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty2;
03053    // x = p[2] (interior)
03054    divshape(15) =  (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty0;
03055    divshape(16) =  (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty1;
03056    divshape(17) =  (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty2;
03057    // y = p[1] (interior)
03058    divshape(18) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx0;
03059    divshape(19) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx1;
03060    divshape(20) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx2;
03061    // y = p[2] (interior)
03062    divshape(21) =  (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx0;
03063    divshape(22) =  (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx1;
03064    divshape(23) =  (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx2;
03065 }
03066 
03067 const double RT2QuadFiniteElement::nk[24][2] =
03068 {
03069    // y = 0
03070    {0,-1}, {0,-1}, {0,-1},
03071    // x = 1
03072    {1, 0}, {1, 0}, {1, 0},
03073    // y = 1
03074    {0, 1}, {0, 1}, {0, 1},
03075    // x = 0
03076    {-1,0}, {-1,0}, {-1,0},
03077    // x = p[1] (interior)
03078    {1, 0}, {1, 0}, {1, 0},
03079    // x = p[2] (interior)
03080    {1, 0}, {1, 0}, {1, 0},
03081    // y = p[1] (interior)
03082    {0, 1}, {0, 1}, {0, 1},
03083    // y = p[1] (interior)
03084    {0, 1}, {0, 1}, {0, 1}
03085 };
03086 
03087 void RT2QuadFiniteElement::GetLocalInterpolation (
03088    ElementTransformation &Trans, DenseMatrix &I) const
03089 {
03090    int k, j;
03091 #ifdef MFEM_USE_OPENMP
03092    DenseMatrix vshape(Dof, Dim);
03093    DenseMatrix Jinv(Dim);
03094 #endif
03095 
03096 #ifdef MFEM_DEBUG
03097    for (k = 0; k < 24; k++)
03098    {
03099       CalcVShape (Nodes.IntPoint(k), vshape);
03100       for (j = 0; j < 24; j++)
03101       {
03102          double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
03103          if (j == k) d -= 1.0;
03104          if (fabs(d) > 1.0e-12)
03105          {
03106             cerr << "RT2QuadFiniteElement::GetLocalInterpolation (...)\n"
03107                " k = " << k << ", j = " << j << ", d = " << d << endl;
03108             mfem_error();
03109          }
03110       }
03111    }
03112 #endif
03113 
03114    IntegrationPoint ip;
03115    ip.x = ip.y = 0.0;
03116    Trans.SetIntPoint (&ip);
03117    // Trans must be linear (more to have embedding?)
03118    // set Jinv = |J| J^{-t} = adj(J)^t
03119    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
03120    double vk[2];
03121    Vector xk (vk, 2);
03122 
03123    for (k = 0; k < 24; k++)
03124    {
03125       Trans.Transform (Nodes.IntPoint (k), xk);
03126       ip.x = vk[0]; ip.y = vk[1];
03127       CalcVShape (ip, vshape);
03128       //  vk = |J| J^{-t} nk
03129       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
03130       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
03131       for (j = 0; j < 24; j++)
03132          if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
03133             I(k,j) = 0.0;
03134    }
03135 }
03136 
03137 void RT2QuadFiniteElement::Project (
03138    VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
03139 {
03140    double vk[2];
03141    Vector xk (vk, 2);
03142 #ifdef MFEM_USE_OPENMP
03143    DenseMatrix Jinv(Dim);
03144 #endif
03145 
03146    for (int k = 0; k < 24; k++)
03147    {
03148       Trans.SetIntPoint (&Nodes.IntPoint (k));
03149       // set Jinv = |J| J^{-t} = adj(J)^t
03150       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
03151 
03152       vc.Eval (xk, Trans, Nodes.IntPoint (k));
03153       //  xk^t |J| J^{-t} nk
03154       dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
03155                  vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
03156    }
03157 }
03158 
03159 P1SegmentFiniteElement::P1SegmentFiniteElement()
03160    : NodalFiniteElement(1, Geometry::SEGMENT, 2, 1)
03161 {
03162    Nodes.IntPoint(0).x = 0.33333333333333333333;
03163    Nodes.IntPoint(1).x = 0.66666666666666666667;
03164 }
03165 
03166 void P1SegmentFiniteElement::CalcShape(const IntegrationPoint &ip,
03167                                        Vector &shape) const
03168 {
03169    double x = ip.x;
03170 
03171    shape(0) = 2. - 3. * x;
03172    shape(1) = 3. * x - 1.;
03173 }
03174 
03175 void P1SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip,
03176                                         DenseMatrix &dshape) const
03177 {
03178    dshape(0,0) = -3.;
03179    dshape(1,0) =  3.;
03180 }
03181 
03182 
03183 P2SegmentFiniteElement::P2SegmentFiniteElement()
03184    : NodalFiniteElement(1, Geometry::SEGMENT, 3, 2)
03185 {
03186    const double p = 0.11270166537925831148;
03187 
03188    Nodes.IntPoint(0).x = p;
03189    Nodes.IntPoint(1).x = 0.5;
03190    Nodes.IntPoint(2).x = 1.-p;
03191 }
03192 
03193 void P2SegmentFiniteElement::CalcShape(const IntegrationPoint &ip,
03194                                        Vector &shape) const
03195 {
03196    const double p = 0.11270166537925831148;
03197    const double w = 1./((1-2*p)*(1-2*p));
03198    double x = ip.x;
03199 
03200    shape(0) = (2*x-1)*(x-1+p)*w;
03201    shape(1) = 4*(x-1+p)*(p-x)*w;
03202    shape(2) = (2*x-1)*(x-p)*w;
03203 }
03204 
03205 void P2SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip,
03206                                         DenseMatrix &dshape) const
03207 {
03208    const double p = 0.11270166537925831148;
03209    const double w = 1./((1-2*p)*(1-2*p));
03210    double x = ip.x;
03211 
03212    dshape(0,0) = (-3+4*x+2*p)*w;
03213    dshape(1,0) = (4-8*x)*w;
03214    dshape(2,0) = (-1+4*x-2*p)*w;
03215 }
03216 
03217 
03218 Lagrange1DFiniteElement::Lagrange1DFiniteElement(int degree)
03219    : NodalFiniteElement(1, Geometry::SEGMENT, degree+1, degree)
03220 {
03221    int i, m = degree;
03222 
03223    Nodes.IntPoint(0).x = 0.0;
03224    Nodes.IntPoint(1).x = 1.0;
03225    for (i = 1; i < m; i++)
03226       Nodes.IntPoint(i+1).x = double(i) / m;
03227 
03228    rwk.SetSize(degree+1);
03229 #ifndef MFEM_USE_OPENMP
03230    rxxk.SetSize(degree+1);
03231 #endif
03232 
03233    rwk(0) = 1.0;
03234    for (i = 1; i <= m; i++)
03235       rwk(i) = rwk(i-1) * ( (double)(m) / (double)(i) );
03236    for (i = 0; i < m/2+1; i++)
03237       rwk(m-i) = ( rwk(i) *= rwk(m-i) );
03238    for (i = m-1; i >= 0; i -= 2)
03239       rwk(i) = -rwk(i);
03240 }
03241 
03242 void Lagrange1DFiniteElement::CalcShape(const IntegrationPoint &ip,
03243                                         Vector &shape) const
03244 {
03245    double w, wk, x = ip.x;
03246    int i, k, m = GetOrder();
03247 
03248 #ifdef MFEM_USE_OPENMP
03249    Vector rxxk(m+1);
03250 #endif
03251 
03252    k = (int) floor ( m * x + 0.5 );
03253    wk = 1.0;
03254    for (i = 0; i <= m; i++)
03255       if (i != k)
03256          wk *= ( rxxk(i) = x - (double)(i) / m );
03257    w = wk * ( rxxk(k) = x - (double)(k) / m );
03258 
03259    if (k != 0)
03260       shape(0) = w * rwk(0) / rxxk(0);
03261    else
03262       shape(0) = wk * rwk(0);
03263    if (k != m)
03264       shape(1) = w * rwk(m) / rxxk(m);
03265    else
03266       shape(1) = wk * rwk(k);
03267    for (i = 1; i < m; i++)
03268       if (i != k)
03269          shape(i+1) = w * rwk(i) / rxxk(i);
03270       else
03271          shape(k+1) = wk * rwk(k);
03272 }
03273 
03274 void Lagrange1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
03275                                          DenseMatrix &dshape) const
03276 {
03277    double s, srx, w, wk, x = ip.x;
03278    int i, k, m = GetOrder();
03279 
03280 #ifdef MFEM_USE_OPENMP
03281    Vector rxxk(m+1);
03282 #endif
03283 
03284    k = (int) floor ( m * x + 0.5 );
03285    wk = 1.0;
03286    for (i = 0; i <= m; i++)
03287       if (i != k)
03288          wk *= ( rxxk(i) = x - (double)(i) / m );
03289    w = wk * ( rxxk(k) = x - (double)(k) / m );
03290 
03291    for (i = 0; i <= m; i++)
03292       rxxk(i) = 1.0 / rxxk(i);
03293    srx = 0.0;
03294    for (i = 0; i <= m; i++)
03295       if (i != k)
03296          srx += rxxk(i);
03297    s = w * srx + wk;
03298 
03299    if (k != 0)
03300       dshape(0,0) = (s - w * rxxk(0)) * rwk(0) * rxxk(0);
03301    else
03302       dshape(0,0) = wk * srx * rwk(0);
03303    if (k != m)
03304       dshape(1,0) = (s - w * rxxk(m)) * rwk(m) * rxxk(m);
03305    else
03306       dshape(1,0) = wk * srx * rwk(k);
03307    for (i = 1; i < m; i++)
03308       if (i != k)
03309          dshape(i+1,0) = (s - w * rxxk(i)) * rwk(i) * rxxk(i);
03310       else
03311          dshape(k+1,0) = wk * srx * rwk(k);
03312 }
03313 
03314 
03315 P1TetNonConfFiniteElement::P1TetNonConfFiniteElement()
03316    : NodalFiniteElement(3, Geometry::TETRAHEDRON, 4, 1)
03317 {
03318    Nodes.IntPoint(0).x = 0.33333333333333333333;
03319    Nodes.IntPoint(0).y = 0.33333333333333333333;
03320    Nodes.IntPoint(0).z = 0.33333333333333333333;
03321 
03322    Nodes.IntPoint(1).x = 0.0;
03323    Nodes.IntPoint(1).y = 0.33333333333333333333;
03324    Nodes.IntPoint(1).z = 0.33333333333333333333;
03325 
03326    Nodes.IntPoint(2).x = 0.33333333333333333333;
03327    Nodes.IntPoint(2).y = 0.0;
03328    Nodes.IntPoint(2).z = 0.33333333333333333333;
03329 
03330    Nodes.IntPoint(3).x = 0.33333333333333333333;
03331    Nodes.IntPoint(3).y = 0.33333333333333333333;
03332    Nodes.IntPoint(3).z = 0.0;
03333 
03334 }
03335 
03336 void P1TetNonConfFiniteElement::CalcShape(const IntegrationPoint &ip,
03337                                           Vector &shape) const
03338 {
03339    double L0, L1, L2, L3;
03340 
03341    L1 = ip.x;  L2 = ip.y;  L3 = ip.z;  L0 = 1.0 - L1 - L2 - L3;
03342    shape(0) = 1.0 - 3.0 * L0;
03343    shape(1) = 1.0 - 3.0 * L1;
03344    shape(2) = 1.0 - 3.0 * L2;
03345    shape(3) = 1.0 - 3.0 * L3;
03346 }
03347 
03348 void P1TetNonConfFiniteElement::CalcDShape(const IntegrationPoint &ip,
03349                                            DenseMatrix &dshape) const
03350 {
03351    dshape(0,0) =  3.0; dshape(0,1) =  3.0; dshape(0,2) =  3.0;
03352    dshape(1,0) = -3.0; dshape(1,1) =  0.0; dshape(1,2) =  0.0;
03353    dshape(2,0) =  0.0; dshape(2,1) = -3.0; dshape(2,2) =  0.0;
03354    dshape(3,0) =  0.0; dshape(3,1) =  0.0; dshape(3,2) = -3.0;
03355 }
03356 
03357 
03358 P0TetFiniteElement::P0TetFiniteElement()
03359    : NodalFiniteElement(3, Geometry::TETRAHEDRON , 1, 0)
03360 {
03361    Nodes.IntPoint(0).x = 0.25;
03362    Nodes.IntPoint(0).y = 0.25;
03363    Nodes.IntPoint(0).z = 0.25;
03364 }
03365 
03366 void P0TetFiniteElement::CalcShape(const IntegrationPoint &ip,
03367                                    Vector &shape) const
03368 {
03369    shape(0) = 1.0;
03370 }
03371 
03372 void P0TetFiniteElement::CalcDShape(const IntegrationPoint &ip,
03373                                     DenseMatrix &dshape) const
03374 {
03375    dshape(0,0) =  0.0; dshape(0,1) =  0.0; dshape(0,2) = 0.0;
03376 }
03377 
03378 
03379 P0HexFiniteElement::P0HexFiniteElement()
03380    : NodalFiniteElement(3, Geometry::CUBE, 1, 0, FunctionSpace::Qk)
03381 {
03382    Nodes.IntPoint(0).x = 0.5;
03383    Nodes.IntPoint(0).y = 0.5;
03384    Nodes.IntPoint(0).z = 0.5;
03385 }
03386 
03387 void P0HexFiniteElement::CalcShape(const IntegrationPoint &ip,
03388                                    Vector &shape) const
03389 {
03390    shape(0) = 1.0;
03391 }
03392 
03393 void P0HexFiniteElement::CalcDShape(const IntegrationPoint &ip,
03394                                     DenseMatrix &dshape) const
03395 {
03396    dshape(0,0) =  0.0; dshape(0,1) =  0.0; dshape(0,2) = 0.0;
03397 }
03398 
03399 
03400 LagrangeHexFiniteElement::LagrangeHexFiniteElement (int degree)
03401    : NodalFiniteElement(3, Geometry::CUBE, (degree+1)*(degree+1)*(degree+1),
03402                         degree, FunctionSpace::Qk)
03403 {
03404    if (degree == 2)
03405    {
03406       I = new int[Dof];
03407       J = new int[Dof];
03408       K = new int[Dof];
03409       // nodes
03410       I[ 0] = 0; J[ 0] = 0; K[ 0] = 0;
03411       I[ 1] = 1; J[ 1] = 0; K[ 1] = 0;
03412       I[ 2] = 1; J[ 2] = 1; K[ 2] = 0;
03413       I[ 3] = 0; J[ 3] = 1; K[ 3] = 0;
03414       I[ 4] = 0; J[ 4] = 0; K[ 4] = 1;
03415       I[ 5] = 1; J[ 5] = 0; K[ 5] = 1;
03416       I[ 6] = 1; J[ 6] = 1; K[ 6] = 1;
03417       I[ 7] = 0; J[ 7] = 1; K[ 7] = 1;
03418       // edges
03419       I[ 8] = 2; J[ 8] = 0; K[ 8] = 0;
03420       I[ 9] = 1; J[ 9] = 2; K[ 9] = 0;
03421       I[10] = 2; J[10] = 1; K[10] = 0;
03422       I[11] = 0; J[11] = 2; K[11] = 0;
03423       I[12] = 2; J[12] = 0; K[12] = 1;
03424       I[13] = 1; J[13] = 2; K[13] = 1;
03425       I[14] = 2; J[14] = 1; K[14] = 1;
03426       I[15] = 0; J[15] = 2; K[15] = 1;
03427       I[16] = 0; J[16] = 0; K[16] = 2;
03428       I[17] = 1; J[17] = 0; K[17] = 2;
03429       I[18] = 1; J[18] = 1; K[18] = 2;
03430       I[19] = 0; J[19] = 1; K[19] = 2;
03431       // faces
03432       I[20] = 2; J[20] = 2; K[20] = 0;
03433       I[21] = 2; J[21] = 0; K[21] = 2;
03434       I[22] = 1; J[22] = 2; K[22] = 2;
03435       I[23] = 2; J[23] = 1; K[23] = 2;
03436       I[24] = 0; J[24] = 2; K[24] = 2;
03437       I[25] = 2; J[25] = 2; K[25] = 1;
03438       // element
03439       I[26] = 2; J[26] = 2; K[26] = 2;
03440    }
03441    else if (degree == 3)
03442    {
03443       I = new int[Dof];
03444       J = new int[Dof];
03445       K = new int[Dof];
03446       // nodes
03447       I[ 0] = 0; J[ 0] = 0; K[ 0] = 0;
03448       I[ 1] = 1; J[ 1] = 0; K[ 1] = 0;
03449       I[ 2] = 1; J[ 2] = 1; K[ 2] = 0;
03450       I[ 3] = 0; J[ 3] = 1; K[ 3] = 0;
03451       I[ 4] = 0; J[ 4] = 0; K[ 4] = 1;
03452       I[ 5] = 1; J[ 5] = 0; K[ 5] = 1;
03453       I[ 6] = 1; J[ 6] = 1; K[ 6] = 1;
03454       I[ 7] = 0; J[ 7] = 1; K[ 7] = 1;
03455       // edges
03456       I[ 8] = 2; J[ 8] = 0; K[ 8] = 0;
03457       I[ 9] = 3; J[ 9] = 0; K[ 9] = 0;
03458       I[10] = 1; J[10] = 2; K[10] = 0;
03459       I[11] = 1; J[11] = 3; K[11] = 0;
03460       I[12] = 2; J[12] = 1; K[12] = 0;
03461       I[13] = 3; J[13] = 1; K[13] = 0;
03462       I[14] = 0; J[14] = 2; K[14] = 0;
03463       I[15] = 0; J[15] = 3; K[15] = 0;
03464       I[16] = 2; J[16] = 0; K[16] = 1;
03465       I[17] = 3; J[17] = 0; K[17] = 1;
03466       I[18] = 1; J[18] = 2; K[18] = 1;
03467       I[19] = 1; J[19] = 3; K[19] = 1;
03468       I[20] = 2; J[20] = 1; K[20] = 1;
03469       I[21] = 3; J[21] = 1; K[21] = 1;
03470       I[22] = 0; J[22] = 2; K[22] = 1;
03471       I[23] = 0; J[23] = 3; K[23] = 1;
03472       I[24] = 0; J[24] = 0; K[24] = 2;
03473       I[25] = 0; J[25] = 0; K[25] = 3;
03474       I[26] = 1; J[26] = 0; K[26] = 2;
03475       I[27] = 1; J[27] = 0; K[27] = 3;
03476       I[28] = 1; J[28] = 1; K[28] = 2;
03477       I[29] = 1; J[29] = 1; K[29] = 3;
03478       I[30] = 0; J[30] = 1; K[30] = 2;
03479       I[31] = 0; J[31] = 1; K[31] = 3;
03480       // faces
03481       I[32] = 2; J[32] = 3; K[32] = 0;
03482       I[33] = 3; J[33] = 3; K[33] = 0;
03483       I[34] = 2; J[34] = 2; K[34] = 0;
03484       I[35] = 3; J[35] = 2; K[35] = 0;
03485       I[36] = 2; J[36] = 0; K[36] = 2;
03486       I[37] = 3; J[37] = 0; K[37] = 2;
03487       I[38] = 2; J[38] = 0; K[38] = 3;
03488       I[39] = 3; J[39] = 0; K[39] = 3;
03489       I[40] = 1; J[40] = 2; K[40] = 2;
03490       I[41] = 1; J[41] = 3; K[41] = 2;
03491       I[42] = 1; J[42] = 2; K[42] = 3;
03492       I[43] = 1; J[43] = 3; K[43] = 3;
03493       I[44] = 3; J[44] = 1; K[44] = 2;
03494       I[45] = 2; J[45] = 1; K[45] = 2;
03495       I[46] = 3; J[46] = 1; K[46] = 3;
03496       I[47] = 2; J[47] = 1; K[47] = 3;
03497       I[48] = 0; J[48] = 3; K[48] = 2;
03498       I[49] = 0; J[49] = 2; K[49] = 2;
03499       I[50] = 0; J[50] = 3; K[50] = 3;
03500       I[51] = 0; J[51] = 2; K[51] = 3;
03501       I[52] = 2; J[52] = 2; K[52] = 1;
03502       I[53] = 3; J[53] = 2; K[53] = 1;
03503       I[54] = 2; J[54] = 3; K[54] = 1;
03504       I[55] = 3; J[55] = 3; K[55] = 1;
03505       // element
03506       I[56] = 2; J[56] = 2; K[56] = 2;
03507       I[57] = 3; J[57] = 2; K[57] = 2;
03508       I[58] = 3; J[58] = 3; K[58] = 2;
03509       I[59] = 2; J[59] = 3; K[59] = 2;
03510       I[60] = 2; J[60] = 2; K[60] = 3;
03511       I[61] = 3; J[61] = 2; K[61] = 3;
03512       I[62] = 3; J[62] = 3; K[62] = 3;
03513       I[63] = 2; J[63] = 3; K[63] = 3;
03514    }
03515    else
03516    {
03517       mfem_error ("LagrangeHexFiniteElement::LagrangeHexFiniteElement");
03518    }
03519 
03520    fe1d = new Lagrange1DFiniteElement(degree);
03521    dof1d = fe1d -> GetDof();
03522 
03523 #ifndef MFEM_USE_OPENMP
03524    shape1dx.SetSize(dof1d);
03525    shape1dy.SetSize(dof1d);
03526    shape1dz.SetSize(dof1d);
03527 
03528    dshape1dx.SetSize(dof1d,1);
03529    dshape1dy.SetSize(dof1d,1);
03530    dshape1dz.SetSize(dof1d,1);
03531 #endif
03532 
03533    for (int n = 0; n < Dof; n++)
03534    {
03535       Nodes.IntPoint(n).x = fe1d -> GetNodes().IntPoint(I[n]).x;
03536       Nodes.IntPoint(n).y = fe1d -> GetNodes().IntPoint(J[n]).x;
03537       Nodes.IntPoint(n).z = fe1d -> GetNodes().IntPoint(K[n]).x;
03538    }
03539 }
03540 
03541 void LagrangeHexFiniteElement::CalcShape(const IntegrationPoint &ip,
03542                                          Vector &shape) const
03543 {
03544    IntegrationPoint ipy, ipz;
03545    ipy.x = ip.y;
03546    ipz.x = ip.z;
03547 
03548 #ifdef MFEM_USE_OPENMP
03549    Vector shape1dx(dof1d), shape1dy(dof1d), shape1dz(dof1d);
03550 #endif
03551 
03552    fe1d -> CalcShape(ip,  shape1dx);
03553    fe1d -> CalcShape(ipy, shape1dy);
03554    fe1d -> CalcShape(ipz, shape1dz);
03555 
03556    for (int n = 0; n < Dof; n++)
03557       shape(n) = shape1dx(I[n]) *  shape1dy(J[n]) * shape1dz(K[n]);
03558 }
03559 
03560 void LagrangeHexFiniteElement::CalcDShape(const IntegrationPoint &ip,
03561                                           DenseMatrix &dshape) const
03562 {
03563    IntegrationPoint ipy, ipz;
03564    ipy.x = ip.y;
03565    ipz.x = ip.z;
03566 
03567 #ifdef MFEM_USE_OPENMP
03568    Vector shape1dx(dof1d), shape1dy(dof1d), shape1dz(dof1d);
03569    DenseMatrix dshape1dx(dof1d,1), dshape1dy(dof1d,1), dshape1dz(dof1d,1);
03570 #endif
03571 
03572    fe1d -> CalcShape(ip,  shape1dx);
03573    fe1d -> CalcShape(ipy, shape1dy);
03574    fe1d -> CalcShape(ipz, shape1dz);
03575 
03576    fe1d -> CalcDShape(ip,  dshape1dx);
03577    fe1d -> CalcDShape(ipy, dshape1dy);
03578    fe1d -> CalcDShape(ipz, dshape1dz);
03579 
03580    for (int n = 0; n < Dof; n++) {
03581       dshape(n,0) = dshape1dx(I[n],0) * shape1dy(J[n])    * shape1dz(K[n]);
03582       dshape(n,1) = shape1dx(I[n])    * dshape1dy(J[n],0) * shape1dz(K[n]);
03583       dshape(n,2) = shape1dx(I[n])    * shape1dy(J[n])    * dshape1dz(K[n],0);
03584    }
03585 }
03586 
03587 LagrangeHexFiniteElement::~LagrangeHexFiniteElement ()
03588 {
03589    delete fe1d;
03590 
03591    delete [] I;
03592    delete [] J;
03593    delete [] K;
03594 }
03595 
03596 
03597 RefinedLinear1DFiniteElement::RefinedLinear1DFiniteElement()
03598    : NodalFiniteElement(1, Geometry::SEGMENT, 3, 4)
03599 {
03600    Nodes.IntPoint(0).x = 0.0;
03601    Nodes.IntPoint(1).x = 1.0;
03602    Nodes.IntPoint(2).x = 0.5;
03603 }
03604 
03605 void RefinedLinear1DFiniteElement::CalcShape(const IntegrationPoint &ip,
03606                                              Vector &shape) const
03607 {
03608    double x = ip.x;
03609 
03610    if (x <= 0.5) {
03611       shape(0) = 1.0 - 2.0 * x;
03612       shape(1) = 0.0;
03613       shape(2) = 2.0 * x;
03614    } else {
03615       shape(0) = 0.0;
03616       shape(1) = 2.0 * x - 1.0;
03617       shape(2) = 2.0 - 2.0 * x;
03618    }
03619 }
03620 
03621 void RefinedLinear1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
03622                                               DenseMatrix &dshape) const
03623 {
03624    double x = ip.x;
03625 
03626    if (x <= 0.5) {
03627       dshape(0,0) = - 2.0;
03628       dshape(1,0) =   0.0;
03629       dshape(2,0) =   2.0;
03630    } else {
03631       dshape(0,0) =   0.0;
03632       dshape(1,0) =   2.0;
03633       dshape(2,0) = - 2.0;
03634    }
03635 }
03636 
03637 RefinedLinear2DFiniteElement::RefinedLinear2DFiniteElement()
03638    : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 5)
03639 {
03640    Nodes.IntPoint(0).x = 0.0;
03641    Nodes.IntPoint(0).y = 0.0;
03642    Nodes.IntPoint(1).x = 1.0;
03643    Nodes.IntPoint(1).y = 0.0;
03644    Nodes.IntPoint(2).x = 0.0;
03645    Nodes.IntPoint(2).y = 1.0;
03646    Nodes.IntPoint(3).x = 0.5;
03647    Nodes.IntPoint(3).y = 0.0;
03648    Nodes.IntPoint(4).x = 0.5;
03649    Nodes.IntPoint(4).y = 0.5;
03650    Nodes.IntPoint(5).x = 0.0;
03651    Nodes.IntPoint(5).y = 0.5;
03652 }
03653 
03654 void RefinedLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
03655                                              Vector &shape) const
03656 {
03657    int i;
03658 
03659    double L0, L1, L2;
03660    L0 = 2.0 * ( 1. - ip.x - ip.y );
03661    L1 = 2.0 * ( ip.x );
03662    L2 = 2.0 * ( ip.y );
03663 
03664    // The reference triangle is split in 4 triangles as follows:
03665    //
03666    // T0 - 0,3,5
03667    // T1 - 1,3,4
03668    // T2 - 2,4,5
03669    // T3 - 3,4,5
03670 
03671    for (i = 0; i < 6; i++)
03672       shape(i) = 0.0;
03673 
03674    if (L0 >= 1.0) { // T0
03675       shape(0) = L0 - 1.0;
03676       shape(3) =       L1;
03677       shape(5) =       L2;
03678    }
03679    else if (L1 >= 1.0) { // T1
03680       shape(3) =       L0;
03681       shape(1) = L1 - 1.0;
03682       shape(4) =       L2;
03683    }
03684    else if (L2 >= 1.0) { // T2
03685       shape(5) =       L0;
03686       shape(4) =       L1;
03687       shape(2) = L2 - 1.0;
03688    }
03689    else { // T3
03690       shape(3) = 1.0 - L2;
03691       shape(4) = 1.0 - L0;
03692       shape(5) = 1.0 - L1;
03693    }
03694 }
03695 
03696 void RefinedLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
03697                                               DenseMatrix &dshape) const
03698 {
03699    int i,j;
03700 
03701    double L0, L1, L2;
03702    L0 = 2.0 * ( 1. - ip.x - ip.y );
03703    L1 = 2.0 * ( ip.x );
03704    L2 = 2.0 * ( ip.y );
03705 
03706    double DL0[2], DL1[2], DL2[2];
03707    DL0[0] = -2.0; DL0[1] = -2.0;
03708    DL1[0] =  2.0; DL1[1] =  0.0;
03709    DL2[0] =  0.0; DL2[1] =  2.0;
03710 
03711    for (i = 0; i < 6; i++)
03712       for (j = 0; j < 2; j++)
03713          dshape(i,j) = 0.0;
03714 
03715    if (L0 >= 1.0) { // T0
03716       for (j = 0; j < 2; j++) {
03717          dshape(0,j) = DL0[j];
03718          dshape(3,j) = DL1[j];
03719          dshape(5,j) = DL2[j];
03720       }
03721    }
03722    else if (L1 >= 1.0) { // T1
03723       for (j = 0; j < 2; j++) {
03724          dshape(3,j) = DL0[j];
03725          dshape(1,j) = DL1[j];
03726          dshape(4,j) = DL2[j];
03727       }
03728    }
03729    else if (L2 >= 1.0) { // T2
03730       for (j = 0; j < 2; j++) {
03731          dshape(5,j) = DL0[j];
03732          dshape(4,j) = DL1[j];
03733          dshape(2,j) = DL2[j];
03734       }
03735    }
03736    else { // T3
03737       for (j = 0; j < 2; j++) {
03738          dshape(3,j) = - DL2[j];
03739          dshape(4,j) = - DL0[j];
03740          dshape(5,j) = - DL1[j];
03741       }
03742    }
03743 }
03744 
03745 RefinedLinear3DFiniteElement::RefinedLinear3DFiniteElement()
03746    : NodalFiniteElement(3, Geometry::TETRAHEDRON, 10, 4)
03747 {
03748    Nodes.IntPoint(0).x = 0.0;
03749    Nodes.IntPoint(0).y = 0.0;
03750    Nodes.IntPoint(0).z = 0.0;
03751    Nodes.IntPoint(1).x = 1.0;
03752    Nodes.IntPoint(1).y = 0.0;
03753    Nodes.IntPoint(1).z = 0.0;
03754    Nodes.IntPoint(2).x = 0.0;
03755    Nodes.IntPoint(2).y = 1.0;
03756    Nodes.IntPoint(2).z = 0.0;
03757    Nodes.IntPoint(3).x = 0.0;
03758    Nodes.IntPoint(3).y = 0.0;
03759    Nodes.IntPoint(3).z = 1.0;
03760    Nodes.IntPoint(4).x = 0.5;
03761    Nodes.IntPoint(4).y = 0.0;
03762    Nodes.IntPoint(4).z = 0.0;
03763    Nodes.IntPoint(5).x = 0.0;
03764    Nodes.IntPoint(5).y = 0.5;
03765    Nodes.IntPoint(5).z = 0.0;
03766    Nodes.IntPoint(6).x = 0.0;
03767    Nodes.IntPoint(6).y = 0.0;
03768    Nodes.IntPoint(6).z = 0.5;
03769    Nodes.IntPoint(7).x = 0.5;
03770    Nodes.IntPoint(7).y = 0.5;
03771    Nodes.IntPoint(7).z = 0.0;
03772    Nodes.IntPoint(8).x = 0.5;
03773    Nodes.IntPoint(8).y = 0.0;
03774    Nodes.IntPoint(8).z = 0.5;
03775    Nodes.IntPoint(9).x = 0.0;
03776    Nodes.IntPoint(9).y = 0.5;
03777    Nodes.IntPoint(9).z = 0.5;
03778 }
03779 
03780 void RefinedLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
03781                                              Vector &shape) const
03782 {
03783    int i;
03784 
03785    double L0, L1, L2, L3, L4, L5;
03786    L0 = 2.0 * ( 1. - ip.x - ip.y - ip.z );
03787    L1 = 2.0 * ( ip.x );
03788    L2 = 2.0 * ( ip.y );
03789    L3 = 2.0 * ( ip.z );
03790    L4 = 2.0 * ( ip.x + ip.y );
03791    L5 = 2.0 * ( ip.y + ip.z );
03792 
03793    // The reference tetrahedron is split in 8 tetrahedra as follows:
03794    //
03795    // T0 - 0,4,5,6
03796    // T1 - 1,4,7,8
03797    // T2 - 2,5,7,9
03798    // T3 - 3,6,8,9
03799    // T4 - 4,5,6,8
03800    // T5 - 4,5,7,8
03801    // T6 - 5,6,8,9
03802    // T7 - 5,7,8,9
03803 
03804    for (i = 0; i < 10; i++)
03805       shape(i) = 0.0;
03806 
03807    if (L0 >= 1.0) { // T0
03808       shape(0) = L0 - 1.0;
03809       shape(4) =       L1;
03810       shape(5) =       L2;
03811       shape(6) =       L3;
03812    }
03813    else if (L1 >= 1.0) { // T1
03814       shape(4) =       L0;
03815       shape(1) = L1 - 1.0;
03816       shape(7) =       L2;
03817       shape(8) =       L3;
03818    }
03819    else if (L2 >= 1.0) { // T2
03820       shape(5) =       L0;
03821       shape(7) =       L1;
03822       shape(2) = L2 - 1.0;
03823       shape(9) =       L3;
03824    }
03825    else if (L3 >= 1.0) { // T3
03826       shape(6) =       L0;
03827       shape(8) =       L1;
03828       shape(9) =       L2;
03829       shape(3) = L3 - 1.0;
03830    }
03831    else if ((L4 <= 1.0) && (L5 <= 1.0)) { // T4
03832       shape(4) = 1.0 - L5;
03833       shape(5) =       L2;
03834       shape(6) = 1.0 - L4;
03835       shape(8) = 1.0 - L0;
03836    }
03837    else if ((L4 >= 1.0) && (L5 <= 1.0)) { // T5
03838       shape(4) = 1.0 - L5;
03839       shape(5) = 1.0 - L1;
03840       shape(7) = L4 - 1.0;
03841       shape(8) =       L3;
03842    }
03843    else if ((L4 <= 1.0) && (L5 >= 1.0)) { // T6
03844       shape(5) = 1.0 - L3;
03845       shape(6) = 1.0 - L4;
03846       shape(8) =       L1;
03847       shape(9) = L5 - 1.0;
03848    }
03849    else if ((L4 >= 1.0) && (L5 >= 1.0)) { // T7
03850       shape(5) =       L0;
03851       shape(7) = L4 - 1.0;
03852       shape(8) = 1.0 - L2;
03853       shape(9) = L5 - 1.0;
03854    }
03855 }
03856 
03857 void RefinedLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
03858                                               DenseMatrix &dshape) const
03859 {
03860    int i,j;
03861 
03862    double L0, L1, L2, L3, L4, L5;
03863    L0 = 2.0 * ( 1. - ip.x - ip.y - ip.z );
03864    L1 = 2.0 * ( ip.x );
03865    L2 = 2.0 * ( ip.y );
03866    L3 = 2.0 * ( ip.z );
03867    L4 = 2.0 * ( ip.x + ip.y );
03868    L5 = 2.0 * ( ip.y + ip.z );
03869 
03870    double DL0[3], DL1[3], DL2[3], DL3[3], DL4[3], DL5[3];
03871    DL0[0] = -2.0; DL0[1] = -2.0; DL0[2] = -2.0;
03872    DL1[0] =  2.0; DL1[1] =  0.0; DL1[2] =  0.0;
03873    DL2[0] =  0.0; DL2[1] =  2.0; DL2[2] =  0.0;
03874    DL3[0] =  0.0; DL3[1] =  0.0; DL3[2] =  2.0;
03875    DL4[0] =  2.0; DL4[1] =  2.0; DL4[2] =  0.0;
03876    DL5[0] =  0.0; DL5[1] =  2.0; DL5[2] =  2.0;
03877 
03878    for (i = 0; i < 10; i++)
03879       for (j = 0; j < 3; j++)
03880          dshape(i,j) = 0.0;
03881 
03882    if (L0 >= 1.0) { // T0
03883       for (j = 0; j < 3; j++) {
03884          dshape(0,j) = DL0[j];
03885          dshape(4,j) = DL1[j];
03886          dshape(5,j) = DL2[j];
03887          dshape(6,j) = DL3[j];
03888       }
03889    }
03890    else if (L1 >= 1.0) { // T1
03891       for (j = 0; j < 3; j++) {
03892          dshape(4,j) = DL0[j];
03893          dshape(1,j) = DL1[j];
03894          dshape(7,j) = DL2[j];
03895          dshape(8,j) = DL3[j];
03896       }
03897    }
03898    else if (L2 >= 1.0) { // T2
03899       for (j = 0; j < 3; j++) {
03900          dshape(5,j) = DL0[j];
03901          dshape(7,j) = DL1[j];
03902          dshape(2,j) = DL2[j];
03903          dshape(9,j) = DL3[j];
03904       }
03905    }
03906    else if (L3 >= 1.0) { // T3
03907       for (j = 0; j < 3; j++) {
03908          dshape(6,j) = DL0[j];
03909          dshape(8,j) = DL1[j];
03910          dshape(9,j) = DL2[j];
03911          dshape(3,j) = DL3[j];
03912       }
03913    }
03914    else if ((L4 <= 1.0) && (L5 <= 1.0)) { // T4
03915       for (j = 0; j < 3; j++) {
03916          dshape(4,j) = - DL5[j];
03917          dshape(5,j) =   DL2[j];
03918          dshape(6,j) = - DL4[j];
03919          dshape(8,j) = - DL0[j];
03920       }
03921    }
03922    else if ((L4 >= 1.0) && (L5 <= 1.0)) { // T5
03923       for (j = 0; j < 3; j++) {
03924          dshape(4,j) = - DL5[j];
03925          dshape(5,j) = - DL1[j];
03926          dshape(7,j) =   DL4[j];
03927          dshape(8,j) =   DL3[j];
03928       }
03929    }
03930    else if ((L4 <= 1.0) && (L5 >= 1.0)) { // T6
03931       for (j = 0; j < 3; j++) {
03932          dshape(5,j) = - DL3[j];
03933          dshape(6,j) = - DL4[j];
03934          dshape(8,j) =   DL1[j];
03935          dshape(9,j) =   DL5[j];
03936       }
03937    }
03938    else if ((L4 >= 1.0) && (L5 >= 1.0)) { // T7
03939       for (j = 0; j < 3; j++) {
03940          dshape(5,j) =   DL0[j];
03941          dshape(7,j) =   DL4[j];
03942          dshape(8,j) = - DL2[j];
03943          dshape(9,j) =   DL5[j];
03944       }
03945    }
03946 }
03947 
03948 
03949 RefinedBiLinear2DFiniteElement::RefinedBiLinear2DFiniteElement()
03950    : NodalFiniteElement(2, Geometry::SQUARE , 9, 1, FunctionSpace::rQk)
03951 {
03952    Nodes.IntPoint(0).x = 0.0;
03953    Nodes.IntPoint(0).y = 0.0;
03954    Nodes.IntPoint(1).x = 1.0;
03955    Nodes.IntPoint(1).y = 0.0;
03956    Nodes.IntPoint(2).x = 1.0;
03957    Nodes.IntPoint(2).y = 1.0;
03958    Nodes.IntPoint(3).x = 0.0;
03959    Nodes.IntPoint(3).y = 1.0;
03960    Nodes.IntPoint(4).x = 0.5;
03961    Nodes.IntPoint(4).y = 0.0;
03962    Nodes.IntPoint(5).x = 1.0;
03963    Nodes.IntPoint(5).y = 0.5;
03964    Nodes.IntPoint(6).x = 0.5;
03965    Nodes.IntPoint(6).y = 1.0;
03966    Nodes.IntPoint(7).x = 0.0;
03967    Nodes.IntPoint(7).y = 0.5;
03968    Nodes.IntPoint(8).x = 0.5;
03969    Nodes.IntPoint(8).y = 0.5;
03970 }
03971 
03972 void RefinedBiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
03973                                                Vector &shape) const
03974 {
03975    int i;
03976    double x = ip.x, y = ip.y;
03977    double Lx, Ly;
03978    Lx = 2.0 * ( 1. - x );
03979    Ly = 2.0 * ( 1. - y );
03980 
03981    // The reference square is split in 4 squares as follows:
03982    //
03983    // T0 - 0,4,7,8
03984    // T1 - 1,4,5,8
03985    // T2 - 2,5,6,8
03986    // T3 - 3,6,7,8
03987 
03988    for (i = 0; i < 9; i++)
03989       shape(i) = 0.0;
03990 
03991    if ((x <= 0.5) && (y <= 0.5)) { // T0
03992       shape(0) = (Lx - 1.0) * (Ly - 1.0);
03993       shape(4) = (2.0 - Lx) * (Ly - 1.0);
03994       shape(8) = (2.0 - Lx) * (2.0 - Ly);
03995       shape(7) = (Lx - 1.0) * (2.0 - Ly);
03996    }
03997    else if ((x >= 0.5) && (y <= 0.5)) { // T1
03998       shape(4) =        Lx  * (Ly - 1.0);
03999       shape(1) = (1.0 - Lx) * (Ly - 1.0);
04000       shape(5) = (1.0 - Lx) * (2.0 - Ly);
04001       shape(8) =        Lx  * (2.0 - Ly);
04002    }
04003    else if ((x >= 0.5) && (y >= 0.5)) { // T2
04004       shape(8) =        Lx  *        Ly ;
04005       shape(5) = (1.0 - Lx) *        Ly ;
04006       shape(2) = (1.0 - Lx) * (1.0 - Ly);
04007       shape(6) =        Lx  * (1.0 - Ly);
04008    }
04009    else if ((x <= 0.5) && (y >= 0.5)) { // T3
04010       shape(7) = (Lx - 1.0) *        Ly ;
04011       shape(8) = (2.0 - Lx) *        Ly ;
04012       shape(6) = (2.0 - Lx) * (1.0 - Ly);
04013       shape(3) = (Lx - 1.0) * (1.0 - Ly);
04014    }
04015 }
04016 
04017 void RefinedBiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
04018                                                 DenseMatrix &dshape) const
04019 {
04020    int i,j;
04021    double x = ip.x, y = ip.y;
04022    double Lx, Ly;
04023    Lx = 2.0 * ( 1. - x );
04024    Ly = 2.0 * ( 1. - y );
04025 
04026    for (i = 0; i < 9; i++)
04027       for (j = 0; j < 2; j++)
04028          dshape(i,j) = 0.0;
04029 
04030    if ((x <= 0.5) && (y <= 0.5)) { // T0
04031       dshape(0,0) =  2.0 * (1.0 - Ly);
04032       dshape(0,1) =  2.0 * (1.0 - Lx);
04033 
04034       dshape(4,0) =  2.0 * (Ly - 1.0);
04035       dshape(4,1) = -2.0 * (2.0 - Lx);
04036 
04037       dshape(8,0) =  2.0 * (2.0 - Ly);
04038       dshape(8,1) =  2.0 * (2.0 - Lx);
04039 
04040       dshape(7,0) = -2.0 * (2.0 - Ly);
04041       dshape(7,0) =  2.0 * (Lx - 1.0);
04042    }
04043    else if ((x >= 0.5) && (y <= 0.5)) { // T1
04044       dshape(4,0) = -2.0 * (Ly - 1.0);
04045       dshape(4,1) = -2.0 * Lx;
04046 
04047       dshape(1,0) =  2.0 * (Ly - 1.0);
04048       dshape(1,1) = -2.0 * (1.0 - Lx);
04049 
04050       dshape(5,0) =  2.0 * (2.0 - Ly);
04051       dshape(5,1) =  2.0 * (1.0 - Lx);
04052 
04053       dshape(8,0) = -2.0 * (2.0 - Ly);
04054       dshape(8,1) =  2.0 * Lx;
04055    }
04056    else if ((x >= 0.5) && (y >= 0.5)) { // T2
04057       dshape(8,0) = -2.0 * Ly;
04058       dshape(8,1) = -2.0 * Lx;
04059 
04060       dshape(5,0) =  2.0 * Ly;
04061       dshape(5,1) = -2.0 * (1.0 - Lx);
04062 
04063       dshape(2,0) =  2.0 * (1.0 - Ly);
04064       dshape(2,1) =  2.0 * (1.0 - Lx);
04065 
04066       dshape(6,0) = -2.0 * (1.0 - Ly);
04067       dshape(6,1) =  2.0 * Lx;
04068    }
04069    else if ((x <= 0.5) && (y >= 0.5)) { // T3
04070       dshape(7,0) = -2.0 * Ly;
04071       dshape(7,1) = -2.0 * (Lx - 1.0);
04072 
04073       dshape(8,0) =  2.0 * Ly ;
04074       dshape(8,1) = -2.0 * (2.0 - Lx);
04075 
04076       dshape(6,0) = 2.0 * (1.0 - Ly);
04077       dshape(6,1) = 2.0 * (2.0 - Lx);
04078 
04079       dshape(3,0) = -2.0 * (1.0 - Ly);
04080       dshape(3,1) =  2.0 * (Lx - 1.0);
04081    }
04082 }
04083 
04084 RefinedTriLinear3DFiniteElement::RefinedTriLinear3DFiniteElement()
04085    : NodalFiniteElement(3, Geometry::CUBE, 27, 2, FunctionSpace::rQk)
04086 {
04087    double I[27];
04088    double J[27];
04089    double K[27];
04090    // nodes
04091    I[ 0] = 0.0; J[ 0] = 0.0; K[ 0] = 0.0;
04092    I[ 1] = 1.0; J[ 1] = 0.0; K[ 1] = 0.0;
04093    I[ 2] = 1.0; J[ 2] = 1.0; K[ 2] = 0.0;
04094    I[ 3] = 0.0; J[ 3] = 1.0; K[ 3] = 0.0;
04095    I[ 4] = 0.0; J[ 4] = 0.0; K[ 4] = 1.0;
04096    I[ 5] = 1.0; J[ 5] = 0.0; K[ 5] = 1.0;
04097    I[ 6] = 1.0; J[ 6] = 1.0; K[ 6] = 1.0;
04098    I[ 7] = 0.0; J[ 7] = 1.0; K[ 7] = 1.0;
04099    // edges
04100    I[ 8] = 0.5; J[ 8] = 0.0; K[ 8] = 0.0;
04101    I[ 9] = 1.0; J[ 9] = 0.5; K[ 9] = 0.0;
04102    I[10] = 0.5; J[10] = 1.0; K[10] = 0.0;
04103    I[11] = 0.0; J[11] = 0.5; K[11] = 0.0;
04104    I[12] = 0.5; J[12] = 0.0; K[12] = 1.0;
04105    I[13] = 1.0; J[13] = 0.5; K[13] = 1.0;
04106    I[14] = 0.5; J[14] = 1.0; K[14] = 1.0;
04107    I[15] = 0.0; J[15] = 0.5; K[15] = 1.0;
04108    I[16] = 0.0; J[16] = 0.0; K[16] = 0.5;
04109    I[17] = 1.0; J[17] = 0.0; K[17] = 0.5;
04110    I[18] = 1.0; J[18] = 1.0; K[18] = 0.5;
04111    I[19] = 0.0; J[19] = 1.0; K[19] = 0.5;
04112    // faces
04113    I[20] = 0.5; J[20] = 0.5; K[20] = 0.0;
04114    I[21] = 0.5; J[21] = 0.0; K[21] = 0.5;
04115    I[22] = 1.0; J[22] = 0.5; K[22] = 0.5;
04116    I[23] = 0.5; J[23] = 1.0; K[23] = 0.5;
04117    I[24] = 0.0; J[24] = 0.5; K[24] = 0.5;
04118    I[25] = 0.5; J[25] = 0.5; K[25] = 1.0;
04119    // element
04120    I[26] = 0.5; J[26] = 0.5; K[26] = 0.5;
04121 
04122    for (int n = 0; n < 27; n++) {
04123       Nodes.IntPoint(n).x = I[n];
04124       Nodes.IntPoint(n).y = J[n];
04125       Nodes.IntPoint(n).z = K[n];
04126    }
04127 }
04128 
04129 void RefinedTriLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
04130                                                 Vector &shape) const
04131 {
04132    int i, N[8];
04133    double Lx, Ly, Lz;
04134    double x = ip.x, y = ip.y, z = ip.z;
04135 
04136    for (i = 0; i < 27; i++)
04137       shape(i) = 0.0;
04138 
04139    if ((x <= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T0
04140       Lx = 1.0 - 2.0 * x;
04141       Ly = 1.0 - 2.0 * y;
04142       Lz = 1.0 - 2.0 * z;
04143 
04144       N[0] =  0;
04145       N[1] =  8;
04146       N[2] = 20;
04147       N[3] = 11;
04148       N[4] = 16;
04149       N[5] = 21;
04150       N[6] = 26;
04151       N[7] = 24;
04152    }
04153    else if ((x >= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T1
04154       Lx = 2.0 - 2.0 * x;
04155       Ly = 1.0 - 2.0 * y;
04156       Lz = 1.0 - 2.0 * z;
04157 
04158       N[0] =  8;
04159       N[1] =  1;
04160       N[2] =  9;
04161       N[3] = 20;
04162       N[4] = 21;
04163       N[5] = 17;
04164       N[6] = 22;
04165       N[7] = 26;
04166    }
04167    else if ((x <= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T2
04168       Lx = 2.0 - 2.0 * x;
04169       Ly = 2.0 - 2.0 * y;
04170       Lz = 1.0 - 2.0 * z;
04171 
04172       N[0] = 20;
04173       N[1] =  9;
04174       N[2] =  2;
04175       N[3] = 10;
04176       N[4] = 26;
04177       N[5] = 22;
04178       N[6] = 18;
04179       N[7] = 23;
04180    }
04181    else if ((x >= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T3
04182       Lx = 1.0 - 2.0 * x;
04183       Ly = 2.0 - 2.0 * y;
04184       Lz = 1.0 - 2.0 * z;
04185 
04186       N[0] = 11;
04187       N[1] = 20;
04188       N[2] = 10;
04189       N[3] =  3;
04190       N[4] = 24;
04191       N[5] = 26;
04192       N[6] = 23;
04193       N[7] = 19;
04194    }
04195    else if ((x <= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T4
04196       Lx = 1.0 - 2.0 * x;
04197       Ly = 1.0 - 2.0 * y;
04198       Lz = 2.0 - 2.0 * z;
04199 
04200       N[0] = 16;
04201       N[1] = 21;
04202       N[2] = 26;
04203       N[3] = 24;
04204       N[4] =  4;
04205       N[5] = 12;
04206       N[6] = 25;
04207       N[7] = 15;
04208    }
04209    else if ((x >= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T5
04210       Lx = 2.0 - 2.0 * x;
04211       Ly = 1.0 - 2.0 * y;
04212       Lz = 2.0 - 2.0 * z;
04213 
04214       N[0] = 21;
04215       N[1] = 17;
04216       N[2] = 22;
04217       N[3] = 26;
04218       N[4] = 12;
04219       N[5] =  5;
04220       N[6] = 13;
04221       N[7] = 25;
04222    }
04223    else if ((x <= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T6
04224       Lx = 2.0 - 2.0 * x;
04225       Ly = 2.0 - 2.0 * y;
04226       Lz = 2.0 - 2.0 * z;
04227 
04228       N[0] = 26;
04229       N[1] = 22;
04230       N[2] = 18;
04231       N[3] = 23;
04232       N[4] = 25;
04233       N[5] = 13;
04234       N[6] =  6;
04235       N[7] = 14;
04236    }
04237    else if ((x >= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T7
04238       Lx = 1.0 - 2.0 * x;
04239       Ly = 2.0 - 2.0 * y;
04240       Lz = 2.0 - 2.0 * z;
04241 
04242       N[0] = 24;
04243       N[1] = 26;
04244       N[2] = 23;
04245       N[3] = 19;
04246       N[4] = 15;
04247       N[5] = 25;
04248       N[6] = 14;
04249       N[7] =  7;
04250    }
04251 
04252    shape(N[0]) = Lx       * Ly       * Lz;
04253    shape(N[1]) = (1 - Lx) * Ly       * Lz;
04254    shape(N[2]) = (1 - Lx) * (1 - Ly) * Lz;
04255    shape(N[3]) = Lx       * (1 - Ly) * Lz;
04256    shape(N[4]) = Lx       * Ly       * (1 - Lz);
04257    shape(N[5]) = (1 - Lx) * Ly       * (1 - Lz);
04258    shape(N[6]) = (1 - Lx) * (1 - Ly) * (1 - Lz);
04259    shape(N[7]) = Lx       * (1 - Ly) * (1 - Lz);
04260 }
04261 
04262 void RefinedTriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
04263                                                  DenseMatrix &dshape) const
04264 {
04265    int i, j, N[8];
04266    double Lx, Ly, Lz;
04267    double x = ip.x, y = ip.y, z = ip.z;
04268 
04269    for (i = 0; i < 27; i++)
04270       for (j = 0; j < 3; j++)
04271          dshape(i,j) = 0.0;
04272 
04273    if ((x <= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T0
04274       Lx = 1.0 - 2.0 * x;
04275       Ly = 1.0 - 2.0 * y;
04276       Lz = 1.0 - 2.0 * z;
04277 
04278       N[0] =  0;
04279       N[1] =  8;
04280       N[2] = 20;
04281       N[3] = 11;
04282       N[4] = 16;
04283       N[5] = 21;
04284       N[6] = 26;
04285       N[7] = 24;
04286    }
04287    else if ((x >= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T1
04288       Lx = 2.0 - 2.0 * x;
04289       Ly = 1.0 - 2.0 * y;
04290       Lz = 1.0 - 2.0 * z;
04291 
04292       N[0] =  8;
04293       N[1] =  1;
04294       N[2] =  9;
04295       N[3] = 20;
04296       N[4] = 21;
04297       N[5] = 17;
04298       N[6] = 22;
04299       N[7] = 26;
04300    }
04301    else if ((x <= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T2
04302       Lx = 2.0 - 2.0 * x;
04303       Ly = 2.0 - 2.0 * y;
04304       Lz = 1.0 - 2.0 * z;
04305 
04306       N[0] = 20;
04307       N[1] =  9;
04308       N[2] =  2;
04309       N[3] = 10;
04310       N[4] = 26;
04311       N[5] = 22;
04312       N[6] = 18;
04313       N[7] = 23;
04314    }
04315    else if ((x >= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T3
04316       Lx = 1.0 - 2.0 * x;
04317       Ly = 2.0 - 2.0 * y;
04318       Lz = 1.0 - 2.0 * z;
04319 
04320       N[0] = 11;
04321       N[1] = 20;
04322       N[2] = 10;
04323       N[3] =  3;
04324       N[4] = 24;
04325       N[5] = 26;
04326       N[6] = 23;
04327       N[7] = 19;
04328    }
04329    else if ((x <= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T4
04330       Lx = 1.0 - 2.0 * x;
04331       Ly = 1.0 - 2.0 * y;
04332       Lz = 2.0 - 2.0 * z;
04333 
04334       N[0] = 16;
04335       N[1] = 21;
04336       N[2] = 26;
04337       N[3] = 24;
04338       N[4] =  4;
04339       N[5] = 12;
04340       N[6] = 25;
04341       N[7] = 15;
04342    }
04343    else if ((x >= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T5
04344       Lx = 2.0 - 2.0 * x;
04345       Ly = 1.0 - 2.0 * y;
04346       Lz = 2.0 - 2.0 * z;
04347 
04348       N[0] = 21;
04349       N[1] = 17;
04350       N[2] = 22;
04351       N[3] = 26;
04352       N[4] = 12;
04353       N[5] =  5;
04354       N[6] = 13;
04355       N[7] = 25;
04356    }
04357    else if ((x <= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T6
04358       Lx = 2.0 - 2.0 * x;
04359       Ly = 2.0 - 2.0 * y;
04360       Lz = 2.0 - 2.0 * z;
04361 
04362       N[0] = 26;
04363       N[1] = 22;
04364       N[2] = 18;
04365       N[3] = 23;
04366       N[4] = 25;
04367       N[5] = 13;
04368       N[6] =  6;
04369       N[7] = 14;
04370    }
04371    else if ((x >= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T7
04372       Lx = 1.0 - 2.0 * x;
04373       Ly = 2.0 - 2.0 * y;
04374       Lz = 2.0 - 2.0 * z;
04375 
04376       N[0] = 24;
04377       N[1] = 26;
04378       N[2] = 23;
04379       N[3] = 19;
04380       N[4] = 15;
04381       N[5] = 25;
04382       N[6] = 14;
04383       N[7] =  7;
04384    }
04385 
04386    dshape(N[0],0) = -2.0 * Ly       * Lz      ;
04387    dshape(N[0],1) = -2.0 * Lx       * Lz      ;
04388    dshape(N[0],2) = -2.0 * Lx       * Ly      ;
04389 
04390    dshape(N[1],0) =  2.0 * Ly       * Lz      ;
04391    dshape(N[1],1) = -2.0 * (1 - Lx) * Lz      ;
04392    dshape(N[1],2) = -2.0 * (1 - Lx) * Ly      ;
04393 
04394    dshape(N[2],0) =  2.0 * (1 - Ly) * Lz      ;
04395    dshape(N[2],1) =  2.0 * (1 - Lx) * Lz      ;
04396    dshape(N[2],2) = -2.0 * (1 - Lx) * (1 - Ly);
04397 
04398    dshape(N[3],0) = -2.0 * (1 - Ly) * Lz      ;
04399    dshape(N[3],1) =  2.0 * Lx       * Lz      ;
04400    dshape(N[3],2) = -2.0 * Lx       * (1 - Ly);
04401 
04402    dshape(N[4],0) = -2.0 * Ly       * (1 - Lz);
04403    dshape(N[4],1) = -2.0 * Lx       * (1 - Lz);
04404    dshape(N[4],2) =  2.0 * Lx       * Ly      ;
04405 
04406    dshape(N[5],0) =  2.0 * Ly       * (1 - Lz);
04407    dshape(N[5],1) = -2.0 * (1 - Lx) * (1 - Lz);
04408    dshape(N[5],2) =  2.0 * (1 - Lx) * Ly      ;
04409 
04410    dshape(N[6],0) =  2.0 * (1 - Ly) * (1 - Lz);
04411    dshape(N[6],1) =  2.0 * (1 - Lx) * (1 - Lz);
04412    dshape(N[6],2) =  2.0 * (1 - Lx) * (1 - Ly);
04413 
04414    dshape(N[7],0) = -2.0 * (1 - Ly) * (1 - Lz);
04415    dshape(N[7],1) =  2.0 * Lx       * (1 - Lz);
04416    dshape(N[7],2) =  2.0 * Lx       * (1 - Ly);
04417 }
04418 
04419 
04420 Nedelec1HexFiniteElement::Nedelec1HexFiniteElement()
04421    : VectorFiniteElement (3, Geometry::CUBE, 12, 1, FunctionSpace::Qk)
04422 {
04423    // not real nodes ...
04424    Nodes.IntPoint(0).x = 0.5;
04425    Nodes.IntPoint(0).y = 0.0;
04426    Nodes.IntPoint(0).z = 0.0;
04427 
04428    Nodes.IntPoint(1).x = 1.0;
04429    Nodes.IntPoint(1).y = 0.5;
04430    Nodes.IntPoint(1).z = 0.0;
04431 
04432    Nodes.IntPoint(2).x = 0.5;
04433    Nodes.IntPoint(2).y = 1.0;
04434    Nodes.IntPoint(2).z = 0.0;
04435 
04436    Nodes.IntPoint(3).x = 0.0;
04437    Nodes.IntPoint(3).y = 0.5;
04438    Nodes.IntPoint(3).z = 0.0;
04439 
04440    Nodes.IntPoint(4).x = 0.5;
04441    Nodes.IntPoint(4).y = 0.0;
04442    Nodes.IntPoint(4).z = 1.0;
04443 
04444    Nodes.IntPoint(5).x = 1.0;
04445    Nodes.IntPoint(5).y = 0.5;
04446    Nodes.IntPoint(5).z = 1.0;
04447 
04448    Nodes.IntPoint(6).x = 0.5;
04449    Nodes.IntPoint(6).y = 1.0;
04450    Nodes.IntPoint(6).z = 1.0;
04451 
04452    Nodes.IntPoint(7).x = 0.0;
04453    Nodes.IntPoint(7).y = 0.5;
04454    Nodes.IntPoint(7).z = 1.0;
04455 
04456    Nodes.IntPoint(8).x = 0.0;
04457    Nodes.IntPoint(8).y = 0.0;
04458    Nodes.IntPoint(8).z = 0.5;
04459 
04460    Nodes.IntPoint(9).x = 1.0;
04461    Nodes.IntPoint(9).y = 0.0;
04462    Nodes.IntPoint(9).z = 0.5;
04463 
04464    Nodes.IntPoint(10).x= 1.0;
04465    Nodes.IntPoint(10).y= 1.0;
04466    Nodes.IntPoint(10).z= 0.5;
04467 
04468    Nodes.IntPoint(11).x= 0.0;
04469    Nodes.IntPoint(11).y= 1.0;
04470    Nodes.IntPoint(11).z= 0.5;
04471 }
04472 
04473 void Nedelec1HexFiniteElement::CalcVShape(const IntegrationPoint &ip,
04474                                           DenseMatrix &shape) const
04475 {
04476    double x = ip.x, y = ip.y, z = ip.z;
04477 
04478    shape(0,0) = (1. - y) * (1. - z);
04479    shape(0,1) = 0.;
04480    shape(0,2) = 0.;
04481 
04482    shape(2,0) = y * (1. - z);
04483    shape(2,1) = 0.;
04484    shape(2,2) = 0.;
04485 
04486    shape(4,0) = z * (1. - y);
04487    shape(4,1) = 0.;
04488    shape(4,2) = 0.;
04489 
04490    shape(6,0) = y * z;
04491    shape(6,1) = 0.;
04492    shape(6,2) = 0.;
04493 
04494    shape(1,0) = 0.;
04495    shape(1,1) = x * (1. - z);
04496    shape(1,2) = 0.;
04497 
04498    shape(3,0) = 0.;
04499    shape(3,1) = (1. - x) * (1. - z);
04500    shape(3,2) = 0.;
04501 
04502    shape(5,0) = 0.;
04503    shape(5,1) = x * z;
04504    shape(5,2) = 0.;
04505 
04506    shape(7,0) = 0.;
04507    shape(7,1) = (1. - x) * z;
04508    shape(7,2) = 0.;
04509 
04510    shape(8,0) = 0.;
04511    shape(8,1) = 0.;
04512    shape(8,2) = (1. - x) * (1. - y);
04513 
04514    shape(9,0) = 0.;
04515    shape(9,1) = 0.;
04516    shape(9,2) = x * (1. - y);
04517 
04518    shape(10,0) = 0.;
04519    shape(10,1) = 0.;
04520    shape(10,2) = x * y;
04521 
04522    shape(11,0) = 0.;
04523    shape(11,1) = 0.;
04524    shape(11,2) = y * (1. - x);
04525 
04526 }
04527 
04528 void Nedelec1HexFiniteElement::CalcCurlShape(const IntegrationPoint &ip,
04529                                              DenseMatrix &curl_shape)
04530    const
04531 {
04532    double x = ip.x, y = ip.y, z = ip.z;
04533 
04534    curl_shape(0,0) = 0.;
04535    curl_shape(0,1) = y - 1.;
04536    curl_shape(0,2) = 1. - z;
04537 
04538    curl_shape(2,0) = 0.;
04539    curl_shape(2,1) = -y;
04540    curl_shape(2,2) = z - 1.;
04541 
04542    curl_shape(4,0) = 0;
04543    curl_shape(4,1) = 1. - y;
04544    curl_shape(4,2) = z;
04545 
04546    curl_shape(6,0) = 0.;
04547    curl_shape(6,1) = y;
04548    curl_shape(6,2) = -z;
04549 
04550    curl_shape(1,0) = x;
04551    curl_shape(1,1) = 0.;
04552    curl_shape(1,2) = 1. - z;
04553 
04554    curl_shape(3,0) = 1. - x;
04555    curl_shape(3,1) = 0.;
04556    curl_shape(3,2) = z - 1.;
04557 
04558    curl_shape(5,0) = -x;
04559    curl_shape(5,1) = 0.;
04560    curl_shape(5,2) = z;
04561 
04562    curl_shape(7,0) = x - 1.;
04563    curl_shape(7,1) = 0.;
04564    curl_shape(7,2) = -z;
04565 
04566    curl_shape(8,0) = x - 1.;
04567    curl_shape(8,1) = 1. - y;
04568    curl_shape(8,2) = 0.;
04569 
04570    curl_shape(9,0) = -x;
04571    curl_shape(9,1) = y - 1.;
04572    curl_shape(9,2) = 0;
04573 
04574    curl_shape(10,0) = x;
04575    curl_shape(10,1) = -y;
04576    curl_shape(10,2) = 0.;
04577 
04578    curl_shape(11,0) = 1. - x;
04579    curl_shape(11,1) = y;
04580    curl_shape(11,2) = 0.;
04581 }
04582 
04583 const double Nedelec1HexFiniteElement::tk[12][3] =
04584 {{1,0,0}, {0,1,0}, {1,0,0}, {0,1,0},
04585  {1,0,0}, {0,1,0}, {1,0,0}, {0,1,0},
04586  {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}};
04587 
04588 void Nedelec1HexFiniteElement::GetLocalInterpolation (
04589    ElementTransformation &Trans, DenseMatrix &I) const
04590 {
04591    int k, j;
04592 #ifdef MFEM_USE_OPENMP
04593    DenseMatrix vshape(Dof, Dim);
04594 #endif
04595 
04596 #ifdef MFEM_DEBUG
04597    for (k = 0; k < 12; k++)
04598    {
04599       CalcVShape (Nodes.IntPoint(k), vshape);
04600       for (j = 0; j < 12; j++)
04601       {
04602          double d = ( vshape(j,0)*tk[k][0] + vshape(j,1)*tk[k][1] +
04603                       vshape(j,2)*tk[k][2] );
04604          if (j == k) d -= 1.0;
04605          if (fabs(d) > 1.0e-12)
04606          {
04607             cerr << "Nedelec1HexFiniteElement::GetLocalInterpolation (...)\n"
04608                " k = " << k << ", j = " << j << ", d = " << d << endl;
04609             mfem_error();
04610          }
04611       }
04612    }
04613 #endif
04614 
04615    IntegrationPoint ip;
04616    ip.x = ip.y = ip.z = 0.0;
04617    Trans.SetIntPoint (&ip);
04618    // Trans must be linear (more to have embedding?)
04619    const DenseMatrix &J = Trans.Jacobian();
04620    double vk[3];
04621    Vector xk (vk, 3);
04622 
04623    for (k = 0; k < 12; k++)
04624    {
04625       Trans.Transform (Nodes.IntPoint (k), xk);
04626       ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
04627       CalcVShape (ip, vshape);
04628       //  vk = J tk
04629       vk[0] = J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2];
04630       vk[1] = J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2];
04631       vk[2] = J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2];
04632       for (j = 0; j < 12; j++)
04633          if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
04634                              vshape(j,2)*vk[2])) < 1.0e-12)
04635             I(k,j) = 0.0;
04636    }
04637 }
04638 
04639 void Nedelec1HexFiniteElement::Project (
04640    VectorCoefficient &vc, ElementTransformation &Trans,
04641    Vector &dofs) const
04642 {
04643    double vk[3];
04644    Vector xk (vk, 3);
04645 
04646    for (int k = 0; k < 12; k++)
04647    {
04648       Trans.SetIntPoint (&Nodes.IntPoint (k));
04649       const DenseMatrix &J = Trans.Jacobian();
04650 
04651       vc.Eval (xk, Trans, Nodes.IntPoint (k));
04652       //  xk^t J tk
04653       dofs(k) =
04654          vk[0] * ( J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2] ) +
04655          vk[1] * ( J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2] ) +
04656          vk[2] * ( J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2] );
04657    }
04658 }
04659 
04660 
04661 Nedelec1TetFiniteElement::Nedelec1TetFiniteElement()
04662    : VectorFiniteElement (3, Geometry::TETRAHEDRON, 6, 1)
04663 {
04664    // not real nodes ...
04665    Nodes.IntPoint(0).x = 0.5;
04666    Nodes.IntPoint(0).y = 0.0;
04667    Nodes.IntPoint(0).z = 0.0;
04668 
04669    Nodes.IntPoint(1).x = 0.0;
04670    Nodes.IntPoint(1).y = 0.5;
04671    Nodes.IntPoint(1).z = 0.0;
04672 
04673    Nodes.IntPoint(2).x = 0.0;
04674    Nodes.IntPoint(2).y = 0.0;
04675    Nodes.IntPoint(2).z = 0.5;
04676 
04677    Nodes.IntPoint(3).x = 0.5;
04678    Nodes.IntPoint(3).y = 0.5;
04679    Nodes.IntPoint(3).z = 0.0;
04680 
04681    Nodes.IntPoint(4).x = 0.5;
04682    Nodes.IntPoint(4).y = 0.0;
04683    Nodes.IntPoint(4).z = 0.5;
04684 
04685    Nodes.IntPoint(5).x = 0.0;
04686    Nodes.IntPoint(5).y = 0.5;
04687    Nodes.IntPoint(5).z = 0.5;
04688 }
04689 
04690 void Nedelec1TetFiniteElement::CalcVShape(const IntegrationPoint &ip,
04691                                           DenseMatrix &shape) const
04692 {
04693    double x = ip.x, y = ip.y, z = ip.z;
04694 
04695    shape(0,0) = 1. - y - z;
04696    shape(0,1) = x;
04697    shape(0,2) = x;
04698 
04699    shape(1,0) = y;
04700    shape(1,1) = 1. - x - z;
04701    shape(1,2) = y;
04702 
04703    shape(2,0) = z;
04704    shape(2,1) = z;
04705    shape(2,2) = 1. - x - y;
04706 
04707    shape(3,0) = -y;
04708    shape(3,1) = x;
04709    shape(3,2) = 0.;
04710 
04711    shape(4,0) = -z;
04712    shape(4,1) = 0.;
04713    shape(4,2) = x;
04714 
04715    shape(5,0) = 0.;
04716    shape(5,1) = -z;
04717    shape(5,2) = y;
04718 }
04719 
04720 void Nedelec1TetFiniteElement::CalcCurlShape(const IntegrationPoint &ip,
04721                                              DenseMatrix &curl_shape)
04722    const
04723 {
04724    curl_shape(0,0) =  0.;
04725    curl_shape(0,1) = -2.;
04726    curl_shape(0,2) =  2.;
04727 
04728    curl_shape(1,0) =  2.;
04729    curl_shape(1,1) =  0.;
04730    curl_shape(1,2) = -2.;
04731 
04732    curl_shape(2,0) = -2.;
04733    curl_shape(2,1) =  2.;
04734    curl_shape(2,2) =  0.;
04735 
04736    curl_shape(3,0) = 0.;
04737    curl_shape(3,1) = 0.;
04738    curl_shape(3,2) = 2.;
04739 
04740    curl_shape(4,0) =  0.;
04741    curl_shape(4,1) = -2.;
04742    curl_shape(4,2) =  0.;
04743 
04744    curl_shape(5,0) = 2.;
04745    curl_shape(5,1) = 0.;
04746    curl_shape(5,2) = 0.;
04747 }
04748 
04749 const double Nedelec1TetFiniteElement::tk[6][3] =
04750 {{1,0,0}, {0,1,0}, {0,0,1}, {-1,1,0}, {-1,0,1}, {0,-1,1}};
04751 
04752 void Nedelec1TetFiniteElement::GetLocalInterpolation (
04753    ElementTransformation &Trans, DenseMatrix &I) const
04754 {
04755    int k, j;
04756 #ifdef MFEM_USE_OPENMP
04757    DenseMatrix vshape(Dof, Dim);
04758 #endif
04759 
04760 #ifdef MFEM_DEBUG
04761    for (k = 0; k < 6; k++)
04762    {
04763       CalcVShape (Nodes.IntPoint(k), vshape);
04764       for (j = 0; j < 6; j++)
04765       {
04766          double d = ( vshape(j,0)*tk[k][0] + vshape(j,1)*tk[k][1] +
04767                       vshape(j,2)*tk[k][2] );
04768          if (j == k) d -= 1.0;
04769          if (fabs(d) > 1.0e-12)
04770          {
04771             cerr << "Nedelec1TetFiniteElement::GetLocalInterpolation (...)\n"
04772                " k = " << k << ", j = " << j << ", d = " << d << endl;
04773             mfem_error();
04774          }
04775       }
04776    }
04777 #endif
04778 
04779    IntegrationPoint ip;
04780    ip.x = ip.y = ip.z = 0.0;
04781    Trans.SetIntPoint (&ip);
04782    // Trans must be linear
04783    const DenseMatrix &J = Trans.Jacobian();
04784    double vk[3];
04785    Vector xk (vk, 3);
04786 
04787    for (k = 0; k < 6; k++)
04788    {
04789       Trans.Transform (Nodes.IntPoint (k), xk);
04790       ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
04791       CalcVShape (ip, vshape);
04792       //  vk = J tk
04793       vk[0] = J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2];
04794       vk[1] = J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2];
04795       vk[2] = J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2];
04796       for (j = 0; j < 6; j++)
04797          if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
04798                              vshape(j,2)*vk[2])) < 1.0e-12)
04799             I(k,j) = 0.0;
04800    }
04801 }
04802 
04803 void Nedelec1TetFiniteElement::Project (
04804    VectorCoefficient &vc, ElementTransformation &Trans,
04805    Vector &dofs) const
04806 {
04807    double vk[3];
04808    Vector xk (vk, 3);
04809 
04810    for (int k = 0; k < 6; k++)
04811    {
04812       Trans.SetIntPoint (&Nodes.IntPoint (k));
04813       const DenseMatrix &J = Trans.Jacobian();
04814 
04815       vc.Eval (xk, Trans, Nodes.IntPoint (k));
04816       //  xk^t J tk
04817       dofs(k) =
04818          vk[0] * ( J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2] ) +
04819          vk[1] * ( J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2] ) +
04820          vk[2] * ( J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2] );
04821    }
04822 }
04823 
04824 RT0HexFiniteElement::RT0HexFiniteElement()
04825    : VectorFiniteElement (3, Geometry::CUBE, 6, 1, FunctionSpace::Qk)
04826 {
04827    // not real nodes ...
04828    // z = 0, y = 0, x = 1, y = 1, x = 0, z = 1
04829    Nodes.IntPoint(0).x = 0.5;
04830    Nodes.IntPoint(0).y = 0.5;
04831    Nodes.IntPoint(0).z = 0.0;
04832 
04833    Nodes.IntPoint(1).x = 0.5;
04834    Nodes.IntPoint(1).y = 0.0;
04835    Nodes.IntPoint(1).z = 0.5;
04836 
04837    Nodes.IntPoint(2).x = 1.0;
04838    Nodes.IntPoint(2).y = 0.5;
04839    Nodes.IntPoint(2).z = 0.5;
04840 
04841    Nodes.IntPoint(3).x = 0.5;
04842    Nodes.IntPoint(3).y = 1.0;
04843    Nodes.IntPoint(3).z = 0.5;
04844 
04845    Nodes.IntPoint(4).x = 0.0;
04846    Nodes.IntPoint(4).y = 0.5;
04847    Nodes.IntPoint(4).z = 0.5;
04848 
04849    Nodes.IntPoint(5).x = 0.5;
04850    Nodes.IntPoint(5).y = 0.5;
04851    Nodes.IntPoint(5).z = 1.0;
04852 }
04853 
04854 void RT0HexFiniteElement::CalcVShape(const IntegrationPoint &ip,
04855                                      DenseMatrix &shape) const
04856 {
04857    double x = ip.x, y = ip.y, z = ip.z;
04858    // z = 0
04859    shape(0,0) = 0.;
04860    shape(0,1) = 0.;
04861    shape(0,2) = z - 1.;
04862    // y = 0
04863    shape(1,0) = 0.;
04864    shape(1,1) = y - 1.;
04865    shape(1,2) = 0.;
04866    // x = 1
04867    shape(2,0) = x;
04868    shape(2,1) = 0.;
04869    shape(2,2) = 0.;
04870    // y = 1
04871    shape(3,0) = 0.;
04872    shape(3,1) = y;
04873    shape(3,2) = 0.;
04874    // x = 0
04875    shape(4,0) = x - 1.;
04876    shape(4,1) = 0.;
04877    shape(4,2) = 0.;
04878    // z = 1
04879    shape(5,0) = 0.;
04880    shape(5,1) = 0.;
04881    shape(5,2) = z;
04882 }
04883 
04884 void RT0HexFiniteElement::CalcDivShape(const IntegrationPoint &ip,
04885                                        Vector &divshape) const
04886 {
04887    divshape(0) = 1.;
04888    divshape(1) = 1.;
04889    divshape(2) = 1.;
04890    divshape(3) = 1.;
04891    divshape(4) = 1.;
04892    divshape(5) = 1.;
04893 }
04894 
04895 const double RT0HexFiniteElement::nk[6][3] =
04896 {{0,0,-1}, {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0}, {0,0,1}};
04897 
04898 void RT0HexFiniteElement::GetLocalInterpolation (
04899    ElementTransformation &Trans, DenseMatrix &I) const
04900 {
04901    int k, j;
04902 #ifdef MFEM_USE_OPENMP
04903    DenseMatrix vshape(Dof, Dim);
04904    DenseMatrix Jinv(Dim);
04905 #endif
04906 
04907 #ifdef MFEM_DEBUG
04908    for (k = 0; k < 6; k++)
04909    {
04910       CalcVShape (Nodes.IntPoint(k), vshape);
04911       for (j = 0; j < 6; j++)
04912       {
04913          double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] +
04914                       vshape(j,2)*nk[k][2] );
04915          if (j == k) d -= 1.0;
04916          if (fabs(d) > 1.0e-12)
04917          {
04918             cerr << "RT0HexFiniteElement::GetLocalInterpolation (...)\n"
04919                " k = " << k << ", j = " << j << ", d = " << d << endl;
04920             mfem_error();
04921          }
04922       }
04923    }
04924 #endif
04925 
04926    IntegrationPoint ip;
04927    ip.x = ip.y = ip.z = 0.0;
04928    Trans.SetIntPoint (&ip);
04929    // Trans must be linear
04930    // set Jinv = |J| J^{-t} = adj(J)^t
04931    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
04932    double vk[3];
04933    Vector xk (vk, 3);
04934 
04935    for (k = 0; k < 6; k++)
04936    {
04937       Trans.Transform (Nodes.IntPoint (k), xk);
04938       ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
04939       CalcVShape (ip, vshape);
04940       //  vk = |J| J^{-t} nk
04941       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2];
04942       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2];
04943       vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2];
04944       for (j = 0; j < 6; j++)
04945          if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
04946                              vshape(j,2)*vk[2])) < 1.0e-12)
04947             I(k,j) = 0.0;
04948    }
04949 }
04950 
04951 void RT0HexFiniteElement::Project (
04952    VectorCoefficient &vc, ElementTransformation &Trans,
04953    Vector &dofs) const
04954 {
04955    double vk[3];
04956    Vector xk (vk, 3);
04957 #ifdef MFEM_USE_OPENMP
04958    DenseMatrix Jinv(Dim);
04959 #endif
04960 
04961    for (int k = 0; k < 6; k++)
04962    {
04963       Trans.SetIntPoint (&Nodes.IntPoint (k));
04964       // set Jinv = |J| J^{-t} = adj(J)^t
04965       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
04966 
04967       vc.Eval (xk, Trans, Nodes.IntPoint (k));
04968       //  xk^t |J| J^{-t} nk
04969       dofs(k) =
04970          vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) +
04971          vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) +
04972          vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] );
04973    }
04974 }
04975 
04976 RT1HexFiniteElement::RT1HexFiniteElement()
04977    : VectorFiniteElement (3, Geometry::CUBE, 36, 2, FunctionSpace::Qk)
04978 {
04979    // z = 0
04980    Nodes.IntPoint(2).x  = 1./3.;
04981    Nodes.IntPoint(2).y  = 1./3.;
04982    Nodes.IntPoint(2).z  = 0.0;
04983    Nodes.IntPoint(3).x  = 2./3.;
04984    Nodes.IntPoint(3).y  = 1./3.;
04985    Nodes.IntPoint(3).z  = 0.0;
04986    Nodes.IntPoint(0).x  = 1./3.;
04987    Nodes.IntPoint(0).y  = 2./3.;
04988    Nodes.IntPoint(0).z  = 0.0;
04989    Nodes.IntPoint(1).x  = 2./3.;
04990    Nodes.IntPoint(1).y  = 2./3.;
04991    Nodes.IntPoint(1).z  = 0.0;
04992    // y = 0
04993    Nodes.IntPoint(4).x  = 1./3.;
04994    Nodes.IntPoint(4).y  = 0.0;
04995    Nodes.IntPoint(4).z  = 1./3.;
04996    Nodes.IntPoint(5).x  = 2./3.;
04997    Nodes.IntPoint(5).y  = 0.0;
04998    Nodes.IntPoint(5).z  = 1./3.;
04999    Nodes.IntPoint(6).x  = 1./3.;
05000    Nodes.IntPoint(6).y  = 0.0;
05001    Nodes.IntPoint(6).z  = 2./3.;
05002    Nodes.IntPoint(7).x  = 2./3.;
05003    Nodes.IntPoint(7).y  = 0.0;
05004    Nodes.IntPoint(7).z  = 2./3.;
05005    // x = 1
05006    Nodes.IntPoint(8).x  = 1.0;
05007    Nodes.IntPoint(8).y  = 1./3.;
05008    Nodes.IntPoint(8).z  = 1./3.;
05009    Nodes.IntPoint(9).x  = 1.0;
05010    Nodes.IntPoint(9).y  = 2./3.;
05011    Nodes.IntPoint(9).z  = 1./3.;
05012    Nodes.IntPoint(10).x = 1.0;
05013    Nodes.IntPoint(10).y = 1./3.;
05014    Nodes.IntPoint(10).z = 2./3.;
05015    Nodes.IntPoint(11).x = 1.0;
05016    Nodes.IntPoint(11).y = 2./3.;
05017    Nodes.IntPoint(11).z = 2./3.;
05018    // y = 1
05019    Nodes.IntPoint(13).x = 1./3.;
05020    Nodes.IntPoint(13).y = 1.0;
05021    Nodes.IntPoint(13).z = 1./3.;
05022    Nodes.IntPoint(12).x = 2./3.;
05023    Nodes.IntPoint(12).y = 1.0;
05024    Nodes.IntPoint(12).z = 1./3.;
05025    Nodes.IntPoint(15).x = 1./3.;
05026    Nodes.IntPoint(15).y = 1.0;
05027    Nodes.IntPoint(15).z = 2./3.;
05028    Nodes.IntPoint(14).x = 2./3.;
05029    Nodes.IntPoint(14).y = 1.0;
05030    Nodes.IntPoint(14).z = 2./3.;
05031    // x = 0
05032    Nodes.IntPoint(17).x = 0.0;
05033    Nodes.IntPoint(17).y = 1./3.;
05034    Nodes.IntPoint(17).z = 1./3.;
05035    Nodes.IntPoint(16).x = 0.0;
05036    Nodes.IntPoint(16).y = 2./3.;
05037    Nodes.IntPoint(16).z = 1./3.;
05038    Nodes.IntPoint(19).x = 0.0;
05039    Nodes.IntPoint(19).y = 1./3.;
05040    Nodes.IntPoint(19).z = 2./3.;
05041    Nodes.IntPoint(18).x = 0.0;
05042    Nodes.IntPoint(18).y = 2./3.;
05043    Nodes.IntPoint(18).z = 2./3.;
05044    // z = 1
05045    Nodes.IntPoint(20).x = 1./3.;
05046    Nodes.IntPoint(20).y = 1./3.;
05047    Nodes.IntPoint(20).z = 1.0;
05048    Nodes.IntPoint(21).x = 2./3.;
05049    Nodes.IntPoint(21).y = 1./3.;
05050    Nodes.IntPoint(21).z = 1.0;
05051    Nodes.IntPoint(22).x = 1./3.;
05052    Nodes.IntPoint(22).y = 2./3.;
05053    Nodes.IntPoint(22).z = 1.0;
05054    Nodes.IntPoint(23).x = 2./3.;
05055    Nodes.IntPoint(23).y = 2./3.;
05056    Nodes.IntPoint(23).z = 1.0;
05057    // x = 0.5 (interior)
05058    Nodes.IntPoint(24).x = 0.5;
05059    Nodes.IntPoint(24).y = 1./3.;
05060    Nodes.IntPoint(24).z = 1./3.;
05061    Nodes.IntPoint(25).x = 0.5;
05062    Nodes.IntPoint(25).y = 1./3.;
05063    Nodes.IntPoint(25).z = 2./3.;
05064    Nodes.IntPoint(26).x = 0.5;
05065    Nodes.IntPoint(26).y = 2./3.;
05066    Nodes.IntPoint(26).z = 1./3.;
05067    Nodes.IntPoint(27).x = 0.5;
05068    Nodes.IntPoint(27).y = 2./3.;
05069    Nodes.IntPoint(27).z = 2./3.;
05070    // y = 0.5 (interior)
05071    Nodes.IntPoint(28).x = 1./3.;
05072    Nodes.IntPoint(28).y = 0.5;
05073    Nodes.IntPoint(28).z = 1./3.;
05074    Nodes.IntPoint(29).x = 1./3.;
05075    Nodes.IntPoint(29).y = 0.5;
05076    Nodes.IntPoint(29).z = 2./3.;
05077    Nodes.IntPoint(30).x = 2./3.;
05078    Nodes.IntPoint(30).y = 0.5;
05079    Nodes.IntPoint(30).z = 1./3.;
05080    Nodes.IntPoint(31).x = 2./3.;
05081    Nodes.IntPoint(31).y = 0.5;
05082    Nodes.IntPoint(31).z = 2./3.;
05083    // z = 0.5 (interior)
05084    Nodes.IntPoint(32).x = 1./3.;
05085    Nodes.IntPoint(32).y = 1./3.;
05086    Nodes.IntPoint(32).z = 0.5;
05087    Nodes.IntPoint(33).x = 1./3.;
05088    Nodes.IntPoint(33).y = 2./3.;
05089    Nodes.IntPoint(33).z = 0.5;
05090    Nodes.IntPoint(34).x = 2./3.;
05091    Nodes.IntPoint(34).y = 1./3.;
05092    Nodes.IntPoint(34).z = 0.5;
05093    Nodes.IntPoint(35).x = 2./3.;
05094    Nodes.IntPoint(35).y = 2./3.;
05095    Nodes.IntPoint(35).z = 0.5;
05096 }
05097 
05098 void RT1HexFiniteElement::CalcVShape(const IntegrationPoint &ip,
05099                                      DenseMatrix &shape) const
05100 {
05101    double x = ip.x, y = ip.y, z = ip.z;
05102    // z = 0
05103    shape(2,0)  = 0.;
05104    shape(2,1)  = 0.;
05105    shape(2,2)  = -(1. - 3.*z + 2.*z*z)*( 2. - 3.*x)*( 2. - 3.*y);
05106    shape(3,0)  = 0.;
05107    shape(3,1)  = 0.;
05108    shape(3,2)  = -(1. - 3.*z + 2.*z*z)*(-1. + 3.*x)*( 2. - 3.*y);
05109    shape(0,0)  = 0.;
05110    shape(0,1)  = 0.;
05111    shape(0,2)  = -(1. - 3.*z + 2.*z*z)*( 2. - 3.*x)*(-1. + 3.*y);
05112    shape(1,0)  = 0.;
05113    shape(1,1)  = 0.;
05114    shape(1,2)  = -(1. - 3.*z + 2.*z*z)*(-1. + 3.*x)*(-1. + 3.*y);
05115    // y = 0
05116    shape(4,0)  = 0.;
05117    shape(4,1)  = -(1. - 3.*y + 2.*y*y)*( 2. - 3.*x)*( 2. - 3.*z);
05118    shape(4,2)  = 0.;
05119    shape(5,0)  = 0.;
05120    shape(5,1)  = -(1. - 3.*y + 2.*y*y)*(-1. + 3.*x)*( 2. - 3.*z);
05121    shape(5,2)  = 0.;
05122    shape(6,0)  = 0.;
05123    shape(6,1)  = -(1. - 3.*y + 2.*y*y)*( 2. - 3.*x)*(-1. + 3.*z);
05124    shape(6,2)  = 0.;
05125    shape(7,0)  = 0.;
05126    shape(7,1)  = -(1. - 3.*y + 2.*y*y)*(-1. + 3.*x)*(-1. + 3.*z);
05127    shape(7,2)  = 0.;
05128    // x = 1
05129    shape(8,0)  = (-x + 2.*x*x)*( 2. - 3.*y)*( 2. - 3.*z);
05130    shape(8,1)  = 0.;
05131    shape(8,2)  = 0.;
05132    shape(9,0)  = (-x + 2.*x*x)*(-1. + 3.*y)*( 2. - 3.*z);
05133    shape(9,1)  = 0.;
05134    shape(9,2)  = 0.;
05135    shape(10,0) = (-x + 2.*x*x)*( 2. - 3.*y)*(-1. + 3.*z);
05136    shape(10,1) = 0.;
05137    shape(10,2) = 0.;
05138    shape(11,0) = (-x + 2.*x*x)*(-1. + 3.*y)*(-1. + 3.*z);
05139    shape(11,1) = 0.;
05140    shape(11,2) = 0.;
05141    // y = 1
05142    shape(13,0) = 0.;
05143    shape(13,1) = (-y + 2.*y*y)*( 2. - 3.*x)*( 2. - 3.*z);
05144    shape(13,2) = 0.;
05145    shape(12,0) = 0.;
05146    shape(12,1) = (-y + 2.*y*y)*(-1. + 3.*x)*( 2. - 3.*z);
05147    shape(12,2) = 0.;
05148    shape(15,0) = 0.;
05149    shape(15,1) = (-y + 2.*y*y)*( 2. - 3.*x)*(-1. + 3.*z);
05150    shape(15,2) = 0.;
05151    shape(14,0) = 0.;
05152    shape(14,1) = (-y + 2.*y*y)*(-1. + 3.*x)*(-1. + 3.*z);
05153    shape(14,2) = 0.;
05154    // x = 0
05155    shape(17,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y)*( 2. - 3.*z);
05156    shape(17,1) = 0.;
05157    shape(17,2) = 0.;
05158    shape(16,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y)*( 2. - 3.*z);
05159    shape(16,1) = 0.;
05160    shape(16,2) = 0.;
05161    shape(19,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y)*(-1. + 3.*z);
05162    shape(19,1) = 0.;
05163    shape(19,2) = 0.;
05164    shape(18,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y)*(-1. + 3.*z);
05165    shape(18,1) = 0.;
05166    shape(18,2) = 0.;
05167    // z = 1
05168    shape(20,0) = 0.;
05169    shape(20,1) = 0.;
05170    shape(20,2) = (-z + 2.*z*z)*( 2. - 3.*x)*( 2. - 3.*y);
05171    shape(21,0) = 0.;
05172    shape(21,1) = 0.;
05173    shape(21,2) = (-z + 2.*z*z)*(-1. + 3.*x)*( 2. - 3.*y);
05174    shape(22,0) = 0.;
05175    shape(22,1) = 0.;
05176    shape(22,2) = (-z + 2.*z*z)*( 2. - 3.*x)*(-1. + 3.*y);
05177    shape(23,0) = 0.;
05178    shape(23,1) = 0.;
05179    shape(23,2) = (-z + 2.*z*z)*(-1. + 3.*x)*(-1. + 3.*y);
05180    // x = 0.5 (interior)
05181    shape(24,0) = (4.*x - 4.*x*x)*( 2. - 3.*y)*( 2. - 3.*z);
05182    shape(24,1) = 0.;
05183    shape(24,2) = 0.;
05184    shape(25,0) = (4.*x - 4.*x*x)*( 2. - 3.*y)*(-1. + 3.*z);
05185    shape(25,1) = 0.;
05186    shape(25,2) = 0.;
05187    shape(26,0) = (4.*x - 4.*x*x)*(-1. + 3.*y)*( 2. - 3.*z);
05188    shape(26,1) = 0.;
05189    shape(26,2) = 0.;
05190    shape(27,0) = (4.*x - 4.*x*x)*(-1. + 3.*y)*(-1. + 3.*z);
05191    shape(27,1) = 0.;
05192    shape(27,2) = 0.;
05193    // y = 0.5 (interior)
05194    shape(28,0) = 0.;
05195    shape(28,1) = (4.*y - 4.*y*y)*( 2. - 3.*x)*( 2. - 3.*z);
05196    shape(28,2) = 0.;
05197    shape(29,0) = 0.;
05198    shape(29,1) = (4.*y - 4.*y*y)*( 2. - 3.*x)*(-1. + 3.*z);
05199    shape(29,2) = 0.;
05200    shape(30,0) = 0.;
05201    shape(30,1) = (4.*y - 4.*y*y)*(-1. + 3.*x)*( 2. - 3.*z);
05202    shape(30,2) = 0.;
05203    shape(31,0) = 0.;
05204    shape(31,1) = (4.*y - 4.*y*y)*(-1. + 3.*x)*(-1. + 3.*z);
05205    shape(31,2) = 0.;
05206    // z = 0.5 (interior)
05207    shape(32,0) = 0.;
05208    shape(32,1) = 0.;
05209    shape(32,2) = (4.*z - 4.*z*z)*( 2. - 3.*x)*( 2. - 3.*y);
05210    shape(33,0) = 0.;
05211    shape(33,1) = 0.;
05212    shape(33,2) = (4.*z - 4.*z*z)*( 2. - 3.*x)*(-1. + 3.*y);
05213    shape(34,0) = 0.;
05214    shape(34,1) = 0.;
05215    shape(34,2) = (4.*z - 4.*z*z)*(-1. + 3.*x)*( 2. - 3.*y);
05216    shape(35,0) = 0.;
05217    shape(35,1) = 0.;
05218    shape(35,2) = (4.*z - 4.*z*z)*(-1. + 3.*x)*(-1. + 3.*y);
05219 }
05220 
05221 void RT1HexFiniteElement::CalcDivShape(const IntegrationPoint &ip,
05222                                        Vector &divshape) const
05223 {
05224    double x = ip.x, y = ip.y, z = ip.z;
05225    // z = 0
05226    divshape(2)  = -(-3. + 4.*z)*( 2. - 3.*x)*( 2. - 3.*y);
05227    divshape(3)  = -(-3. + 4.*z)*(-1. + 3.*x)*( 2. - 3.*y);
05228    divshape(0)  = -(-3. + 4.*z)*( 2. - 3.*x)*(-1. + 3.*y);
05229    divshape(1)  = -(-3. + 4.*z)*(-1. + 3.*x)*(-1. + 3.*y);
05230    // y = 0
05231    divshape(4)  = -(-3. + 4.*y)*( 2. - 3.*x)*( 2. - 3.*z);
05232    divshape(5)  = -(-3. + 4.*y)*(-1. + 3.*x)*( 2. - 3.*z);
05233    divshape(6)  = -(-3. + 4.*y)*( 2. - 3.*x)*(-1. + 3.*z);
05234    divshape(7)  = -(-3. + 4.*y)*(-1. + 3.*x)*(-1. + 3.*z);
05235    // x = 1
05236    divshape(8)  = (-1. + 4.*x)*( 2. - 3.*y)*( 2. - 3.*z);
05237    divshape(9)  = (-1. + 4.*x)*(-1. + 3.*y)*( 2. - 3.*z);
05238    divshape(10) = (-1. + 4.*x)*( 2. - 3.*y)*(-1. + 3.*z);
05239    divshape(11) = (-1. + 4.*x)*(-1. + 3.*y)*(-1. + 3.*z);
05240    // y = 1
05241    divshape(13) = (-1. + 4.*y)*( 2. - 3.*x)*( 2. - 3.*z);
05242    divshape(12) = (-1. + 4.*y)*(-1. + 3.*x)*( 2. - 3.*z);
05243    divshape(15) = (-1. + 4.*y)*( 2. - 3.*x)*(-1. + 3.*z);
05244    divshape(14) = (-1. + 4.*y)*(-1. + 3.*x)*(-1. + 3.*z);
05245    // x = 0
05246    divshape(17) = -(-3. + 4.*x)*( 2. - 3.*y)*( 2. - 3.*z);
05247    divshape(16) = -(-3. + 4.*x)*(-1. + 3.*y)*( 2. - 3.*z);
05248    divshape(19) = -(-3. + 4.*x)*( 2. - 3.*y)*(-1. + 3.*z);
05249    divshape(18) = -(-3. + 4.*x)*(-1. + 3.*y)*(-1. + 3.*z);
05250    // z = 1
05251    divshape(20) = (-1. + 4.*z)*( 2. - 3.*x)*( 2. - 3.*y);
05252    divshape(21) = (-1. + 4.*z)*(-1. + 3.*x)*( 2. - 3.*y);
05253    divshape(22) = (-1. + 4.*z)*( 2. - 3.*x)*(-1. + 3.*y);
05254    divshape(23) = (-1. + 4.*z)*(-1. + 3.*x)*(-1. + 3.*y);
05255    // x = 0.5 (interior)
05256    divshape(24) = ( 4. - 8.*x)*( 2. - 3.*y)*( 2. - 3.*z);
05257    divshape(25) = ( 4. - 8.*x)*( 2. - 3.*y)*(-1. + 3.*z);
05258    divshape(26) = ( 4. - 8.*x)*(-1. + 3.*y)*( 2. - 3.*z);
05259    divshape(27) = ( 4. - 8.*x)*(-1. + 3.*y)*(-1. + 3.*z);
05260    // y = 0.5 (interior)
05261    divshape(28) = ( 4. - 8.*y)*( 2. - 3.*x)*( 2. - 3.*z);
05262    divshape(29) = ( 4. - 8.*y)*( 2. - 3.*x)*(-1. + 3.*z);
05263    divshape(30) = ( 4. - 8.*y)*(-1. + 3.*x)*( 2. - 3.*z);
05264    divshape(31) = ( 4. - 8.*y)*(-1. + 3.*x)*(-1. + 3.*z);
05265    // z = 0.5 (interior)
05266    divshape(32) = ( 4. - 8.*z)*( 2. - 3.*x)*( 2. - 3.*y);
05267    divshape(33) = ( 4. - 8.*z)*( 2. - 3.*x)*(-1. + 3.*y);
05268    divshape(34) = ( 4. - 8.*z)*(-1. + 3.*x)*( 2. - 3.*y);
05269    divshape(35) = ( 4. - 8.*z)*(-1. + 3.*x)*(-1. + 3.*y);
05270 }
05271 
05272 const double RT1HexFiniteElement::nk[36][3] =
05273 {
05274    {0, 0,-1}, {0, 0,-1}, {0, 0,-1}, {0, 0,-1},
05275    {0,-1, 0}, {0,-1, 0}, {0,-1, 0}, {0,-1, 0},
05276    {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0},
05277    {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0},
05278    {-1,0, 0}, {-1,0, 0}, {-1,0, 0}, {-1,0, 0},
05279    {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1},
05280    {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0},
05281    {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0},
05282    {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}
05283 };
05284 
05285 void RT1HexFiniteElement::GetLocalInterpolation (
05286    ElementTransformation &Trans, DenseMatrix &I) const
05287 {
05288    int k, j;
05289 #ifdef MFEM_USE_OPENMP
05290    DenseMatrix vshape(Dof, Dim);
05291    DenseMatrix Jinv(Dim);
05292 #endif
05293 
05294 #ifdef MFEM_DEBUG
05295    for (k = 0; k < 36; k++)
05296    {
05297       CalcVShape (Nodes.IntPoint(k), vshape);
05298       for (j = 0; j < 36; j++)
05299       {
05300          double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] +
05301                       vshape(j,2)*nk[k][2] );
05302          if (j == k) d -= 1.0;
05303          if (fabs(d) > 1.0e-12)
05304          {
05305             cerr << "RT0HexFiniteElement::GetLocalInterpolation (...)\n"
05306                " k = " << k << ", j = " << j << ", d = " << d << endl;
05307             mfem_error();
05308          }
05309       }
05310    }
05311 #endif
05312 
05313    IntegrationPoint ip;
05314    ip.x = ip.y = ip.z = 0.0;
05315    Trans.SetIntPoint (&ip);
05316    // Trans must be linear
05317    // set Jinv = |J| J^{-t} = adj(J)^t
05318    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
05319    double vk[3];
05320    Vector xk (vk, 3);
05321 
05322    for (k = 0; k < 36; k++)
05323    {
05324       Trans.Transform (Nodes.IntPoint (k), xk);
05325       ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
05326       CalcVShape (ip, vshape);
05327       //  vk = |J| J^{-t} nk
05328       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2];
05329       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2];
05330       vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2];
05331       for (j = 0; j < 36; j++)
05332          if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
05333                              vshape(j,2)*vk[2])) < 1.0e-12)
05334             I(k,j) = 0.0;
05335    }
05336 }
05337 
05338 void RT1HexFiniteElement::Project (
05339    VectorCoefficient &vc, ElementTransformation &Trans,
05340    Vector &dofs) const
05341 {
05342    double vk[3];
05343    Vector xk (vk, 3);
05344 #ifdef MFEM_USE_OPENMP
05345    DenseMatrix Jinv(Dim);
05346 #endif
05347 
05348    for (int k = 0; k < 36; k++)
05349    {
05350       Trans.SetIntPoint (&Nodes.IntPoint (k));
05351       // set Jinv = |J| J^{-t} = adj(J)^t
05352       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
05353 
05354       vc.Eval (xk, Trans, Nodes.IntPoint (k));
05355       //  xk^t |J| J^{-t} nk
05356       dofs(k) =
05357          vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) +
05358          vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) +
05359          vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] );
05360    }
05361 }
05362 
05363 RT0TetFiniteElement::RT0TetFiniteElement()
05364    : VectorFiniteElement (3, Geometry::TETRAHEDRON, 4, 1)
05365 {
05366    // not real nodes ...
05367    Nodes.IntPoint(0).x = 0.33333333333333333333;
05368    Nodes.IntPoint(0).y = 0.33333333333333333333;
05369    Nodes.IntPoint(0).z = 0.33333333333333333333;
05370 
05371    Nodes.IntPoint(1).x = 0.0;
05372    Nodes.IntPoint(1).y = 0.33333333333333333333;
05373    Nodes.IntPoint(1).z = 0.33333333333333333333;
05374 
05375    Nodes.IntPoint(2).x = 0.33333333333333333333;
05376    Nodes.IntPoint(2).y = 0.0;
05377    Nodes.IntPoint(2).z = 0.33333333333333333333;
05378 
05379    Nodes.IntPoint(3).x = 0.33333333333333333333;
05380    Nodes.IntPoint(3).y = 0.33333333333333333333;
05381    Nodes.IntPoint(3).z = 0.0;
05382 }
05383 
05384 void RT0TetFiniteElement::CalcVShape(const IntegrationPoint &ip,
05385                                      DenseMatrix &shape) const
05386 {
05387    double x2 = 2.0*ip.x, y2 = 2.0*ip.y, z2 = 2.0*ip.z;
05388 
05389    shape(0,0) = x2;
05390    shape(0,1) = y2;
05391    shape(0,2) = z2;
05392 
05393    shape(1,0) = x2 - 2.0;
05394    shape(1,1) = y2;
05395    shape(1,2) = z2;
05396 
05397    shape(2,0) = x2;
05398    shape(2,1) = y2 - 2.0;
05399    shape(2,2) = z2;
05400 
05401    shape(3,0) = x2;
05402    shape(3,1) = y2;
05403    shape(3,2) = z2 - 2.0;
05404 }
05405 
05406 void RT0TetFiniteElement::CalcDivShape(const IntegrationPoint &ip,
05407                                        Vector &divshape) const
05408 {
05409    divshape(0) = 6.0;
05410    divshape(1) = 6.0;
05411    divshape(2) = 6.0;
05412    divshape(3) = 6.0;
05413 }
05414 
05415 const double RT0TetFiniteElement::nk[4][3] =
05416 {{.5,.5,.5}, {-.5,0,0}, {0,-.5,0}, {0,0,-.5}};
05417 
05418 void RT0TetFiniteElement::GetLocalInterpolation (
05419    ElementTransformation &Trans, DenseMatrix &I) const
05420 {
05421    int k, j;
05422 #ifdef MFEM_USE_OPENMP
05423    DenseMatrix vshape(Dof, Dim);
05424    DenseMatrix Jinv(Dim);
05425 #endif
05426 
05427 #ifdef MFEM_DEBUG
05428    for (k = 0; k < 4; k++)
05429    {
05430       CalcVShape (Nodes.IntPoint(k), vshape);
05431       for (j = 0; j < 4; j++)
05432       {
05433          double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] +
05434                       vshape(j,2)*nk[k][2] );
05435          if (j == k) d -= 1.0;
05436          if (fabs(d) > 1.0e-12)
05437          {
05438             cerr << "RT0TetFiniteElement::GetLocalInterpolation (...)\n"
05439                " k = " << k << ", j = " << j << ", d = " << d << endl;
05440             mfem_error();
05441          }
05442       }
05443    }
05444 #endif
05445 
05446    IntegrationPoint ip;
05447    ip.x = ip.y = ip.z = 0.0;
05448    Trans.SetIntPoint (&ip);
05449    // Trans must be linear
05450    // set Jinv = |J| J^{-t} = adj(J)^t
05451    CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
05452    double vk[3];
05453    Vector xk (vk, 3);
05454 
05455    for (k = 0; k < 4; k++)
05456    {
05457       Trans.Transform (Nodes.IntPoint (k), xk);
05458       ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
05459       CalcVShape (ip, vshape);
05460       //  vk = |J| J^{-t} nk
05461       vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2];
05462       vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2];
05463       vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2];
05464       for (j = 0; j < 4; j++)
05465          if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
05466                              vshape(j,2)*vk[2])) < 1.0e-12)
05467             I(k,j) = 0.0;
05468    }
05469 }
05470 
05471 void RT0TetFiniteElement::Project (
05472    VectorCoefficient &vc, ElementTransformation &Trans,
05473    Vector &dofs) const
05474 {
05475    double vk[3];
05476    Vector xk (vk, 3);
05477 #ifdef MFEM_USE_OPENMP
05478    DenseMatrix Jinv(Dim);
05479 #endif
05480 
05481    for (int k = 0; k < 4; k++)
05482    {
05483       Trans.SetIntPoint (&Nodes.IntPoint (k));
05484       // set Jinv = |J| J^{-t} = adj(J)^t
05485       CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
05486 
05487       vc.Eval (xk, Trans, Nodes.IntPoint (k));
05488       //  xk^t |J| J^{-t} nk
05489       dofs(k) =
05490          vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) +
05491          vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) +
05492          vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] );
05493    }
05494 }
05495 
05496 RotTriLinearHexFiniteElement::RotTriLinearHexFiniteElement()
05497    : NodalFiniteElement(3, Geometry::CUBE, 6, 2, FunctionSpace::Qk)
05498 {
05499    Nodes.IntPoint(0).x = 0.5;
05500    Nodes.IntPoint(0).y = 0.5;
05501    Nodes.IntPoint(0).z = 0.0;
05502 
05503    Nodes.IntPoint(1).x = 0.5;
05504    Nodes.IntPoint(1).y = 0.0;
05505    Nodes.IntPoint(1).z = 0.5;
05506 
05507    Nodes.IntPoint(2).x = 1.0;
05508    Nodes.IntPoint(2).y = 0.5;
05509    Nodes.IntPoint(2).z = 0.5;
05510 
05511    Nodes.IntPoint(3).x = 0.5;
05512    Nodes.IntPoint(3).y = 1.0;
05513    Nodes.IntPoint(3).z = 0.5;
05514 
05515    Nodes.IntPoint(4).x = 0.0;
05516    Nodes.IntPoint(4).y = 0.5;
05517    Nodes.IntPoint(4).z = 0.5;
05518 
05519    Nodes.IntPoint(5).x = 0.5;
05520    Nodes.IntPoint(5).y = 0.5;
05521    Nodes.IntPoint(5).z = 1.0;
05522 }
05523 
05524 void RotTriLinearHexFiniteElement::CalcShape(const IntegrationPoint &ip,
05525                                              Vector &shape) const
05526 {
05527    double x = 2. * ip.x - 1.;
05528    double y = 2. * ip.y - 1.;
05529    double z = 2. * ip.z - 1.;
05530    double f5 = x * x - y * y;
05531    double f6 = y * y - z * z;
05532 
05533    shape(0) = (1./6.) * (1. - 3. * z -      f5 - 2. * f6);
05534    shape(1) = (1./6.) * (1. - 3. * y -      f5 +      f6);
05535    shape(2) = (1./6.) * (1. + 3. * x + 2. * f5 +      f6);
05536    shape(3) = (1./6.) * (1. + 3. * y -      f5 +      f6);
05537    shape(4) = (1./6.) * (1. - 3. * x + 2. * f5 +      f6);
05538    shape(5) = (1./6.) * (1. + 3. * z -      f5 - 2. * f6);
05539 }
05540 
05541 void RotTriLinearHexFiniteElement::CalcDShape(const IntegrationPoint &ip,
05542                                               DenseMatrix &dshape) const
05543 {
05544    const double a = 2./3.;
05545 
05546    double xt = a * (1. - 2. * ip.x);
05547    double yt = a * (1. - 2. * ip.y);
05548    double zt = a * (1. - 2. * ip.z);
05549 
05550    dshape(0,0) = xt;
05551    dshape(0,1) = yt;
05552    dshape(0,2) = -1. - 2. * zt;
05553 
05554    dshape(1,0) = xt;
05555    dshape(1,1) = -1. - 2. * yt;
05556    dshape(1,2) = zt;
05557 
05558    dshape(2,0) = 1. - 2. * xt;
05559    dshape(2,1) = yt;
05560    dshape(2,2) = zt;
05561 
05562    dshape(3,0) = xt;
05563    dshape(3,1) = 1. - 2. * yt;
05564    dshape(3,2) = zt;
05565 
05566    dshape(4,0) = -1. - 2. * xt;
05567    dshape(4,1) = yt;
05568    dshape(4,2) = zt;
05569 
05570    dshape(5,0) = xt;
05571    dshape(5,1) = yt;
05572    dshape(5,2) = 1. - 2. * zt;
05573 }
05574 
05575 
05576 Poly_1D::Basis::Basis(const int p, const double *nodes)
05577    : A(p + 1)
05578 {
05579 #ifdef MFEM_USE_OPENMP
05580    Vector a(p+1);
05581 #else
05582    a.SetSize(p+1);
05583    b.SetSize(p+1);
05584 #endif
05585    for (int i = 0; i <= p; i++)
05586    {
05587       CalcBasis(p, nodes[i], a);
05588       for (int j = 0; j <= p; j++)
05589          A(j, i) = a(j);
05590    }
05591 
05592    A.Invert();
05593    // cout << "Poly_1D::Basis(" << p << ",...) : "; A.TestInversion();
05594 }
05595 
05596 void Poly_1D::Basis::Eval(const double x, Vector &u) const
05597 {
05598 #ifdef MFEM_USE_OPENMP
05599    Vector a(A.Size());
05600 #endif
05601    const int p = A.Size() - 1;
05602    CalcBasis(p, x, a);
05603    A.Mult(a, u);
05604 }
05605 
05606 void Poly_1D::Basis::Eval(const double x, Vector &u, Vector &d) const
05607 {
05608 #ifdef MFEM_USE_OPENMP
05609    Vector a(A.Size()), b(A.Size());
05610 #endif
05611    const int p = A.Size() - 1;
05612    CalcBasis(p, x, a, b);
05613    A.Mult(a, u);
05614    A.Mult(b, d);
05615 }
05616 
05617 void Poly_1D::UniformPoints(const int p, double *x)
05618 {
05619    if (p == 0)
05620    {
05621       x[0] = 0.5;
05622    }
05623    else
05624    {
05625       for (int i = 0; i <= p; i++)
05626          x[i] = double(i)/p;
05627    }
05628 }
05629 
05630 void Poly_1D::GaussPoints(const int p, double *x)
05631 {
05632    int m = (p+1)/2, odd_p = p%2;
05633 
05634    if (!odd_p)
05635       x[m] = 0.5;
05636 
05637    for (int i = 0; i < m; i++)
05638    {
05639       double z, y, p0, d0;
05640       z = cos(M_PI*(i + 0.75)/(p + 1.5));
05641 
05642       for (int k = 0; true; )
05643       {
05644          // compute p0, d0 -- P_{p+1}(z), P'_{p+1}(z) using
05645          // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z)
05646          // P'_{n+1}(z) = (2*n+1)*P_n(z)+P'_{n-1}(z)
05647          {
05648             double p1, p2;
05649             p2 = 1.;
05650             p1 = z;
05651             d0 = 1 - odd_p;
05652             for (int n = 1; true; n++)
05653             {
05654                p0 = ((2*n+1)*z*p1 - n*p2)/(n + 1);
05655                if (n%2 == odd_p)
05656                   d0 += (2*n+1)*p1;
05657                if (n == p) break;
05658                p2 = p1;
05659                p1 = p0;
05660             }
05661             // d0 = (p + 1)*(z*p0 - p1)/(z*z - 1); // alternative formula
05662          }
05663 
05664          if (fabs(p0/d0) < 2e-16) break;
05665 
05666          if (++k == 5)
05667          {
05668             std::cout << "Poly_1D::GaussPoints : No convergence!"
05669                " p = " << p << ", i = " << i << ", p0/d0 = " << p0/d0
05670                       << std::endl;
05671             break;
05672          }
05673 
05674          z = z - p0/d0;
05675       }
05676 
05677       // z = z - p0/d0; y = (1 - z)/2; // bad roundoff !!!
05678       y = ((1 - z) + p0/d0)/2;
05679 
05680       x[i]   = y;
05681       x[p-i] = 1 - y;
05682       // the weight is: 1./(4*y*(1 - y)*d0*d0)
05683    }
05684 }
05685 
05686 void Poly_1D::GaussLobattoPoints(const int p, double *x)
05687 {
05688    if (p == 0)
05689    {
05690       x[0] = 0.5;
05691    }
05692    else
05693    {
05694       x[0] = 0.;
05695       x[p] = 1.;
05696       if (p == 1) return;
05697 
05698       // x[1],...,x[p-1] are the (shifted) roots of P'_p
05699       int m = (p - 1)/2, odd_p = p%2;
05700 
05701       if (!odd_p)
05702          x[m+1] = 0.5;
05703       for (int i = 0; i < m; )
05704       {
05705          double y, z, d0, s0;
05706          z = cos(M_PI*(i + 1)/p);
05707 
05708          for (int k = 0; true; )
05709          {
05710             // compute d0, s0 -- P'_p(z), P"_p(z)
05711             // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z)
05712             // P'_{n+1}(z) = (2*n+1)* P_n(z)+P'_{n-1}(z)
05713             // P"_{n+1}(z) = (2*n+1)*P'_n(z)+P"_{n-1}(z)
05714             {
05715                double p0, p1, p2, d1;
05716                p2 = 1.;
05717                p1 = z;
05718                d0 = odd_p;
05719                d1 = 1 - odd_p;
05720                s0 = 0;
05721                for (int n = 1; true; n++)
05722                {
05723                   p0 = ((2*n+1)*z*p1 - n*p2)/(n + 1);
05724                   if (n%2 != odd_p)
05725                   {
05726                      d0 += (2*n+1)*p1;
05727                      s0 += (2*n+1)*d1;
05728                   }
05729                   else
05730                   {
05731                      d1 += (2*n+1)*p1;
05732                   }
05733                   if (n == p - 1) break;
05734                   p2 = p1;
05735                   p1 = p0;
05736                }
05737             }
05738 
05739             if (fabs(d0/s0) < 2e-16) break;
05740 
05741             if (++k == 6)
05742             {
05743                std::cout << "Poly_1D::GaussLobattoPoints : No convergence!"
05744                   " p = " << p << ", i = " << i << ", d0/s0 = " << d0/s0
05745                          << std::endl;
05746                break;
05747             }
05748 
05749             z = z - d0/s0;
05750          }
05751 
05752          y = ((1 - z) + d0/s0)/2;
05753 
05754          x[++i] = y;
05755          x[p-i] = 1 - y;
05756       }
05757    }
05758 }
05759 
05760 void Poly_1D::ChebyshevPoints(const int p, double *x)
05761 {
05762    for (int i = 0; i <= p; i++)
05763    {
05764       // x[i] = 0.5*(1. + cos(M_PI*(p - i + 0.5)/(p + 1)));
05765       double s = sin(M_PI_2*(i + 0.5)/(p + 1));
05766       x[i] = s*s;
05767    }
05768 }
05769 
05770 void Poly_1D::CalcMono(const int p, const double x, double *u)
05771 {
05772    double xn;
05773    u[0] = xn = 1.;
05774    for (int n = 1; n <= p; n++)
05775       u[n] = (xn *= x);
05776 }
05777 
05778 void Poly_1D::CalcMono(const int p, const double x, double *u, double *d)
05779 {
05780    double xn;
05781    u[0] = xn = 1.;
05782    d[0] = 0.;
05783    for (int n = 1; n <= p; n++)
05784    {
05785       d[n] = n * xn;
05786       u[n] = (xn *= x);
05787    }
05788 }
05789 
05790 void Poly_1D::CalcBernstein(const int p, const double x, double *u)
05791 {
05792    // not the best way to evaluate; just for testing
05793    u[0] = 1.;
05794    for (int n = 1; n <= p; n++)
05795    {
05796       u[n] = x*u[n-1];
05797       for (int k = n - 1; k > 0; k--)
05798          u[k] = x*u[k-1] + (1. - x)*u[k];
05799       u[0] = (1. - x)*u[0];
05800    }
05801 }
05802 
05803 void Poly_1D::CalcBernstein(const int p, const double x, double *u, double *d)
05804 {
05805    // not the best way to evaluate; just for testing
05806    u[0] = 1.;
05807    d[0] = 0.;
05808    for (int n = 1; n <= p; n++)
05809    {
05810       d[n] = u[n-1] + x*d[n-1];
05811       u[n] = x*u[n-1];
05812       for (int k = n - 1; k > 0; k--)
05813       {
05814          d[k] = u[k-1] + x*d[k-1] - u[k] + (1. - x)*d[k];
05815          u[k] = x*u[k-1] + (1. - x)*u[k];
05816       }
05817       d[0] = -u[0] + (1. - x)*d[0];
05818       u[0] = (1. - x)*u[0];
05819    }
05820 }
05821 
05822 void Poly_1D::CalcLegendre(const int p, const double x, double *u)
05823 {
05824    // use the recursive definition for [-1,1]:
05825    // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z)
05826    double z;
05827    u[0] = 1.;
05828    if (p == 0) return;
05829    u[1] = z = 2.*x - 1.;
05830    for (int n = 1; n < p; n++)
05831    {
05832       u[n+1] = ((2*n + 1)*z*u[n] - n*u[n-1])/(n + 1);
05833    }
05834 }
05835 
05836 void Poly_1D::CalcLegendre(const int p, const double x, double *u, double *d)
05837 {
05838    // use the recursive definition for [-1,1]:
05839    // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z)
05840    // for the derivative use, z in [-1,1]:
05841    // P'_{n+1}(z) = (2*n+1)*P_n(z)+P'_{n-1}(z)
05842    double z;
05843    u[0] = 1.;
05844    d[0] = 0.;
05845    if (p == 0) return;
05846    u[1] = z = 2.*x - 1.;
05847    d[1] = 2.;
05848    for (int n = 1; n < p; n++)
05849    {
05850       u[n+1] = ((2*n + 1)*z*u[n] - n*u[n-1])/(n + 1);
05851       d[n+1] = (4*n + 2)*u[n] + d[n-1];
05852    }
05853 }
05854 
05855 void Poly_1D::CalcChebyshev(const int p, const double x, double *u)
05856 {
05857    // recursive definition, z in [-1,1]
05858    // T_0(z) = 1,  T_1(z) = z
05859    // T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z)
05860    double z;
05861    u[0] = 1.;
05862    if (p == 0) return;
05863    u[1] = z = 2.*x - 1.;
05864    for (int n = 1; n < p; n++)
05865    {
05866       u[n+1] = 2*z*u[n] - u[n-1];
05867    }
05868 }
05869 
05870 void Poly_1D::CalcChebyshev(const int p, const double x, double *u, double *d)
05871 {
05872    // recursive definition, z in [-1,1]
05873    // T_0(z) = 1,  T_1(z) = z
05874    // T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z)
05875    // T'_n(z) = n*U_{n-1}(z)
05876    // U_0(z) = 1  U_1(z) = 2*z
05877    // U_{n+1}(z) = 2*z*U_n(z) - U_{n-1}(z)
05878    // U_n(z) = z*U_{n-1}(z) + T_n(z) = z*T'_n(z)/n + T_n(z)
05879    // T'_{n+1}(z) = (n + 1)*(z*T'_n(z)/n + T_n(z))
05880    double z;
05881    u[0] = 1.;
05882    d[0] = 0.;
05883    if (p == 0) return;
05884    u[1] = z = 2.*x - 1.;
05885    d[1] = 2.;
05886    for (int n = 1; n < p; n++)
05887    {
05888       u[n+1] = 2*z*u[n] - u[n-1];
05889       d[n+1] = (n + 1)*(z*d[n]/n + 2*u[n]);
05890    }
05891 }
05892 
05893 const double *Poly_1D::OpenPoints(const int p)
05894 {
05895    double *op;
05896 
05897    if (open_pts.Size() <= p)
05898    {
05899       int i = open_pts.Size();
05900       open_pts.SetSize(p + 1);
05901       for ( ; i < p; i++)
05902          open_pts[i] = NULL;
05903       goto alloc_open;
05904    }
05905    if ((op = open_pts[p]) != NULL)
05906       return op;
05907 alloc_open:
05908    open_pts[p] = op = new double[p + 1];
05909    GaussPoints(p, op);
05910    // ChebyshevPoints(p, op);
05911    return op;
05912 }
05913 
05914 const double *Poly_1D::ClosedPoints(const int p)
05915 {
05916    double *cp;
05917 
05918    if (closed_pts.Size() <= p)
05919    {
05920       int i = closed_pts.Size();
05921       closed_pts.SetSize(p + 1);
05922       for ( ; i < p; i++)
05923          closed_pts[i] = NULL;
05924       goto alloc_closed;
05925    }
05926    if ((cp = closed_pts[p]) != NULL)
05927       return cp;
05928 alloc_closed:
05929    closed_pts[p] = cp = new double[p + 1];
05930    GaussLobattoPoints(p, cp);
05931    // UniformPoints(p, cp);
05932    return cp;
05933 }
05934 
05935 Poly_1D::Basis &Poly_1D::OpenBasis(const int p)
05936 {
05937    Basis *ob;
05938 
05939    if (open_basis.Size() <= p)
05940    {
05941       int i = open_basis.Size();
05942       open_basis.SetSize(p + 1);
05943       for ( ; i < p; i++)
05944          open_basis[i] = NULL;
05945       goto alloc_obasis;
05946    }
05947    if ((ob = open_basis[p]) != NULL)
05948       return *ob;
05949 alloc_obasis:
05950    open_basis[p] = ob = new Basis(p, OpenPoints(p));
05951    return *ob;
05952 }
05953 
05954 Poly_1D::Basis &Poly_1D::ClosedBasis(const int p)
05955 {
05956    Basis *cb;
05957 
05958    if (closed_basis.Size() <= p)
05959    {
05960       int i = closed_basis.Size();
05961       closed_basis.SetSize(p + 1);
05962       for ( ; i < p; i++)
05963          closed_basis[i] = NULL;
05964       goto alloc_cbasis;
05965    }
05966    if ((cb = closed_basis[p]) != NULL)
05967       return *cb;
05968 alloc_cbasis:
05969    closed_basis[p] = cb = new Basis(p, ClosedPoints(p));
05970    return *cb;
05971 }
05972 
05973 Poly_1D::~Poly_1D()
05974 {
05975    for (int i = 0; i < open_pts.Size(); i++)
05976       delete [] open_pts[i];
05977    for (int i = 0; i < closed_pts.Size(); i++)
05978       delete [] closed_pts[i];
05979    for (int i = 0; i < open_basis.Size(); i++)
05980       delete open_basis[i];
05981    for (int i = 0; i < closed_basis.Size(); i++)
05982       delete closed_basis[i];
05983 }
05984 
05985 Poly_1D poly1d;
05986 
05987 
05988 H1_SegmentElement::H1_SegmentElement(const int p)
05989    : NodalFiniteElement(1, Geometry::SEGMENT, p + 1, p, FunctionSpace::Pk),
05990      basis1d(poly1d.ClosedBasis(p))
05991 {
05992    const double *cp = poly1d.ClosedPoints(p);
05993 
05994 #ifndef MFEM_USE_OPENMP
05995    shape_x.SetSize(p+1);
05996    dshape_x.SetSize(p+1);
05997 #endif
05998 
05999    Nodes.IntPoint(0).x = cp[0];
06000    Nodes.IntPoint(1).x = cp[p];
06001    for (int i = 1; i < p; i++)
06002       Nodes.IntPoint(i+1).x = cp[i];
06003 }
06004 
06005 void H1_SegmentElement::CalcShape(const IntegrationPoint &ip,
06006                                   Vector &shape) const
06007 {
06008    const int p = Order;
06009 
06010 #ifdef MFEM_USE_OPENMP
06011    Vector shape_x(p+1);
06012 #endif
06013 
06014    basis1d.Eval(ip.x, shape_x);
06015 
06016    shape(0) = shape_x(0);
06017    shape(1) = shape_x(p);
06018    for (int i = 1; i < p; i++)
06019       shape(i+1) = shape_x(i);
06020 }
06021 
06022 void H1_SegmentElement::CalcDShape(const IntegrationPoint &ip,
06023                                    DenseMatrix &dshape) const
06024 {
06025    const int p = Order;
06026 
06027 #ifdef MFEM_USE_OPENMP
06028    Vector shape_x(p+1), dshape_x(p+1);
06029 #endif
06030 
06031    basis1d.Eval(ip.x, shape_x, dshape_x);
06032 
06033    dshape(0,0) = dshape_x(0);
06034    dshape(1,0) = dshape_x(p);
06035    for (int i = 1; i < p; i++)
06036       dshape(i+1,0) = dshape_x(i);
06037 }
06038 
06039 
06040 H1_QuadrilateralElement::H1_QuadrilateralElement(const int p)
06041    : NodalFiniteElement(2, Geometry::SQUARE, (p + 1)*(p + 1), p,
06042                         FunctionSpace::Qk),
06043      basis1d(poly1d.ClosedBasis(p)), dof_map((p + 1)*(p + 1))
06044 {
06045    const double *cp = poly1d.ClosedPoints(p);
06046 
06047    const int p1 = p + 1;
06048 
06049 #ifndef MFEM_USE_OPENMP
06050    shape_x.SetSize(p1);
06051    shape_y.SetSize(p1);
06052    dshape_x.SetSize(p1);
06053    dshape_y.SetSize(p1);
06054 #endif
06055 
06056    // vertices
06057    dof_map[0 + 0*p1] = 0;
06058    dof_map[p + 0*p1] = 1;
06059    dof_map[p + p*p1] = 2;
06060    dof_map[0 + p*p1] = 3;
06061 
06062    // edges
06063    int o = 4;
06064    for (int i = 1; i < p; i++)
06065       dof_map[i + 0*p1] = o++;
06066    for (int i = 1; i < p; i++)
06067       dof_map[p + i*p1] = o++;
06068    for (int i = 1; i < p; i++)
06069       dof_map[(p-i) + p*p1] = o++;
06070    for (int i = 1; i < p; i++)
06071       dof_map[0 + (p-i)*p1] = o++;
06072 
06073    // interior
06074    for (int j = 1; j < p; j++)
06075       for (int i = 1; i < p; i++)
06076          dof_map[i + j*p1] = o++;
06077 
06078    o = 0;
06079    for (int j = 0; j <= p; j++)
06080       for (int i = 0; i <= p; i++)
06081          Nodes.IntPoint(dof_map[o++]).Set2(cp[i], cp[j]);
06082 }
06083 
06084 void H1_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
06085                                         Vector &shape) const
06086 {
06087    const int p = Order;
06088 
06089 #ifdef MFEM_USE_OPENMP
06090    Vector shape_x(p+1), shape_y(p+1);
06091 #endif
06092 
06093    basis1d.Eval(ip.x, shape_x);
06094    basis1d.Eval(ip.y, shape_y);
06095 
06096    for (int o = 0, j = 0; j <= p; j++)
06097       for (int i = 0; i <= p; i++)
06098          shape(dof_map[o++]) = shape_x(i)*shape_y(j);
06099 }
06100 
06101 void H1_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
06102                                          DenseMatrix &dshape) const
06103 {
06104    const int p = Order;
06105 
06106 #ifdef MFEM_USE_OPENMP
06107    Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
06108 #endif
06109 
06110    basis1d.Eval(ip.x, shape_x, dshape_x);
06111    basis1d.Eval(ip.y, shape_y, dshape_y);
06112 
06113    for (int o = 0, j = 0; j <= p; j++)
06114       for (int i = 0; i <= p; i++)
06115       {
06116          dshape(dof_map[o],0) = dshape_x(i)* shape_y(j);
06117          dshape(dof_map[o],1) =  shape_x(i)*dshape_y(j);  o++;
06118       }
06119 }
06120 
06121 H1_HexahedronElement::H1_HexahedronElement(const int p)
06122    : NodalFiniteElement(3, Geometry::CUBE, (p + 1)*(p + 1)*(p + 1), p,
06123                         FunctionSpace::Qk),
06124      basis1d(poly1d.ClosedBasis(p)), dof_map((p + 1)*(p + 1)*(p + 1))
06125 {
06126    const double *cp = poly1d.ClosedPoints(p);
06127 
06128    const int p1 = p + 1;
06129 
06130 #ifndef MFEM_USE_OPENMP
06131    shape_x.SetSize(p1);
06132    shape_y.SetSize(p1);
06133    shape_z.SetSize(p1);
06134    dshape_x.SetSize(p1);
06135    dshape_y.SetSize(p1);
06136    dshape_z.SetSize(p1);
06137 #endif
06138 
06139    // vertices
06140    dof_map[0 + (0 + 0*p1)*p1] = 0;
06141    dof_map[p + (0 + 0*p1)*p1] = 1;
06142    dof_map[p + (p + 0*p1)*p1] = 2;
06143    dof_map[0 + (p + 0*p1)*p1] = 3;
06144    dof_map[0 + (0 + p*p1)*p1] = 4;
06145    dof_map[p + (0 + p*p1)*p1] = 5;
06146    dof_map[p + (p + p*p1)*p1] = 6;
06147    dof_map[0 + (p + p*p1)*p1] = 7;
06148 
06149    // edges (see Hexahedron::edges in mesh/hexahedron.cpp)
06150    int o = 8;
06151    for (int i = 1; i < p; i++)
06152       dof_map[i + (0 + 0*p1)*p1] = o++;  // (0,1)
06153    for (int i = 1; i < p; i++)
06154       dof_map[p + (i + 0*p1)*p1] = o++;  // (1,2)
06155    for (int i = 1; i < p; i++)
06156       dof_map[i + (p + 0*p1)*p1] = o++;  // (3,2)
06157    for (int i = 1; i < p; i++)
06158       dof_map[0 + (i + 0*p1)*p1] = o++;  // (0,3)
06159    for (int i = 1; i < p; i++)
06160       dof_map[i + (0 + p*p1)*p1] = o++;  // (4,5)
06161    for (int i = 1; i < p; i++)
06162       dof_map[p + (i + p*p1)*p1] = o++;  // (5,6)
06163    for (int i = 1; i < p; i++)
06164       dof_map[i + (p + p*p1)*p1] = o++;  // (7,6)
06165    for (int i = 1; i < p; i++)
06166       dof_map[0 + (i + p*p1)*p1] = o++;  // (4,7)
06167    for (int i = 1; i < p; i++)
06168       dof_map[0 + (0 + i*p1)*p1] = o++;  // (0,4)
06169    for (int i = 1; i < p; i++)
06170       dof_map[p + (0 + i*p1)*p1] = o++;  // (1,5)
06171    for (int i = 1; i < p; i++)
06172       dof_map[p + (p + i*p1)*p1] = o++;  // (2,6)
06173    for (int i = 1; i < p; i++)
06174       dof_map[0 + (p + i*p1)*p1] = o++;  // (3,7)
06175 
06176    // faces (see Mesh::GenerateFaces in mesh/mesh.cpp)
06177    for (int j = 1; j < p; j++)
06178       for (int i = 1; i < p; i++)
06179          dof_map[i + ((p-j) + 0*p1)*p1] = o++;  // (3,2,1,0)
06180    for (int j = 1; j < p; j++)
06181       for (int i = 1; i < p; i++)
06182          dof_map[i + (0 + j*p1)*p1] = o++;  // (0,1,5,4)
06183    for (int j = 1; j < p; j++)
06184       for (int i = 1; i < p; i++)
06185          dof_map[p + (i + j*p1)*p1] = o++;  // (1,2,6,5)
06186    for (int j = 1; j < p; j++)
06187       for (int i = 1; i < p; i++)
06188          dof_map[(p-i) + (p + j*p1)*p1] = o++;  // (2,3,7,6)
06189    for (int j = 1; j < p; j++)
06190       for (int i = 1; i < p; i++)
06191          dof_map[0 + ((p-i) + j*p1)*p1] = o++;  // (3,0,4,7)
06192    for (int j = 1; j < p; j++)
06193       for (int i = 1; i < p; i++)
06194          dof_map[i + (j + p*p1)*p1] = o++;  // (4,5,6,7)
06195 
06196    // interior
06197    for (int k = 1; k < p; k++)
06198       for (int j = 1; j < p; j++)
06199          for (int i = 1; i < p; i++)
06200             dof_map[i + (j + k*p1)*p1] = o++;
06201 
06202    o = 0;
06203    for (int k = 0; k <= p; k++)
06204       for (int j = 0; j <= p; j++)
06205          for (int i = 0; i <= p; i++)
06206             Nodes.IntPoint(dof_map[o++]).Set3(cp[i], cp[j], cp[k]);
06207 }
06208 
06209 void H1_HexahedronElement::CalcShape(const IntegrationPoint &ip,
06210                                      Vector &shape) const
06211 {
06212    const int p = Order;
06213 
06214 #ifdef MFEM_USE_OPENMP
06215    Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
06216 #endif
06217 
06218    basis1d.Eval(ip.x, shape_x);
06219    basis1d.Eval(ip.y, shape_y);
06220    basis1d.Eval(ip.z, shape_z);
06221 
06222    for (int o = 0, k = 0; k <= p; k++)
06223       for (int j = 0; j <= p; j++)
06224          for (int i = 0; i <= p; i++)
06225             shape(dof_map[o++]) = shape_x(i)*shape_y(j)*shape_z(k);
06226 }
06227 
06228 void H1_HexahedronElement::CalcDShape(const IntegrationPoint &ip,
06229                                       DenseMatrix &dshape) const
06230 {
06231    const int p = Order;
06232 
06233 #ifdef MFEM_USE_OPENMP
06234    Vector shape_x(p+1),  shape_y(p+1),  shape_z(p+1);
06235    Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
06236 #endif
06237 
06238    basis1d.Eval(ip.x, shape_x, dshape_x);
06239    basis1d.Eval(ip.y, shape_y, dshape_y);
06240    basis1d.Eval(ip.z, shape_z, dshape_z);
06241 
06242    for (int o = 0, k = 0; k <= p; k++)
06243       for (int j = 0; j <= p; j++)
06244          for (int i = 0; i <= p; i++)
06245          {
06246             dshape(dof_map[o],0) = dshape_x(i)* shape_y(j)* shape_z(k);
06247             dshape(dof_map[o],1) =  shape_x(i)*dshape_y(j)* shape_z(k);
06248             dshape(dof_map[o],2) =  shape_x(i)* shape_y(j)*dshape_z(k);  o++;
06249          }
06250 }
06251 
06252 
06253 H1_TriangleElement::H1_TriangleElement(const int p)
06254    : NodalFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
06255                         FunctionSpace::Pk), T(Dof)
06256 {
06257    const double *cp = poly1d.ClosedPoints(p);
06258 
06259 #ifndef MFEM_USE_OPENMP
06260    shape_x.SetSize(p + 1);
06261    shape_y.SetSize(p + 1);
06262    shape_l.SetSize(p + 1);
06263    dshape_x.SetSize(p + 1);
06264    dshape_y.SetSize(p + 1);
06265    dshape_l.SetSize(p + 1);
06266    u.SetSize(Dof);
06267    du.SetSize(Dof, Dim);
06268 #else
06269    Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
06270 #endif
06271 
06272    // vertices
06273    Nodes.IntPoint(0).Set2(cp[0], cp[0]);
06274    Nodes.IntPoint(1).Set2(cp[p], cp[0]);
06275    Nodes.IntPoint(2).Set2(cp[0], cp[p]);
06276 
06277    // edges
06278    int o = 3;
06279    for (int i = 1; i < p; i++)
06280       Nodes.IntPoint(o++).Set2(cp[i], cp[0]);
06281    for (int i = 1; i < p; i++)
06282       Nodes.IntPoint(o++).Set2(cp[p-i], cp[i]);
06283    for (int i = 1; i < p; i++)
06284       Nodes.IntPoint(o++).Set2(cp[0], cp[p-i]);
06285 
06286    // interior
06287    for (int j = 1; j < p; j++)
06288       for (int i = 1; i + j < p; i++)
06289       {
06290          const double w = cp[i] + cp[j] + cp[p-i-j];
06291          Nodes.IntPoint(o++).Set2(cp[i]/w, cp[j]/w);
06292       }
06293 
06294    for (int k = 0; k < Dof; k++)
06295    {
06296       IntegrationPoint &ip = Nodes.IntPoint(k);
06297       poly1d.CalcBasis(p, ip.x, shape_x);
06298       poly1d.CalcBasis(p, ip.y, shape_y);
06299       poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
06300 
06301       o = 0;
06302       for (int j = 0; j <= p; j++)
06303          for (int i = 0; i + j <= p; i++)
06304             T(o++, k) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
06305    }
06306 
06307    T.Invert();
06308    // cout << "H1_TriangleElement(" << p << ") : "; T.TestInversion();
06309 }
06310 
06311 void H1_TriangleElement::CalcShape(const IntegrationPoint &ip,
06312                                    Vector &shape) const
06313 {
06314    const int p = Order;
06315 
06316 #ifdef MFEM_USE_OPENMP
06317    Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1), u(Dof);
06318 #endif
06319 
06320    poly1d.CalcBasis(p, ip.x, shape_x);
06321    poly1d.CalcBasis(p, ip.y, shape_y);
06322    poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
06323 
06324    for (int o = 0, j = 0; j <= p; j++)
06325       for (int i = 0; i + j <= p; i++)
06326          u(o++) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
06327 
06328    T.Mult(u, shape);
06329 }
06330 
06331 void H1_TriangleElement::CalcDShape(const IntegrationPoint &ip,
06332                                     DenseMatrix &dshape) const
06333 {
06334    const int p = Order;
06335 
06336 #ifdef MFEM_USE_OPENMP
06337    Vector  shape_x(p + 1),  shape_y(p + 1),  shape_l(p + 1);
06338    Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
06339    DenseMatrix du(Dof, Dim);
06340 #endif
06341 
06342    poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
06343    poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
06344    poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l);
06345 
06346    for (int o = 0, j = 0; j <= p; j++)
06347       for (int i = 0; i + j <= p; i++)
06348       {
06349          int k = p - i - j;
06350          du(o,0) = ((dshape_x(i)* shape_l(k)) -
06351                     ( shape_x(i)*dshape_l(k)))*shape_y(j);
06352          du(o,1) = ((dshape_y(j)* shape_l(k)) -
06353                     ( shape_y(j)*dshape_l(k)))*shape_x(i);
06354          o++;
06355       }
06356 
06357    Mult(T, du, dshape);
06358 }
06359 
06360 
06361 H1_TetrahedronElement::H1_TetrahedronElement(const int p)
06362    : NodalFiniteElement(3, Geometry::TETRAHEDRON, ((p + 1)*(p + 2)*(p + 3))/6,
06363                         p, FunctionSpace::Pk), T(Dof)
06364 {
06365    const double *cp = poly1d.ClosedPoints(p);
06366 
06367 #ifndef MFEM_USE_OPENMP
06368    shape_x.SetSize(p + 1);
06369    shape_y.SetSize(p + 1);
06370    shape_z.SetSize(p + 1);
06371    shape_l.SetSize(p + 1);
06372    dshape_x.SetSize(p + 1);
06373    dshape_y.SetSize(p + 1);
06374    dshape_z.SetSize(p + 1);
06375    dshape_l.SetSize(p + 1);
06376    u.SetSize(Dof);
06377    du.SetSize(Dof, Dim);
06378 #else
06379    Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
06380 #endif
06381 
06382    // vertices
06383    Nodes.IntPoint(0).Set3(cp[0], cp[0], cp[0]);
06384    Nodes.IntPoint(1).Set3(cp[p], cp[0], cp[0]);
06385    Nodes.IntPoint(2).Set3(cp[0], cp[p], cp[0]);
06386    Nodes.IntPoint(3).Set3(cp[0], cp[0], cp[p]);
06387 
06388    // edges (see Tetrahedron::edges in mesh/tetrahedron.cpp)
06389    int o = 4;
06390    for (int i = 1; i < p; i++)  // (0,1)
06391       Nodes.IntPoint(o++).Set3(cp[i], cp[0], cp[0]);
06392    for (int i = 1; i < p; i++)  // (0,2)
06393       Nodes.IntPoint(o++).Set3(cp[0], cp[i], cp[0]);
06394    for (int i = 1; i < p; i++)  // (0,3)
06395       Nodes.IntPoint(o++).Set3(cp[0], cp[0], cp[i]);
06396    for (int i = 1; i < p; i++)  // (1,2)
06397       Nodes.IntPoint(o++).Set3(cp[p-i], cp[i], cp[0]);
06398    for (int i = 1; i < p; i++)  // (1,3)
06399       Nodes.IntPoint(o++).Set3(cp[p-i], cp[0], cp[i]);
06400    for (int i = 1; i < p; i++)  // (2,3)
06401       Nodes.IntPoint(o++).Set3(cp[0], cp[p-i], cp[i]);
06402 
06403    // faces (see Mesh::GenerateFaces in mesh/mesh.cpp)
06404    for (int j = 1; j < p; j++)
06405       for (int i = 1; i + j < p; i++)  // (1,2,3)
06406       {
06407          double w = cp[i] + cp[j] + cp[p-i-j];
06408          Nodes.IntPoint(o++).Set3(cp[p-i-j]/w, cp[i]/w, cp[j]/w);
06409       }
06410    for (int j = 1; j < p; j++)
06411       for (int i = 1; i + j < p; i++)  // (0,3,2)
06412       {
06413          double w = cp[i] + cp[j] + cp[p-i-j];
06414          Nodes.IntPoint(o++).Set3(cp[0], cp[j]/w, cp[i]/w);
06415       }
06416    for (int j = 1; j < p; j++)
06417       for (int i = 1; i + j < p; i++)  // (0,1,3)
06418       {
06419          double w = cp[i] + cp[j] + cp[p-i-j];
06420          Nodes.IntPoint(o++).Set3(cp[i]/w, cp[0], cp[j]/w);
06421       }
06422    for (int j = 1; j < p; j++)
06423       for (int i = 1; i + j < p; i++)  // (0,2,1)
06424       {
06425          double w = cp[i] + cp[j] + cp[p-i-j];
06426          Nodes.IntPoint(o++).Set3(cp[j]/w, cp[i]/w, cp[0]);
06427       }
06428 
06429    // interior
06430    for (int k = 1; k < p; k++)
06431       for (int j = 1; j + k < p; j++)
06432          for (int i = 1; i + j + k < p; i++)
06433          {
06434             double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k];
06435             Nodes.IntPoint(o++).Set3(cp[i]/w, cp[j]/w, cp[k]/w);
06436          }
06437 
06438    for (int m = 0; m < Dof; m++)
06439    {
06440       IntegrationPoint &ip = Nodes.IntPoint(m);
06441       poly1d.CalcBasis(p, ip.x, shape_x);
06442       poly1d.CalcBasis(p, ip.y, shape_y);
06443       poly1d.CalcBasis(p, ip.z, shape_z);
06444       poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
06445 
06446       o = 0;
06447       for (int k = 0; k <= p; k++)
06448          for (int j = 0; j + k <= p; j++)
06449             for (int i = 0; i + j + k <= p; i++)
06450                T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
06451    }
06452 
06453    T.Invert();
06454    // cout << "H1_TetrahedronElement(" << p << ") : "; T.TestInversion();
06455 }
06456 
06457 void H1_TetrahedronElement::CalcShape(const IntegrationPoint &ip,
06458                                       Vector &shape) const
06459 {
06460    const int p = Order;
06461 
06462 #ifdef MFEM_USE_OPENMP
06463    Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
06464    Vector u(Dof);
06465 #endif
06466 
06467    poly1d.CalcBasis(p, ip.x, shape_x);
06468    poly1d.CalcBasis(p, ip.y, shape_y);
06469    poly1d.CalcBasis(p, ip.z, shape_z);
06470    poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
06471 
06472    for (int o = 0, k = 0; k <= p; k++)
06473       for (int j = 0; j + k <= p; j++)
06474          for (int i = 0; i + j + k <= p; i++)
06475             u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
06476 
06477    T.Mult(u, shape);
06478 }
06479 
06480 void H1_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
06481                                        DenseMatrix &dshape) const
06482 {
06483    const int p = Order;
06484 
06485 #ifdef MFEM_USE_OPENMP
06486    Vector  shape_x(p + 1),  shape_y(p + 1),  shape_z(p + 1),  shape_l(p + 1);
06487    Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
06488    DenseMatrix du(Dof, Dim);
06489 #endif
06490 
06491    poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
06492    poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
06493    poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
06494    poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
06495 
06496    for (int o = 0, k = 0; k <= p; k++)
06497       for (int j = 0; j + k <= p; j++)
06498          for (int i = 0; i + j + k <= p; i++)
06499          {
06500             int l = p - i - j - k;
06501             du(o,0) = ((dshape_x(i)* shape_l(l)) -
06502                        ( shape_x(i)*dshape_l(l)))*shape_y(j)*shape_z(k);
06503             du(o,1) = ((dshape_y(j)* shape_l(l)) -
06504                        ( shape_y(j)*dshape_l(l)))*shape_x(i)*shape_z(k);
06505             du(o,2) = ((dshape_z(k)* shape_l(l)) -
06506                        ( shape_z(k)*dshape_l(l)))*shape_x(i)*shape_y(j);
06507             o++;
06508          }
06509 
06510    Mult(T, du, dshape);
06511 }
06512 
06513 
06514 L2_SegmentElement::L2_SegmentElement(const int p)
06515    : NodalFiniteElement(1, Geometry::SEGMENT, p + 1, p, FunctionSpace::Pk),
06516      basis1d(poly1d.OpenBasis(p))
06517 {
06518    const double *op = poly1d.OpenPoints(p);
06519 
06520 #ifndef MFEM_USE_OPENMP
06521    shape_x.SetSize(p + 1);
06522    dshape_x.SetDataAndSize(NULL, p + 1);
06523 #endif
06524 
06525    for (int i = 0; i <= p; i++)
06526       Nodes.IntPoint(i).x = op[i];
06527 }
06528 
06529 void L2_SegmentElement::CalcShape(const IntegrationPoint &ip,
06530                                   Vector &shape) const
06531 {
06532    basis1d.Eval(ip.x, shape);
06533 }
06534 
06535 void L2_SegmentElement::CalcDShape(const IntegrationPoint &ip,
06536                                    DenseMatrix &dshape) const
06537 {
06538 #ifdef MFEM_USE_OPENMP
06539    Vector shape_x(Dof), dshape_x(dshape.Data(), Dof);
06540 #else
06541    dshape_x.SetData(dshape.Data());
06542 #endif
06543    basis1d.Eval(ip.x, shape_x, dshape_x);
06544 }
06545 
06546 void L2_SegmentElement::ProjectDelta(int vertex,
06547                                      Vector &dofs) const
06548 {
06549    const int p = Order;
06550    const double *op = poly1d.OpenPoints(p);
06551    switch (vertex)
06552    {
06553    case 0:
06554       for (int i = 0; i <= p; i++)
06555          dofs(i) = poly1d.CalcDelta(p,(1.0 - op[i]));
06556       break;
06557 
06558    case 1:
06559       for (int i = 0; i <= p; i++)
06560          dofs(i) = poly1d.CalcDelta(p,op[i]);
06561       break;
06562    }
06563 }
06564 
06565 
06566 L2_QuadrilateralElement::L2_QuadrilateralElement(const int p)
06567    : NodalFiniteElement(2, Geometry::SQUARE, (p + 1)*(p + 1), p,
06568                         FunctionSpace::Qk), basis1d(poly1d.OpenBasis(p))
06569 {
06570    const double *op = poly1d.OpenPoints(p);
06571 
06572 #ifndef MFEM_USE_OPENMP
06573    shape_x.SetSize(p + 1);
06574    shape_y.SetSize(p + 1);
06575    dshape_x.SetSize(p + 1);
06576    dshape_y.SetSize(p + 1);
06577 #endif
06578 
06579    for (int o = 0, j = 0; j <= p; j++)
06580       for (int i = 0; i <= p; i++)
06581          Nodes.IntPoint(o++).Set2(op[i], op[j]);
06582 }
06583 
06584 void L2_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
06585                                         Vector &shape) const
06586 {
06587    const int p = Order;
06588 
06589 #ifdef MFEM_USE_OPENMP
06590    Vector shape_x(p+1), shape_y(p+1);
06591 #endif
06592 
06593    basis1d.Eval(ip.x, shape_x);
06594    basis1d.Eval(ip.y, shape_y);
06595 
06596    for (int o = 0, j = 0; j <= p; j++)
06597       for (int i = 0; i <= p; i++)
06598          shape(o++) = shape_x(i)*shape_y(j);
06599 }
06600 
06601 void L2_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
06602                                          DenseMatrix &dshape) const
06603 {
06604    const int p = Order;
06605 
06606 #ifdef MFEM_USE_OPENMP
06607    Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
06608 #endif
06609 
06610    basis1d.Eval(ip.x, shape_x, dshape_x);
06611    basis1d.Eval(ip.y, shape_y, dshape_y);
06612 
06613    for (int o = 0, j = 0; j <= p; j++)
06614       for (int i = 0; i <= p; i++)
06615       {
06616          dshape(o,0) = dshape_x(i)* shape_y(j);
06617          dshape(o,1) =  shape_x(i)*dshape_y(j);  o++;
06618       }
06619 }
06620 
06621 void L2_QuadrilateralElement::ProjectDelta(int vertex,
06622                                            Vector &dofs) const
06623 {
06624    const int p = Order;
06625    const double *op = poly1d.OpenPoints(p);
06626 
06627 #ifdef MFEM_USE_OPENMP
06628    Vector shape_x(p+1), shape_y(p+1);
06629 #endif
06630 
06631    for (int i = 0; i <= p; i++)
06632    {
06633       shape_x(i) = poly1d.CalcDelta(p,(1.0 - op[i]));
06634       shape_y(i) = poly1d.CalcDelta(p,op[i]);
06635    }
06636 
06637    switch (vertex)
06638    {
06639    case 0:
06640       for (int o = 0, j = 0; j <= p; j++)
06641          for (int i = 0; i <= p; i++)
06642             dofs[o++] = shape_x(i)*shape_x(j);
06643       break;
06644    case 1:
06645       for (int o = 0, j = 0; j <= p; j++)
06646          for (int i = 0; i <= p; i++)
06647             dofs[o++] = shape_y(i)*shape_x(j);
06648       break;
06649    case 2:
06650       for (int o = 0, j = 0; j <= p; j++)
06651          for (int i = 0; i <= p; i++)
06652             dofs[o++] = shape_y(i)*shape_y(j);
06653       break;
06654    case 3:
06655       for (int o = 0, j = 0; j <= p; j++)
06656          for (int i = 0; i <= p; i++)
06657             dofs[o++] = shape_x(i)*shape_y(j);
06658       break;
06659    }
06660 }
06661 
06662 
06663 L2_HexahedronElement::L2_HexahedronElement(const int p)
06664    : NodalFiniteElement(3, Geometry::CUBE, (p + 1)*(p + 1)*(p + 1), p,
06665                         FunctionSpace::Qk), basis1d(poly1d.OpenBasis(p))
06666 {
06667    const double *op = poly1d.OpenPoints(p);
06668 
06669 #ifndef MFEM_USE_OPENMP
06670    shape_x.SetSize(p + 1);
06671    shape_y.SetSize(p + 1);
06672    shape_z.SetSize(p + 1);
06673    dshape_x.SetSize(p + 1);
06674    dshape_y.SetSize(p + 1);
06675    dshape_z.SetSize(p + 1);
06676 #endif
06677 
06678    for (int o = 0, k = 0; k <= p; k++)
06679       for (int j = 0; j <= p; j++)
06680          for (int i = 0; i <= p; i++)
06681             Nodes.IntPoint(o++).Set3(op[i], op[j], op[k]);
06682 }
06683 
06684 void L2_HexahedronElement::CalcShape(const IntegrationPoint &ip,
06685                                      Vector &shape) const
06686 {
06687    const int p = Order;
06688 
06689 #ifdef MFEM_USE_OPENMP
06690    Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
06691 #endif
06692 
06693    basis1d.Eval(ip.x, shape_x);
06694    basis1d.Eval(ip.y, shape_y);
06695    basis1d.Eval(ip.z, shape_z);
06696 
06697    for (int o = 0, k = 0; k <= p; k++)
06698       for (int j = 0; j <= p; j++)
06699          for (int i = 0; i <= p; i++)
06700             shape(o++) = shape_x(i)*shape_y(j)*shape_z(k);
06701 }
06702 
06703 void L2_HexahedronElement::CalcDShape(const IntegrationPoint &ip,
06704                                       DenseMatrix &dshape) const
06705 {
06706    const int p = Order;
06707 
06708 #ifdef MFEM_USE_OPENMP
06709    Vector shape_x(p+1),  shape_y(p+1),  shape_z(p+1);
06710    Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
06711 #endif
06712 
06713    basis1d.Eval(ip.x, shape_x, dshape_x);
06714    basis1d.Eval(ip.y, shape_y, dshape_y);
06715    basis1d.Eval(ip.z, shape_z, dshape_z);
06716 
06717    for (int o = 0, k = 0; k <= p; k++)
06718       for (int j = 0; j <= p; j++)
06719          for (int i = 0; i <= p; i++)
06720          {
06721             dshape(o,0) = dshape_x(i)* shape_y(j)* shape_z(k);
06722             dshape(o,1) =  shape_x(i)*dshape_y(j)* shape_z(k);
06723             dshape(o,2) =  shape_x(i)* shape_y(j)*dshape_z(k);  o++;
06724          }
06725 }
06726 
06727 void L2_HexahedronElement::ProjectDelta(int vertex,
06728                                         Vector &dofs) const
06729 {
06730    const int p = Order;
06731    const double *op = poly1d.OpenPoints(p);
06732 
06733 #ifdef MFEM_USE_OPENMP
06734    Vector shape_x(p+1), shape_y(p+1);
06735 #endif
06736 
06737    for (int i = 0; i <= p; i++)
06738    {
06739       shape_x(i) = poly1d.CalcDelta(p,(1.0 - op[i]));
06740       shape_y(i) = poly1d.CalcDelta(p,op[i]);
06741    }
06742 
06743    switch (vertex)
06744    {
06745    case 0:
06746       for (int o = 0, k = 0; k <= p; k++)
06747          for (int j = 0; j <= p; j++)
06748             for (int i = 0; i <= p; i++)
06749                dofs[o++] = shape_x(i)*shape_x(j)*shape_x(k);
06750       break;
06751    case 1:
06752       for (int o = 0, k = 0; k <= p; k++)
06753          for (int j = 0; j <= p; j++)
06754             for (int i = 0; i <= p; i++)
06755                dofs[o++] = shape_y(i)*shape_x(j)*shape_x(k);
06756       break;
06757    case 2:
06758       for (int o = 0, k = 0; k <= p; k++)
06759          for (int j = 0; j <= p; j++)
06760             for (int i = 0; i <= p; i++)
06761                dofs[o++] = shape_y(i)*shape_y(j)*shape_x(k);
06762       break;
06763    case 3:
06764       for (int o = 0, k = 0; k <= p; k++)
06765          for (int j = 0; j <= p; j++)
06766             for (int i = 0; i <= p; i++)
06767                dofs[o++] = shape_x(i)*shape_y(j)*shape_x(k);
06768       break;
06769    case 4:
06770       for (int o = 0, k = 0; k <= p; k++)
06771          for (int j = 0; j <= p; j++)
06772             for (int i = 0; i <= p; i++)
06773                dofs[o++] = shape_x(i)*shape_x(j)*shape_y(k);
06774       break;
06775    case 5:
06776       for (int o = 0, k = 0; k <= p; k++)
06777          for (int j = 0; j <= p; j++)
06778             for (int i = 0; i <= p; i++)
06779                dofs[o++] = shape_y(i)*shape_x(j)*shape_y(k);
06780       break;
06781    case 6:
06782       for (int o = 0, k = 0; k <= p; k++)
06783          for (int j = 0; j <= p; j++)
06784             for (int i = 0; i <= p; i++)
06785                dofs[o++] = shape_y(i)*shape_y(j)*shape_y(k);
06786       break;
06787    case 7:
06788       for (int o = 0, k = 0; k <= p; k++)
06789          for (int j = 0; j <= p; j++)
06790             for (int i = 0; i <= p; i++)
06791                dofs[o++] = shape_x(i)*shape_y(j)*shape_y(k);
06792       break;
06793    }
06794 }
06795 
06796 
06797 L2_TriangleElement::L2_TriangleElement(const int p)
06798    : NodalFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
06799                         FunctionSpace::Pk), T(Dof)
06800 {
06801    const double *op = poly1d.OpenPoints(p);
06802 
06803 #ifndef MFEM_USE_OPENMP
06804    shape_x.SetSize(p + 1);
06805    shape_y.SetSize(p + 1);
06806    shape_l.SetSize(p + 1);
06807    dshape_x.SetSize(p + 1);
06808    dshape_y.SetSize(p + 1);
06809    dshape_l.SetSize(p + 1);
06810    u.SetSize(Dof);
06811    du.SetSize(Dof, Dim);
06812 #else
06813    Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
06814 #endif
06815 
06816    for (int o = 0, j = 0; j <= p; j++)
06817       for (int i = 0; i + j <= p; i++)
06818       {
06819          double w = op[i] + op[j] + op[p-i-j];
06820          Nodes.IntPoint(o++).Set2(op[i]/w, op[j]/w);
06821       }
06822 
06823    for (int k = 0; k < Dof; k++)
06824    {
06825       IntegrationPoint &ip = Nodes.IntPoint(k);
06826       poly1d.CalcBasis(p, ip.x, shape_x);
06827       poly1d.CalcBasis(p, ip.y, shape_y);
06828       poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
06829 
06830       for (int o = 0, j = 0; j <= p; j++)
06831          for (int i = 0; i + j <= p; i++)
06832             T(o++, k) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
06833    }
06834 
06835    T.Invert();
06836    // cout << "L2_TriangleElement(" << p << ") : "; T.TestInversion();
06837 }
06838 
06839 void L2_TriangleElement::CalcShape(const IntegrationPoint &ip,
06840                                    Vector &shape) const
06841 {
06842    const int p = Order;
06843 
06844 #ifdef MFEM_USE_OPENMP
06845    Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1), u(Dof);
06846 #endif
06847 
06848    poly1d.CalcBasis(p, ip.x, shape_x);
06849    poly1d.CalcBasis(p, ip.y, shape_y);
06850    poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
06851 
06852    for (int o = 0, j = 0; j <= p; j++)
06853       for (int i = 0; i + j <= p; i++)
06854          u(o++) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
06855 
06856    T.Mult(u, shape);
06857 }
06858 
06859 void L2_TriangleElement::CalcDShape(const IntegrationPoint &ip,
06860                                     DenseMatrix &dshape) const
06861 {
06862    const int p = Order;
06863 
06864 #ifdef MFEM_USE_OPENMP
06865    Vector  shape_x(p + 1),  shape_y(p + 1),  shape_l(p + 1);
06866    Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
06867    DenseMatrix du(Dof, Dim);
06868 #endif
06869 
06870    poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
06871    poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
06872    poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l);
06873 
06874    for (int o = 0, j = 0; j <= p; j++)
06875       for (int i = 0; i + j <= p; i++)
06876       {
06877          int k = p - i - j;
06878          du(o,0) = ((dshape_x(i)* shape_l(k)) -
06879                     ( shape_x(i)*dshape_l(k)))*shape_y(j);
06880          du(o,1) = ((dshape_y(j)* shape_l(k)) -
06881                     ( shape_y(j)*dshape_l(k)))*shape_x(i);
06882          o++;
06883       }
06884 
06885    Mult(T, du, dshape);
06886 }
06887 
06888 
06889 L2_TetrahedronElement::L2_TetrahedronElement(const int p)
06890    : NodalFiniteElement(3, Geometry::TETRAHEDRON, ((p + 1)*(p + 2)*(p + 3))/6,
06891                         p, FunctionSpace::Pk), T(Dof)
06892 {
06893    const double *op = poly1d.OpenPoints(p);
06894 
06895 #ifndef MFEM_USE_OPENMP
06896    shape_x.SetSize(p + 1);
06897    shape_y.SetSize(p + 1);
06898    shape_z.SetSize(p + 1);
06899    shape_l.SetSize(p + 1);
06900    dshape_x.SetSize(p + 1);
06901    dshape_y.SetSize(p + 1);
06902    dshape_z.SetSize(p + 1);
06903    dshape_l.SetSize(p + 1);
06904    u.SetSize(Dof);
06905    du.SetSize(Dof, Dim);
06906 #else
06907    Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
06908 #endif
06909 
06910    for (int o = 0, k = 0; k <= p; k++)
06911       for (int j = 0; j + k <= p; j++)
06912          for (int i = 0; i + j + k <= p; i++)
06913          {
06914             double w = op[i] + op[j] + op[k] + op[p-i-j-k];
06915             Nodes.IntPoint(o++).Set3(op[i]/w, op[j]/w, op[k]/w);
06916          }
06917 
06918    for (int m = 0; m < Dof; m++)
06919    {
06920       IntegrationPoint &ip = Nodes.IntPoint(m);
06921       poly1d.CalcBasis(p, ip.x, shape_x);
06922       poly1d.CalcBasis(p, ip.y, shape_y);
06923       poly1d.CalcBasis(p, ip.z, shape_z);
06924       poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
06925 
06926       for (int o = 0, k = 0; k <= p; k++)
06927          for (int j = 0; j + k <= p; j++)
06928             for (int i = 0; i + j + k <= p; i++)
06929                T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
06930    }
06931 
06932    T.Invert();
06933    // cout << "L2_TetrahedronElement(" << p << ") : "; T.TestInversion();
06934 }
06935 
06936 void L2_TetrahedronElement::CalcShape(const IntegrationPoint &ip,
06937                                       Vector &shape) const
06938 {
06939    const int p = Order;
06940 
06941 #ifdef MFEM_USE_OPENMP
06942    Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
06943    Vector u(Dof);
06944 #endif
06945 
06946    poly1d.CalcBasis(p, ip.x, shape_x);
06947    poly1d.CalcBasis(p, ip.y, shape_y);
06948    poly1d.CalcBasis(p, ip.z, shape_z);
06949    poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
06950 
06951    for (int o = 0, k = 0; k <= p; k++)
06952       for (int j = 0; j + k <= p; j++)
06953          for (int i = 0; i + j + k <= p; i++)
06954             u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
06955 
06956    T.Mult(u, shape);
06957 }
06958 
06959 void L2_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
06960                                        DenseMatrix &dshape) const
06961 {
06962    const int p = Order;
06963 
06964 #ifdef MFEM_USE_OPENMP
06965    Vector  shape_x(p + 1),  shape_y(p + 1),  shape_z(p + 1),  shape_l(p + 1);
06966    Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
06967    DenseMatrix du(Dof, Dim);
06968 #endif
06969 
06970    poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
06971    poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
06972    poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
06973    poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
06974 
06975    for (int o = 0, k = 0; k <= p; k++)
06976       for (int j = 0; j + k <= p; j++)
06977          for (int i = 0; i + j + k <= p; i++)
06978          {
06979             int l = p - i - j - k;
06980             du(o,0) = ((dshape_x(i)* shape_l(l)) -
06981                        ( shape_x(i)*dshape_l(l)))*shape_y(j)*shape_z(k);
06982             du(o,1) = ((dshape_y(j)* shape_l(l)) -
06983                        ( shape_y(j)*dshape_l(l)))*shape_x(i)*shape_z(k);
06984             du(o,2) = ((dshape_z(k)* shape_l(l)) -
06985                        ( shape_z(k)*dshape_l(l)))*shape_x(i)*shape_y(j);
06986             o++;
06987          }
06988 
06989    Mult(T, du, dshape);
06990 }
06991 
06992 
06993 const double RT_QuadrilateralElement::nk[8] =
06994 { 0., -1.,  1., 0.,  0., 1.,  -1., 0. };
06995 
06996 RT_QuadrilateralElement::RT_QuadrilateralElement(const int p)
06997    : VectorFiniteElement(2, Geometry::SQUARE, 2*(p + 1)*(p + 2), p + 1,
06998                          FunctionSpace::Qk),
06999      cbasis1d(poly1d.ClosedBasis(p + 1)), obasis1d(poly1d.OpenBasis(p)),
07000      dof_map(Dof), dof2nk(Dof)
07001 {
07002    const double *cp = poly1d.ClosedPoints(p + 1);
07003    const double *op = poly1d.OpenPoints(p);
07004    const int dof2 = Dof/2;
07005 
07006 #ifndef MFEM_USE_OPENMP
07007    shape_cx.SetSize(p + 2);
07008    shape_ox.SetSize(p + 1);
07009    shape_cy.SetSize(p + 2);
07010    shape_oy.SetSize(p + 1);
07011    dshape_cx.SetSize(p + 2);
07012    dshape_cy.SetSize(p + 2);
07013 #endif
07014 
07015    // edges
07016    int o = 0;
07017    for (int i = 0; i <= p; i++)  // (0,1)
07018       dof_map[1*dof2 + i + 0*(p + 1)] = o++;
07019    for (int i = 0; i <= p; i++)  // (1,2)
07020       dof_map[0*dof2 + (p + 1) + i*(p + 2)] = o++;
07021    for (int i = 0; i <= p; i++)  // (2,3)
07022       dof_map[1*dof2 + (p - i) + (p + 1)*(p + 1)] = o++;
07023    for (int i = 0; i <= p; i++)  // (3,0)
07024       dof_map[0*dof2 + 0 + (p - i)*(p + 2)] = o++;
07025 
07026    // interior
07027    for (int j = 0; j <= p; j++)  // x-components
07028       for (int i = 1; i <= p; i++)
07029          dof_map[0*dof2 + i + j*(p + 2)] = o++;
07030    for (int j = 1; j <= p; j++)  // y-components
07031       for (int i = 0; i <= p; i++)
07032          dof_map[1*dof2 + i + j*(p + 1)] = o++;
07033 
07034    // dof orientations
07035    // x-components
07036    for (int j = 0; j <= p; j++)
07037       for (int i = 0; i <= p/2; i++)
07038       {
07039          int idx = 0*dof2 + i + j*(p + 2);
07040          dof_map[idx] = -1 - dof_map[idx];
07041       }
07042    if (p%2 == 1)
07043       for (int j = p/2 + 1; j <= p; j++)
07044       {
07045          int idx = 0*dof2 + (p/2 + 1) + j*(p + 2);
07046          dof_map[idx] = -1 - dof_map[idx];
07047       }
07048    // y-components
07049    for (int j = 0; j <= p/2; j++)
07050       for (int i = 0; i <= p; i++)
07051       {
07052          int idx = 1*dof2 + i + j*(p + 1);
07053          dof_map[idx] = -1 - dof_map[idx];
07054       }
07055    if (p%2 == 1)
07056       for (int i = p/2 + 1; i <= p; i++)
07057       {
07058          int idx = 1*dof2 + i + (p/2 + 1)*(p + 1);
07059          dof_map[idx] = -1 - dof_map[idx];
07060       }
07061 
07062    o = 0;
07063    for (int j = 0; j <= p; j++)
07064       for (int i = 0; i <= p + 1; i++)
07065       {
07066          int idx;
07067          if ((idx = dof_map[o++]) < 0)
07068          {
07069             idx = -1 - idx;
07070             dof2nk[idx] = 3;
07071          }
07072          else
07073          {
07074             dof2nk[idx] = 1;
07075          }
07076          Nodes.IntPoint(idx).Set2(cp[i], op[j]);
07077       }
07078    for (int j = 0; j <= p + 1; j++)
07079       for (int i = 0; i <= p; i++)
07080       {
07081          int idx;
07082          if ((idx = dof_map[o++]) < 0)
07083          {
07084             idx = -1 - idx;
07085             dof2nk[idx] = 0;
07086          }
07087          else
07088          {
07089             dof2nk[idx] = 2;
07090          }
07091          Nodes.IntPoint(idx).Set2(op[i], cp[j]);
07092       }
07093 }
07094 
07095 void RT_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip,
07096                                          DenseMatrix &shape) const
07097 {
07098    const int pp1 = Order;
07099 
07100 #ifdef MFEM_USE_OPENMP
07101    Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
07102 #endif
07103 
07104    cbasis1d.Eval(ip.x, shape_cx);
07105    obasis1d.Eval(ip.x, shape_ox);
07106    cbasis1d.Eval(ip.y, shape_cy);
07107    obasis1d.Eval(ip.y, shape_oy);
07108 
07109    int o = 0;
07110    for (int j = 0; j < pp1; j++)
07111       for (int i = 0; i <= pp1; i++)
07112       {
07113          int idx, s;
07114          if ((idx = dof_map[o++]) < 0)
07115             idx = -1 - idx, s = -1;
07116          else
07117             s = +1;
07118          shape(idx,0) = s*shape_cx(i)*shape_oy(j);
07119          shape(idx,1) = 0.;
07120       }
07121    for (int j = 0; j <= pp1; j++)
07122       for (int i = 0; i < pp1; i++)
07123       {
07124          int idx, s;
07125          if ((idx = dof_map[o++]) < 0)
07126             idx = -1 - idx, s = -1;
07127          else
07128             s = +1;
07129          shape(idx,0) = 0.;
07130          shape(idx,1) = s*shape_ox(i)*shape_cy(j);
07131       }
07132 }
07133 
07134 void RT_QuadrilateralElement::CalcDivShape(const IntegrationPoint &ip,
07135                                            Vector &divshape) const
07136 {
07137    const int pp1 = Order;
07138 
07139 #ifdef MFEM_USE_OPENMP
07140    Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
07141    Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1);
07142 #endif
07143 
07144    cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
07145    obasis1d.Eval(ip.x, shape_ox);
07146    cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
07147    obasis1d.Eval(ip.y, shape_oy);
07148 
07149    int o = 0;
07150    for (int j = 0; j < pp1; j++)
07151       for (int i = 0; i <= pp1; i++)
07152       {
07153          int idx, s;
07154          if ((idx = dof_map[o++]) < 0)
07155             idx = -1 - idx, s = -1;
07156          else
07157             s = +1;
07158          divshape(idx) = s*dshape_cx(i)*shape_oy(j);
07159       }
07160    for (int j = 0; j <= pp1; j++)
07161       for (int i = 0; i < pp1; i++)
07162       {
07163          int idx, s;
07164          if ((idx = dof_map[o++]) < 0)
07165             idx = -1 - idx, s = -1;
07166          else
07167             s = +1;
07168          divshape(idx) = s*shape_ox(i)*dshape_cy(j);
07169       }
07170 }
07171 
07172 
07173 const double RT_HexahedronElement::nk[18] =
07174 { 0.,0.,-1.,  0.,-1.,0.,  1.,0.,0.,  0.,1.,0.,  -1.,0.,0.,  0.,0.,1. };
07175 
07176 RT_HexahedronElement::RT_HexahedronElement(const int p)
07177    : VectorFiniteElement(3, Geometry::CUBE, 3*(p + 1)*(p + 1)*(p + 2), p + 1,
07178                          FunctionSpace::Qk),
07179      cbasis1d(poly1d.ClosedBasis(p + 1)), obasis1d(poly1d.OpenBasis(p)),
07180      dof_map(Dof), dof2nk(Dof)
07181 {
07182    const double *cp = poly1d.ClosedPoints(p + 1);
07183    const double *op = poly1d.OpenPoints(p);
07184    const int dof3 = Dof/3;
07185 
07186 #ifndef MFEM_USE_OPENMP
07187    shape_cx.SetSize(p + 2);
07188    shape_ox.SetSize(p + 1);
07189    shape_cy.SetSize(p + 2);
07190    shape_oy.SetSize(p + 1);
07191    shape_cz.SetSize(p + 2);
07192    shape_oz.SetSize(p + 1);
07193    dshape_cx.SetSize(p + 2);
07194    dshape_cy.SetSize(p + 2);
07195    dshape_cz.SetSize(p + 2);
07196 #endif
07197 
07198    // faces
07199    int o = 0;
07200    for (int j = 0; j <= p; j++)  // (3,2,1,0) -- bottom
07201       for (int i = 0; i <= p; i++)
07202          dof_map[2*dof3 + i + ((p - j) + 0*(p + 1))*(p + 1)] = o++;
07203    for (int j = 0; j <= p; j++)  // (0,1,5,4) -- front
07204       for (int i = 0; i <= p; i++)
07205          dof_map[1*dof3 + i + (0 + j*(p + 2))*(p + 1)] = o++;
07206    for (int j = 0; j <= p; j++)  // (1,2,6,5) -- right
07207       for (int i = 0; i <= p; i++)
07208          dof_map[0*dof3 + (p + 1) + (i + j*(p + 1))*(p + 2)] = o++;
07209    for (int j = 0; j <= p; j++)  // (2,3,7,6) -- back
07210       for (int i = 0; i <= p; i++)
07211          dof_map[1*dof3 + (p - i) + ((p + 1) + j*(p + 2))*(p + 1)] = o++;
07212    for (int j = 0; j <= p; j++)  // (3,0,4,7) -- left
07213       for (int i = 0; i <= p; i++)
07214          dof_map[0*dof3 + 0 + ((p - i) + j*(p + 1))*(p + 2)] = o++;
07215    for (int j = 0; j <= p; j++)  // (4,5,6,7) -- top
07216       for (int i = 0; i <= p; i++)
07217          dof_map[2*dof3 + i + (j + (p + 1)*(p + 1))*(p + 1)] = o++;
07218 
07219    // interior
07220    // x-components
07221    for (int k = 0; k <= p; k++)
07222       for (int j = 0; j <= p; j++)
07223          for (int i = 1; i <= p; i++)
07224             dof_map[0*dof3 + i + (j + k*(p + 1))*(p + 2)] = o++;
07225    // y-components
07226    for (int k = 0; k <= p; k++)
07227       for (int j = 1; j <= p; j++)
07228          for (int i = 0; i <= p; i++)
07229             dof_map[1*dof3 + i + (j + k*(p + 2))*(p + 1)] = o++;
07230    // z-components
07231    for (int k = 1; k <= p; k++)
07232       for (int j = 0; j <= p; j++)
07233          for (int i = 0; i <= p; i++)
07234             dof_map[2*dof3 + i + (j + k*(p + 1))*(p + 1)] = o++;
07235 
07236    // dof orientations
07237    // for odd p, do not change the orientations in the mid-planes
07238    // {i = p/2 + 1}, {j = p/2 + 1}, {k = p/2 + 1} in the x, y, z-components
07239    // respectively.
07240    // x-components
07241    for (int k = 0; k <= p; k++)
07242       for (int j = 0; j <= p; j++)
07243          for (int i = 0; i <= p/2; i++)
07244          {
07245             int idx = 0*dof3 + i + (j + k*(p + 1))*(p + 2);
07246             dof_map[idx] = -1 - dof_map[idx];
07247          }
07248    // y-components
07249    for (int k = 0; k <= p; k++)
07250       for (int j = 0; j <= p/2; j++)
07251          for (int i = 0; i <= p; i++)
07252          {
07253             int idx = 1*dof3 + i + (j + k*(p + 2))*(p + 1);
07254             dof_map[idx] = -1 - dof_map[idx];
07255          }
07256    // z-components
07257    for (int k = 0; k <= p/2; k++)
07258       for (int j = 0; j <= p; j++)
07259          for (int i = 0; i <= p; i++)
07260          {
07261             int idx = 2*dof3 + i + (j + k*(p + 1))*(p + 1);
07262             dof_map[idx] = -1 - dof_map[idx];
07263          }
07264 
07265    o = 0;
07266    // x-components
07267    for (int k = 0; k <= p; k++)
07268       for (int j = 0; j <= p; j++)
07269          for (int i = 0; i <= p + 1; i++)
07270          {
07271             int idx;
07272             if ((idx = dof_map[o++]) < 0)
07273             {
07274                idx = -1 - idx;
07275                dof2nk[idx] = 4;
07276             }
07277             else
07278             {
07279                dof2nk[idx] = 2;
07280             }
07281             Nodes.IntPoint(idx).Set3(cp[i], op[j], op[k]);
07282          }
07283    // y-components
07284    for (int k = 0; k <= p; k++)
07285       for (int j = 0; j <= p + 1; j++)
07286          for (int i = 0; i <= p; i++)
07287          {
07288             int idx;
07289             if ((idx = dof_map[o++]) < 0)
07290             {
07291                idx = -1 - idx;
07292                dof2nk[idx] = 1;
07293             }
07294             else
07295             {
07296                dof2nk[idx] = 3;
07297             }
07298             Nodes.IntPoint(idx).Set3(op[i], cp[j], op[k]);
07299          }
07300    // z-components
07301    for (int k = 0; k <= p + 1; k++)
07302       for (int j = 0; j <= p; j++)
07303          for (int i = 0; i <= p; i++)
07304          {
07305             int idx;
07306             if ((idx = dof_map[o++]) < 0)
07307             {
07308                idx = -1 - idx;
07309                dof2nk[idx] = 0;
07310             }
07311             else
07312             {
07313                dof2nk[idx] = 5;
07314             }
07315             Nodes.IntPoint(idx).Set3(op[i], op[j], cp[k]);
07316          }
07317 }
07318 
07319 void RT_HexahedronElement::CalcVShape(const IntegrationPoint &ip,
07320                                       DenseMatrix &shape) const
07321 {
07322    const int pp1 = Order;
07323 
07324 #ifdef MFEM_USE_OPENMP
07325    Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
07326    Vector shape_cz(pp1 + 1), shape_oz(pp1);
07327 #endif
07328 
07329    cbasis1d.Eval(ip.x, shape_cx);
07330    obasis1d.Eval(ip.x, shape_ox);
07331    cbasis1d.Eval(ip.y, shape_cy);
07332    obasis1d.Eval(ip.y, shape_oy);
07333    cbasis1d.Eval(ip.z, shape_cz);
07334    obasis1d.Eval(ip.z, shape_oz);
07335 
07336    int o = 0;
07337    // x-components
07338    for (int k = 0; k < pp1; k++)
07339       for (int j = 0; j < pp1; j++)
07340          for (int i = 0; i <= pp1; i++)
07341          {
07342             int idx, s;
07343             if ((idx = dof_map[o++]) < 0)
07344                idx = -1 - idx, s = -1;
07345             else
07346                s = +1;
07347             shape(idx,0) = s*shape_cx(i)*shape_oy(j)*shape_oz(k);
07348             shape(idx,1) = 0.;
07349             shape(idx,2) = 0.;
07350          }
07351    // y-components
07352    for (int k = 0; k < pp1; k++)
07353       for (int j = 0; j <= pp1; j++)
07354          for (int i = 0; i < pp1; i++)
07355          {
07356             int idx, s;
07357             if ((idx = dof_map[o++]) < 0)
07358                idx = -1 - idx, s = -1;
07359             else
07360                s = +1;
07361             shape(idx,0) = 0.;
07362             shape(idx,1) = s*shape_ox(i)*shape_cy(j)*shape_oz(k);
07363             shape(idx,2) = 0.;
07364          }
07365    // z-components
07366    for (int k = 0; k <= pp1; k++)
07367       for (int j = 0; j < pp1; j++)
07368          for (int i = 0; i < pp1; i++)
07369          {
07370             int idx, s;
07371             if ((idx = dof_map[o++]) < 0)
07372                idx = -1 - idx, s = -1;
07373             else
07374                s = +1;
07375             shape(idx,0) = 0.;
07376             shape(idx,1) = 0.;
07377             shape(idx,2) = s*shape_ox(i)*shape_oy(j)*shape_cz(k);
07378          }
07379 }
07380 
07381 void RT_HexahedronElement::CalcDivShape(const IntegrationPoint &ip,
07382                                         Vector &divshape) const
07383 {
07384    const int pp1 = Order;
07385 
07386 #ifdef MFEM_USE_OPENMP
07387    Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
07388    Vector shape_cz(pp1 + 1), shape_oz(pp1);
07389    Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1), dshape_cz(pp1 + 1);
07390 #endif
07391 
07392    cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
07393    obasis1d.Eval(ip.x, shape_ox);
07394    cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
07395    obasis1d.Eval(ip.y, shape_oy);
07396    cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
07397    obasis1d.Eval(ip.z, shape_oz);
07398 
07399    int o = 0;
07400    // x-components
07401    for (int k = 0; k < pp1; k++)
07402       for (int j = 0; j < pp1; j++)
07403          for (int i = 0; i <= pp1; i++)
07404          {
07405             int idx, s;
07406             if ((idx = dof_map[o++]) < 0)
07407                idx = -1 - idx, s = -1;
07408             else
07409                s = +1;
07410             divshape(idx) = s*dshape_cx(i)*shape_oy(j)*shape_oz(k);
07411          }
07412    // y-components
07413    for (int k = 0; k < pp1; k++)
07414       for (int j = 0; j <= pp1; j++)
07415          for (int i = 0; i < pp1; i++)
07416          {
07417             int idx, s;
07418             if ((idx = dof_map[o++]) < 0)
07419                idx = -1 - idx, s = -1;
07420             else
07421                s = +1;
07422             divshape(idx) = s*shape_ox(i)*dshape_cy(j)*shape_oz(k);
07423          }
07424    // z-components
07425    for (int k = 0; k <= pp1; k++)
07426       for (int j = 0; j < pp1; j++)
07427          for (int i = 0; i < pp1; i++)
07428          {
07429             int idx, s;
07430             if ((idx = dof_map[o++]) < 0)
07431                idx = -1 - idx, s = -1;
07432             else
07433                s = +1;
07434             divshape(idx) = s*shape_ox(i)*shape_oy(j)*dshape_cz(k);
07435          }
07436 }
07437 
07438 
07439 const double RT_TriangleElement::nk[6] =
07440 { 0., -1., 1., 1., -1., 0. };
07441 
07442 const double RT_TriangleElement::c = 1./3.;
07443 
07444 RT_TriangleElement::RT_TriangleElement(const int p)
07445    : VectorFiniteElement(2, Geometry::TRIANGLE, (p + 1)*(p + 3), p + 1,
07446                          FunctionSpace::Pk), dof2nk(Dof), T(Dof)
07447 {
07448    const double *iop = (p > 0) ? poly1d.OpenPoints(p - 1) : NULL;
07449    const double *bop = poly1d.OpenPoints(p);
07450 
07451 #ifndef MFEM_USE_OPENMP
07452    shape_x.SetSize(p + 1);
07453    shape_y.SetSize(p + 1);
07454    shape_l.SetSize(p + 1);
07455    dshape_x.SetSize(p + 1);
07456    dshape_y.SetSize(p + 1);
07457    dshape_l.SetSize(p + 1);
07458    u.SetSize(Dof, Dim);
07459    divu.SetSize(Dof);
07460 #else
07461    Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
07462 #endif
07463 
07464    // edges
07465    int o = 0;
07466    for (int i = 0; i <= p; i++)  // (0,1)
07467    {
07468       Nodes.IntPoint(o).Set2(bop[i], 0.);
07469       dof2nk[o++] = 0;
07470    }
07471    for (int i = 0; i <= p; i++)  // (1,2)
07472    {
07473       Nodes.IntPoint(o).Set2(bop[p-i], bop[i]);
07474       dof2nk[o++] = 1;
07475    }
07476    for (int i = 0; i <= p; i++)  // (2,0)
07477    {
07478       Nodes.IntPoint(o).Set2(0., bop[p-i]);
07479       dof2nk[o++] = 2;
07480    }
07481 
07482    // interior
07483    for (int j = 0; j < p; j++)
07484       for (int i = 0; i + j < p; i++)
07485       {
07486          double w = iop[i] + iop[j] + iop[p-1-i-j];
07487          Nodes.IntPoint(o).Set2(iop[i]/w, iop[j]/w);
07488          dof2nk[o++] = 0;
07489          Nodes.IntPoint(o).Set2(iop[i]/w, iop[j]/w);
07490          dof2nk[o++] = 2;
07491       }
07492 
07493    for (int k = 0; k < Dof; k++)
07494    {
07495       const IntegrationPoint &ip = Nodes.IntPoint(k);
07496       poly1d.CalcBasis(p, ip.x, shape_x);
07497       poly1d.CalcBasis(p, ip.y, shape_y);
07498       poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
07499       const double *n_k = nk + 2*dof2nk[k];
07500 
07501       o = 0;
07502       for (int j = 0; j <= p; j++)
07503          for (int i = 0; i + j <= p; i++)
07504          {
07505             double s = shape_x(i)*shape_y(j)*shape_l(p-i-j);
07506             T(o++, k) = s*n_k[0];
07507             T(o++, k) = s*n_k[1];
07508          }
07509       for (int i = 0; i <= p; i++)
07510       {
07511          double s = shape_x(i)*shape_y(p-i);
07512          T(o++, k) = s*((ip.x - c)*n_k[0] + (ip.y - c)*n_k[1]);
07513       }
07514    }
07515 
07516    T.Invert();
07517    // cout << "RT_TriangleElement(" << p << ") : "; T.TestInversion();
07518 }
07519 
07520 void RT_TriangleElement::CalcVShape(const IntegrationPoint &ip,
07521                                     DenseMatrix &shape) const
07522 {
07523    const int p = Order - 1;
07524 
07525 #ifdef MFEM_USE_OPENMP
07526    Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
07527    DenseMatrix u(Dof, Dim);
07528 #endif
07529 
07530    poly1d.CalcBasis(p, ip.x, shape_x);
07531    poly1d.CalcBasis(p, ip.y, shape_y);
07532    poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
07533 
07534    int o = 0;
07535    for (int j = 0; j <= p; j++)
07536       for (int i = 0; i + j <= p; i++)
07537       {
07538          double s = shape_x(i)*shape_y(j)*shape_l(p-i-j);
07539          u(o,0) = s;  u(o,1) = 0;  o++;
07540          u(o,0) = 0;  u(o,1) = s;  o++;
07541       }
07542    for (int i = 0; i <= p; i++)
07543    {
07544       double s = shape_x(i)*shape_y(p-i);
07545       u(o,0) = (ip.x - c)*s;  u(o,1) = (ip.y - c)*s;  o++;
07546    }
07547 
07548    Mult(T, u, shape);
07549 }
07550 
07551 void RT_TriangleElement::CalcDivShape(const IntegrationPoint &ip,
07552                                       Vector &divshape) const
07553 {
07554    const int p = Order - 1;
07555 
07556 #ifdef MFEM_USE_OPENMP
07557    Vector shape_x(p + 1),  shape_y(p + 1),  shape_l(p + 1);
07558    Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
07559    Vector divu(Dof);
07560 #endif
07561 
07562    poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
07563    poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
07564    poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l);
07565 
07566    int o = 0;
07567    for (int j = 0; j <= p; j++)
07568       for (int i = 0; i + j <= p; i++)
07569       {
07570          int k = p - i - j;
07571          divu(o++) = (dshape_x(i)*shape_l(k) -
07572                       shape_x(i)*dshape_l(k))*shape_y(j);
07573          divu(o++) = (dshape_y(j)*shape_l(k) -
07574                       shape_y(j)*dshape_l(k))*shape_x(i);
07575       }
07576    for (int i = 0; i <= p; i++)
07577    {
07578       int j = p - i;
07579       divu(o++) = ((shape_x(i) + (ip.x - c)*dshape_x(i))*shape_y(j) +
07580                    (shape_y(j) + (ip.y - c)*dshape_y(j))*shape_x(i));
07581    }
07582 
07583    T.Mult(divu, divshape);
07584 }
07585 
07586 
07587 const double RT_TetrahedronElement::nk[12] =
07588 { 1,1,1,  -1,0,0,  0,-1,0,  0,0,-1 };
07589 // { .5,.5,.5, -.5,0,0, 0,-.5,0, 0,0,-.5}; // n_F |F|
07590 
07591 const double RT_TetrahedronElement::c = 1./4.;
07592 
07593 RT_TetrahedronElement::RT_TetrahedronElement(const int p)
07594    : VectorFiniteElement(3, Geometry::TETRAHEDRON, (p + 1)*(p + 2)*(p + 4)/2,
07595                          p + 1, FunctionSpace::Pk), dof2nk(Dof), T(Dof)
07596 {
07597    const double *iop = (p > 0) ? poly1d.OpenPoints(p - 1) : NULL;
07598    const double *bop = poly1d.OpenPoints(p);
07599 
07600 #ifndef MFEM_USE_OPENMP
07601    shape_x.SetSize(p + 1);
07602    shape_y.SetSize(p + 1);
07603    shape_z.SetSize(p + 1);
07604    shape_l.SetSize(p + 1);
07605    dshape_x.SetSize(p + 1);
07606    dshape_y.SetSize(p + 1);
07607    dshape_z.SetSize(p + 1);
07608    dshape_l.SetSize(p + 1);
07609    u.SetSize(Dof, Dim);
07610    divu.SetSize(Dof);
07611 #else
07612    Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
07613 #endif
07614 
07615    int o = 0;
07616    // faces (see Mesh::GenerateFaces in mesh/mesh.cpp,
07617    //        the constructor of H1_TetrahedronElement)
07618    for (int j = 0; j <= p; j++)
07619       for (int i = 0; i + j <= p; i++)  // (1,2,3)
07620       {
07621          double w = bop[i] + bop[j] + bop[p-i-j];
07622          Nodes.IntPoint(o).Set3(bop[p-i-j]/w, bop[i]/w, bop[j]/w);
07623          dof2nk[o++] = 0;
07624       }
07625    for (int j = 0; j <= p; j++)
07626       for (int i = 0; i + j <= p; i++)  // (0,3,2)
07627       {
07628          double w = bop[i] + bop[j] + bop[p-i-j];
07629          Nodes.IntPoint(o).Set3(0., bop[j]/w, bop[i]/w);
07630          dof2nk[o++] = 1;
07631       }
07632    for (int j = 0; j <= p; j++)
07633       for (int i = 0; i + j <= p; i++)  // (0,1,3)
07634       {
07635          double w = bop[i] + bop[j] + bop[p-i-j];
07636          Nodes.IntPoint(o).Set3(bop[i]/w, 0., bop[j]/w);
07637          dof2nk[o++] = 2;
07638       }
07639    for (int j = 0; j <= p; j++)
07640       for (int i = 0; i + j <= p; i++)  // (0,2,1)
07641       {
07642          double w = bop[i] + bop[j] + bop[p-i-j];
07643          Nodes.IntPoint(o).Set3(bop[j]/w, bop[i]/w, 0.);
07644          dof2nk[o++] = 3;
07645       }
07646 
07647    // interior
07648    for (int k = 0; k < p; k++)
07649       for (int j = 0; j + k < p; j++)
07650          for (int i = 0; i + j + k < p; i++)
07651          {
07652             double w = iop[i] + iop[j] + iop[k] + iop[p-1-i-j-k];
07653             Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
07654             dof2nk[o++] = 1;
07655             Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
07656             dof2nk[o++] = 2;
07657             Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
07658             dof2nk[o++] = 3;
07659          }
07660 
07661    for (int m = 0; m < Dof; m++)
07662    {
07663       const IntegrationPoint &ip = Nodes.IntPoint(m);
07664       poly1d.CalcBasis(p, ip.x, shape_x);
07665       poly1d.CalcBasis(p, ip.y, shape_y);
07666       poly1d.CalcBasis(p, ip.z, shape_z);
07667       poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
07668       const double *nm = nk + 3*dof2nk[m];
07669 
07670       o = 0;
07671       for (int k = 0; k <= p; k++)
07672          for (int j = 0; j + k <= p; j++)
07673             for (int i = 0; i + j + k <= p; i++)
07674             {
07675                double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
07676                T(o++, m) = s * nm[0];
07677                T(o++, m) = s * nm[1];
07678                T(o++, m) = s * nm[2];
07679             }
07680       for (int j = 0; j <= p; j++)
07681          for (int i = 0; i + j <= p; i++)
07682          {
07683             double s = shape_x(i)*shape_y(j)*shape_z(p-i-j);
07684             T(o++, m) = s*((ip.x - c)*nm[0] + (ip.y - c)*nm[1] +
07685                            (ip.z - c)*nm[2]);
07686          }
07687    }
07688 
07689    T.Invert();
07690    // cout << "RT_TetrahedronElement(" << p << ") : "; T.TestInversion();
07691 }
07692 
07693 void RT_TetrahedronElement::CalcVShape(const IntegrationPoint &ip,
07694                                        DenseMatrix &shape) const
07695 {
07696    const int p = Order - 1;
07697 
07698 #ifdef MFEM_USE_OPENMP
07699    Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
07700    DenseMatrix u(Dof, Dim);
07701 #endif
07702 
07703    poly1d.CalcBasis(p, ip.x, shape_x);
07704    poly1d.CalcBasis(p, ip.y, shape_y);
07705    poly1d.CalcBasis(p, ip.z, shape_z);
07706    poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
07707 
07708    int o = 0;
07709    for (int k = 0; k <= p; k++)
07710       for (int j = 0; j + k <= p; j++)
07711          for (int i = 0; i + j + k <= p; i++)
07712          {
07713             double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
07714             u(o,0) = s;  u(o,1) = 0;  u(o,2) = 0;  o++;
07715             u(o,0) = 0;  u(o,1) = s;  u(o,2) = 0;  o++;
07716             u(o,0) = 0;  u(o,1) = 0;  u(o,2) = s;  o++;
07717          }
07718    for (int j = 0; j <= p; j++)
07719       for (int i = 0; i + j <= p; i++)
07720       {
07721          double s = shape_x(i)*shape_y(j)*shape_z(p-i-j);
07722          u(o,0) = (ip.x - c)*s;  u(o,1) = (ip.y - c)*s;  u(o,2) = (ip.z - c)*s;
07723          o++;
07724       }
07725 
07726    Mult(T, u, shape);
07727 }
07728 
07729 void RT_TetrahedronElement::CalcDivShape(const IntegrationPoint &ip,
07730                                          Vector &divshape) const
07731 {
07732    const int p = Order - 1;
07733 
07734 #ifdef MFEM_USE_OPENMP
07735    Vector shape_x(p + 1),  shape_y(p + 1),  shape_z(p + 1),  shape_l(p + 1);
07736    Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
07737    Vector divu(Dof);
07738 #endif
07739 
07740    poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
07741    poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
07742    poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
07743    poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
07744 
07745    int o = 0;
07746    for (int k = 0; k <= p; k++)
07747       for (int j = 0; j + k <= p; j++)
07748          for (int i = 0; i + j + k <= p; i++)
07749          {
07750             int l = p - i - j - k;
07751             divu(o++) = (dshape_x(i)*shape_l(l) -
07752                          shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k);
07753             divu(o++) = (dshape_y(j)*shape_l(l) -
07754                          shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k);
07755             divu(o++) = (dshape_z(k)*shape_l(l) -
07756                          shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j);
07757          }
07758    for (int j = 0; j <= p; j++)
07759       for (int i = 0; i + j <= p; i++)
07760       {
07761          int k = p - i - j;
07762          divu(o++) =
07763             (shape_x(i) + (ip.x - c)*dshape_x(i))*shape_y(j)*shape_z(k) +
07764             (shape_y(j) + (ip.y - c)*dshape_y(j))*shape_x(i)*shape_z(k) +
07765             (shape_z(k) + (ip.z - c)*dshape_z(k))*shape_x(i)*shape_y(j);
07766       }
07767 
07768    T.Mult(divu, divshape);
07769 }
07770 
07771 
07772 const double ND_HexahedronElement::tk[18] =
07773 { 1.,0.,0.,  0.,1.,0.,  0.,0.,1., -1.,0.,0.,  0.,-1.,0.,  0.,0.,-1. };
07774 
07775 ND_HexahedronElement::ND_HexahedronElement(const int p)
07776    : VectorFiniteElement(3, Geometry::CUBE, 3*p*(p + 1)*(p + 1), p,
07777                          FunctionSpace::Qk),
07778      cbasis1d(poly1d.ClosedBasis(p)), obasis1d(poly1d.OpenBasis(p - 1)),
07779      dof_map(Dof), dof2tk(Dof)
07780 {
07781    const double *cp = poly1d.ClosedPoints(p);
07782    const double *op = poly1d.OpenPoints(p - 1);
07783    const int dof3 = Dof/3;
07784 
07785 #ifndef MFEM_USE_OPENMP
07786    shape_cx.SetSize(p + 1);
07787    shape_ox.SetSize(p);
07788    shape_cy.SetSize(p + 1);
07789    shape_oy.SetSize(p);
07790    shape_cz.SetSize(p + 1);
07791    shape_oz.SetSize(p);
07792    dshape_cx.SetSize(p + 1);
07793    dshape_cy.SetSize(p + 1);
07794    dshape_cz.SetSize(p + 1);
07795 #endif
07796 
07797    // edges
07798    int o = 0;
07799    for (int i = 0; i < p; i++)  // (0,1)
07800       dof_map[0*dof3 + i + (0 + 0*(p + 1))*p] = o++;
07801    for (int i = 0; i < p; i++)  // (1,2)
07802       dof_map[1*dof3 + p + (i + 0*p)*(p + 1)] = o++;
07803    for (int i = 0; i < p; i++)  // (3,2)
07804       dof_map[0*dof3 + i + (p + 0*(p + 1))*p] = o++;
07805    for (int i = 0; i < p; i++)  // (0,3)
07806       dof_map[1*dof3 + 0 + (i + 0*p)*(p + 1)] = o++;
07807    for (int i = 0; i < p; i++)  // (4,5)
07808       dof_map[0*dof3 + i + (0 + p*(p + 1))*p] = o++;
07809    for (int i = 0; i < p; i++)  // (5,6)
07810       dof_map[1*dof3 + p + (i + p*p)*(p + 1)] = o++;
07811    for (int i = 0; i < p; i++)  // (7,6)
07812       dof_map[0*dof3 + i + (p + p*(p + 1))*p] = o++;
07813    for (int i = 0; i < p; i++)  // (4,7)
07814       dof_map[1*dof3 + 0 + (i + p*p)*(p + 1)] = o++;
07815    for (int i = 0; i < p; i++)  // (0,4)
07816       dof_map[2*dof3 + 0 + (0 + i*(p + 1))*(p + 1)] = o++;
07817    for (int i = 0; i < p; i++)  // (1,5)
07818       dof_map[2*dof3 + p + (0 + i*(p + 1))*(p + 1)] = o++;
07819    for (int i = 0; i < p; i++)  // (2,6)
07820       dof_map[2*dof3 + p + (p + i*(p + 1))*(p + 1)] = o++;
07821    for (int i = 0; i < p; i++)  // (3,7)
07822       dof_map[2*dof3 + 0 + (p + i*(p + 1))*(p + 1)] = o++;
07823 
07824    // faces
07825    // (3,2,1,0) -- bottom
07826    for (int j = 1; j < p; j++) // x - components
07827       for (int i = 0; i < p; i++)
07828          dof_map[0*dof3 + i + ((p - j) + 0*(p + 1))*p] = o++;
07829    for (int j = 0; j < p; j++) // y - components
07830       for (int i = 1; i < p; i++)
07831          dof_map[1*dof3 + i + ((p - 1 - j) + 0*p)*(p + 1)] = -1 - (o++);
07832    // (0,1,5,4) -- front
07833    for (int k = 1; k < p; k++) // x - components
07834       for (int i = 0; i < p; i++)
07835          dof_map[0*dof3 + i + (0 + k*(p + 1))*p] = o++;
07836    for (int k = 0; k < p; k++) // z - components
07837       for (int i = 1; i < p; i++ )
07838          dof_map[2*dof3 + i + (0 + k*(p + 1))*(p + 1)] = o++;
07839    // (1,2,6,5) -- right
07840    for (int k = 1; k < p; k++) // y - components
07841       for (int j = 0; j < p; j++)
07842          dof_map[1*dof3 + p + (j + k*p)*(p + 1)] = o++;
07843    for (int k = 0; k < p; k++) // z - components
07844       for (int j = 1; j < p; j++)
07845          dof_map[2*dof3 + p + (j + k*(p + 1))*(p + 1)] = o++;
07846    // (2,3,7,6) -- back
07847    for (int k = 1; k < p; k++) // x - components
07848       for (int i = 0; i < p; i++)
07849          dof_map[0*dof3 + (p - 1 - i) + (p + k*(p + 1))*p] = -1 - (o++);
07850    for (int k = 0; k < p; k++) // z - components
07851       for (int i = 1; i < p; i++)
07852          dof_map[2*dof3 + (p - i) + (p + k*(p + 1))*(p + 1)] = o++;
07853    // (3,0,4,7) -- left
07854    for (int k = 1; k < p; k++) // y - components
07855       for (int j = 0; j < p; j++)
07856          dof_map[1*dof3 + 0 + ((p - 1 - j) + k*p)*(p + 1)] = -1 - (o++);
07857    for (int k = 0; k < p; k++) // z - components
07858       for (int j = 1; j < p; j++)
07859          dof_map[2*dof3 + 0 + ((p - j) + k*(p + 1))*(p + 1)] = o++;
07860    // (4,5,6,7) -- top
07861    for (int j = 1; j < p; j++) // x - components
07862       for (int i = 0; i < p; i++)
07863          dof_map[0*dof3 + i + (j + p*(p + 1))*p] = o++;
07864    for (int j = 0; j < p; j++) // y - components
07865       for (int i = 1; i < p; i++)
07866          dof_map[1*dof3 + i + (j + p*p)*(p + 1)] = o++;
07867 
07868    // interior
07869    // x-components
07870    for (int k = 1; k < p; k++)
07871       for (int j = 1; j < p; j++)
07872          for (int i = 0; i < p; i++)
07873             dof_map[0*dof3 + i + (j + k*(p + 1))*p] = o++;
07874    // y-components
07875    for (int k = 1; k < p; k++)
07876       for (int j = 0; j < p; j++)
07877          for (int i = 1; i < p; i++)
07878             dof_map[1*dof3 + i + (j + k*p)*(p + 1)] = o++;
07879    // z-components
07880    for (int k = 0; k < p; k++)
07881       for (int j = 1; j < p; j++)
07882          for (int i = 1; i < p; i++)
07883             dof_map[2*dof3 + i + (j + k*(p + 1))*(p + 1)] = o++;
07884 
07885    // set dof2tk and Nodes
07886    o = 0;
07887    // x-components
07888    for (int k = 0; k <= p; k++)
07889       for (int j = 0; j <= p; j++)
07890          for (int i = 0; i < p; i++)
07891          {
07892             int idx;
07893             if ((idx = dof_map[o++]) < 0)
07894                dof2tk[idx = -1 - idx] = 3;
07895             else
07896                dof2tk[idx] = 0;
07897             Nodes.IntPoint(idx).Set3(op[i], cp[j], cp[k]);
07898          }
07899    // y-components
07900    for (int k = 0; k <= p; k++)
07901       for (int j = 0; j < p; j++)
07902          for (int i = 0; i <= p; i++)
07903          {
07904             int idx;
07905             if ((idx = dof_map[o++]) < 0)
07906                dof2tk[idx = -1 - idx] = 4;
07907             else
07908                dof2tk[idx] = 1;
07909             Nodes.IntPoint(idx).Set3(cp[i], op[j], cp[k]);
07910          }
07911    // z-components
07912    for (int k = 0; k < p; k++)
07913       for (int j = 0; j <= p; j++)
07914          for (int i = 0; i <= p; i++)
07915          {
07916             int idx;
07917             if ((idx = dof_map[o++]) < 0)
07918                dof2tk[idx = -1 - idx] = 5;
07919             else
07920                dof2tk[idx] = 2;
07921             Nodes.IntPoint(idx).Set3(cp[i], cp[j], op[k]);
07922          }
07923 }
07924 
07925 void ND_HexahedronElement::CalcVShape(const IntegrationPoint &ip,
07926                                       DenseMatrix &shape) const
07927 {
07928    const int p = Order;
07929 
07930 #ifdef MFEM_USE_OPENMP
07931    Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
07932    Vector shape_cz(p + 1), shape_oz(p);
07933 #endif
07934 
07935    cbasis1d.Eval(ip.x, shape_cx);
07936    obasis1d.Eval(ip.x, shape_ox);
07937    cbasis1d.Eval(ip.y, shape_cy);
07938    obasis1d.Eval(ip.y, shape_oy);
07939    cbasis1d.Eval(ip.z, shape_cz);
07940    obasis1d.Eval(ip.z, shape_oz);
07941 
07942    int o = 0;
07943    // x-components
07944    for (int k = 0; k <= p; k++)
07945       for (int j = 0; j <= p; j++)
07946          for (int i = 0; i < p; i++)
07947          {
07948             int idx, s;
07949             if ((idx = dof_map[o++]) < 0)
07950                idx = -1 - idx, s = -1;
07951             else
07952                s = +1;
07953             shape(idx,0) = s*shape_ox(i)*shape_cy(j)*shape_cz(k);
07954             shape(idx,1) = 0.;
07955             shape(idx,2) = 0.;
07956          }
07957    // y-components
07958    for (int k = 0; k <= p; k++)
07959       for (int j = 0; j < p; j++)
07960          for (int i = 0; i <= p; i++)
07961          {
07962             int idx, s;
07963             if ((idx = dof_map[o++]) < 0)
07964                idx = -1 - idx, s = -1;
07965             else
07966                s = +1;
07967             shape(idx,0) = 0.;
07968             shape(idx,1) = s*shape_cx(i)*shape_oy(j)*shape_cz(k);
07969             shape(idx,2) = 0.;
07970          }
07971    // z-components
07972    for (int k = 0; k < p; k++)
07973       for (int j = 0; j <= p; j++)
07974          for (int i = 0; i <= p; i++)
07975          {
07976             int idx, s;
07977             if ((idx = dof_map[o++]) < 0)
07978                idx = -1 - idx, s = -1;
07979             else
07980                s = +1;
07981             shape(idx,0) = 0.;
07982             shape(idx,1) = 0.;
07983             shape(idx,2) = s*shape_cx(i)*shape_cy(j)*shape_oz(k);
07984          }
07985 }
07986 
07987 void ND_HexahedronElement::CalcCurlShape(const IntegrationPoint &ip,
07988                                          DenseMatrix &curl_shape) const
07989 {
07990    const int p = Order;
07991 
07992 #ifdef MFEM_USE_OPENMP
07993    Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
07994    Vector shape_cz(p + 1), shape_oz(p);
07995    Vector dshape_cx(p + 1), dshape_cy(p + 1), dshape_cz(p + 1);
07996 #endif
07997 
07998    cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
07999    obasis1d.Eval(ip.x, shape_ox);
08000    cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
08001    obasis1d.Eval(ip.y, shape_oy);
08002    cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
08003    obasis1d.Eval(ip.z, shape_oz);
08004 
08005    int o = 0;
08006    // x-components
08007    for (int k = 0; k <= p; k++)
08008       for (int j = 0; j <= p; j++)
08009          for (int i = 0; i < p; i++)
08010          {
08011             int idx, s;
08012             if ((idx = dof_map[o++]) < 0)
08013                idx = -1 - idx, s = -1;
08014             else
08015                s = +1;
08016             curl_shape(idx,0) = 0.;
08017             curl_shape(idx,1) =  s*shape_ox(i)* shape_cy(j)*dshape_cz(k);
08018             curl_shape(idx,2) = -s*shape_ox(i)*dshape_cy(j)* shape_cz(k);
08019          }
08020    // y-components
08021    for (int k = 0; k <= p; k++)
08022       for (int j = 0; j < p; j++)
08023          for (int i = 0; i <= p; i++)
08024          {
08025             int idx, s;
08026             if ((idx = dof_map[o++]) < 0)
08027                idx = -1 - idx, s = -1;
08028             else
08029                s = +1;
08030             curl_shape(idx,0) = -s* shape_cx(i)*shape_oy(j)*dshape_cz(k);
08031             curl_shape(idx,1) = 0.;
08032             curl_shape(idx,2) =  s*dshape_cx(i)*shape_oy(j)* shape_cz(k);
08033          }
08034    // z-components
08035    for (int k = 0; k < p; k++)
08036       for (int j = 0; j <= p; j++)
08037          for (int i = 0; i <= p; i++)
08038          {
08039             int idx, s;
08040             if ((idx = dof_map[o++]) < 0)
08041                idx = -1 - idx, s = -1;
08042             else
08043                s = +1;
08044             curl_shape(idx,0) =   s* shape_cx(i)*dshape_cy(j)*shape_oz(k);
08045             curl_shape(idx,1) =  -s*dshape_cx(i)* shape_cy(j)*shape_oz(k);
08046             curl_shape(idx,2) = 0.;
08047          }
08048 }
08049 
08050 
08051 const double ND_QuadrilateralElement::tk[8] =
08052 { 1.,0.,  0.,1., -1.,0., 0.,-1. };
08053 
08054 ND_QuadrilateralElement::ND_QuadrilateralElement(const int p)
08055    : VectorFiniteElement(2, Geometry::SQUARE, 2*p*(p + 1), p,
08056                          FunctionSpace::Qk),
08057      cbasis1d(poly1d.ClosedBasis(p)), obasis1d(poly1d.OpenBasis(p - 1)),
08058      dof_map(Dof), dof2tk(Dof)
08059 {
08060    const double *cp = poly1d.ClosedPoints(p);
08061    const double *op = poly1d.OpenPoints(p - 1);
08062    const int dof2 = Dof/2;
08063 
08064 #ifndef MFEM_USE_OPENMP
08065    shape_cx.SetSize(p + 1);
08066    shape_ox.SetSize(p);
08067    shape_cy.SetSize(p + 1);
08068    shape_oy.SetSize(p);
08069    dshape_cx.SetSize(p + 1);
08070    dshape_cy.SetSize(p + 1);
08071 #endif
08072 
08073    // edges
08074    int o = 0;
08075    for (int i = 0; i < p; i++)  // (0,1)
08076       dof_map[0*dof2 + i + 0*p] = o++;
08077    for (int j = 0; j < p; j++)  // (1,2)
08078       dof_map[1*dof2 + p + j*(p + 1)] = o++;
08079    for (int i = 0; i < p; i++)  // (2,3)
08080       dof_map[0*dof2 + (p - 1 - i) + p*p] = -1 - (o++);
08081    for (int j = 0; j < p; j++)  // (3,0)
08082       dof_map[1*dof2 + 0 + (p - 1 - j)*(p + 1)] = -1 - (o++);
08083 
08084    // interior
08085    // x-components
08086    for (int j = 1; j < p; j++)
08087       for (int i = 0; i < p; i++)
08088          dof_map[0*dof2 + i + j*p] = o++;
08089    // y-components
08090    for (int j = 0; j < p; j++)
08091       for (int i = 1; i < p; i++)
08092          dof_map[1*dof2 + i + j*(p + 1)] = o++;
08093 
08094    // set dof2tk and Nodes
08095    o = 0;
08096    // x-components
08097    for (int j = 0; j <= p; j++)
08098       for (int i = 0; i < p; i++)
08099       {
08100          int idx;
08101          if ((idx = dof_map[o++]) < 0)
08102             dof2tk[idx = -1 - idx] = 2;
08103          else
08104             dof2tk[idx] = 0;
08105          Nodes.IntPoint(idx).Set2(op[i], cp[j]);
08106       }
08107    // y-components
08108    for (int j = 0; j < p; j++)
08109       for (int i = 0; i <= p; i++)
08110       {
08111          int idx;
08112          if ((idx = dof_map[o++]) < 0)
08113             dof2tk[idx = -1 - idx] = 3;
08114          else
08115             dof2tk[idx] = 1;
08116          Nodes.IntPoint(idx).Set2(cp[i], op[j]);
08117       }
08118 }
08119 
08120 void ND_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip,
08121                                          DenseMatrix &shape) const
08122 {
08123    const int p = Order;
08124 
08125 #ifdef MFEM_USE_OPENMP
08126    Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
08127 #endif
08128 
08129    cbasis1d.Eval(ip.x, shape_cx);
08130    obasis1d.Eval(ip.x, shape_ox);
08131    cbasis1d.Eval(ip.y, shape_cy);
08132    obasis1d.Eval(ip.y, shape_oy);
08133 
08134    int o = 0;
08135    // x-components
08136    for (int j = 0; j <= p; j++)
08137       for (int i = 0; i < p; i++)
08138       {
08139          int idx, s;
08140          if ((idx = dof_map[o++]) < 0)
08141             idx = -1 - idx, s = -1;
08142          else
08143             s = +1;
08144          shape(idx,0) = s*shape_ox(i)*shape_cy(j);
08145          shape(idx,1) = 0.;
08146       }
08147    // y-components
08148    for (int j = 0; j < p; j++)
08149       for (int i = 0; i <= p; i++)
08150       {
08151          int idx, s;
08152          if ((idx = dof_map[o++]) < 0)
08153             idx = -1 - idx, s = -1;
08154          else
08155             s = +1;
08156          shape(idx,0) = 0.;
08157          shape(idx,1) = s*shape_cx(i)*shape_oy(j);
08158       }
08159 }
08160 
08161 void ND_QuadrilateralElement::CalcCurlShape(const IntegrationPoint &ip,
08162                                             DenseMatrix &curl_shape) const
08163 {
08164    mfem_error("ND_QuadrilateralElement::CalcCurlShape");
08165 }
08166 
08167 
08168 const double ND_TetrahedronElement::tk[18] =
08169 { 1.,0.,0.,  0.,1.,0.,  0.,0.,1.,  -1.,1.,0.,  -1.,0.,1.,  0.,-1.,1. };
08170 
08171 const double ND_TetrahedronElement::c = 1./4.;
08172 
08173 ND_TetrahedronElement::ND_TetrahedronElement(const int p)
08174    : VectorFiniteElement(3, Geometry::TETRAHEDRON, p*(p + 2)*(p + 3)/2, p,
08175                          FunctionSpace::Pk), dof2tk(Dof), T(Dof)
08176 {
08177    const double *eop = poly1d.OpenPoints(p - 1);
08178    const double *fop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL;
08179    const double *iop = (p > 2) ? poly1d.OpenPoints(p - 3) : NULL;
08180 
08181    const int pm1 = p - 1, pm2 = p - 2, pm3 = p - 3;
08182 
08183 #ifndef MFEM_USE_OPENMP
08184    shape_x.SetSize(p);
08185    shape_y.SetSize(p);
08186    shape_z.SetSize(p);
08187    shape_l.SetSize(p);
08188    dshape_x.SetSize(p);
08189    dshape_y.SetSize(p);
08190    dshape_z.SetSize(p);
08191    dshape_l.SetSize(p);
08192    u.SetSize(Dof, Dim);
08193 #else
08194    Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
08195 #endif
08196 
08197    int o = 0;
08198    // edges
08199    for (int i = 0; i < p; i++) // (0,1)
08200    {
08201       Nodes.IntPoint(o).Set3(eop[i], 0., 0.);
08202       dof2tk[o++] = 0;
08203    }
08204    for (int i = 0; i < p; i++) // (0,2)
08205    {
08206       Nodes.IntPoint(o).Set3(0., eop[i], 0.);
08207       dof2tk[o++] = 1;
08208    }
08209    for (int i = 0; i < p; i++) // (0,3)
08210    {
08211       Nodes.IntPoint(o).Set3(0., 0., eop[i]);
08212       dof2tk[o++] = 2;
08213    }
08214    for (int i = 0; i < p; i++) // (1,2)
08215    {
08216       Nodes.IntPoint(o).Set3(eop[pm1-i], eop[i], 0.);
08217       dof2tk[o++] = 3;
08218    }
08219    for (int i = 0; i < p; i++) // (1,3)
08220    {
08221       Nodes.IntPoint(o).Set3(eop[pm1-i], 0., eop[i]);
08222       dof2tk[o++] = 4;
08223    }
08224    for (int i = 0; i < p; i++) // (2,3)
08225    {
08226       Nodes.IntPoint(o).Set3(0., eop[pm1-i], eop[i]);
08227       dof2tk[o++] = 5;
08228    }
08229 
08230    // faces
08231    for (int j = 0; j <= pm2; j++)  // (1,2,3)
08232       for (int i = 0; i + j <= pm2; i++)
08233       {
08234          double w = fop[i] + fop[j] + fop[pm2-i-j];
08235          Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w);
08236          dof2tk[o++] = 3;
08237          Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w);
08238          dof2tk[o++] = 4;
08239       }
08240    for (int j = 0; j <= pm2; j++)  // (0,3,2)
08241       for (int i = 0; i + j <= pm2; i++)
08242       {
08243          double w = fop[i] + fop[j] + fop[pm2-i-j];
08244          Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w);
08245          dof2tk[o++] = 2;
08246          Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w);
08247          dof2tk[o++] = 1;
08248       }
08249    for (int j = 0; j <= pm2; j++)  // (0,1,3)
08250       for (int i = 0; i + j <= pm2; i++)
08251       {
08252          double w = fop[i] + fop[j] + fop[pm2-i-j];
08253          Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w);
08254          dof2tk[o++] = 0;
08255          Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w);
08256          dof2tk[o++] = 2;
08257       }
08258    for (int j = 0; j <= pm2; j++)  // (0,2,1)
08259       for (int i = 0; i + j <= pm2; i++)
08260       {
08261          double w = fop[i] + fop[j] + fop[pm2-i-j];
08262          Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.);
08263          dof2tk[o++] = 1;
08264          Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.);
08265          dof2tk[o++] = 0;
08266       }
08267 
08268    // interior
08269    for (int k = 0; k <= pm3; k++)
08270       for (int j = 0; j + k <= pm3; j++)
08271          for (int i = 0; i + j + k <= pm3; i++)
08272          {
08273             double w = iop[i] + iop[j] + iop[k] + iop[pm3-i-j-k];
08274             Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
08275             dof2tk[o++] = 0;
08276             Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
08277             dof2tk[o++] = 1;
08278             Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
08279             dof2tk[o++] = 2;
08280          }
08281 
08282    for (int m = 0; m < Dof; m++)
08283    {
08284       const IntegrationPoint &ip = Nodes.IntPoint(m);
08285       const double *tm = tk + 3*dof2tk[m];
08286       o = 0;
08287 
08288       poly1d.CalcBasis(pm1, ip.x, shape_x);
08289       poly1d.CalcBasis(pm1, ip.y, shape_y);
08290       poly1d.CalcBasis(pm1, ip.z, shape_z);
08291       poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l);
08292 
08293       for (int k = 0; k <= pm1; k++)
08294          for (int j = 0; j + k <= pm1; j++)
08295             for (int i = 0; i + j + k <= pm1; i++)
08296             {
08297                double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k);
08298                T(o++, m) = s * tm[0];
08299                T(o++, m) = s * tm[1];
08300                T(o++, m) = s * tm[2];
08301             }
08302       for (int k = 0; k <= pm1; k++)
08303          for (int j = 0; j + k <= pm1; j++)
08304          {
08305             double s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k);
08306             T(o++, m) = s*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]);
08307             T(o++, m) = s*((ip.z - c)*tm[0] - (ip.x - c)*tm[2]);
08308          }
08309       for (int k = 0; k <= pm1; k++)
08310       {
08311          T(o++, m) =
08312             shape_y(pm1-k)*shape_z(k)*((ip.z - c)*tm[1] - (ip.y - c)*tm[2]);
08313       }
08314    }
08315 
08316    T.Invert();
08317    // cout << "ND_TetrahedronElement(" << p << ") : "; T.TestInversion();
08318 }
08319 
08320 void ND_TetrahedronElement::CalcVShape(const IntegrationPoint &ip,
08321                                        DenseMatrix &shape) const
08322 {
08323    const int pm1 = Order - 1;
08324 
08325 #ifdef MFEM_USE_OPENMP
08326    const int p = Order;
08327    Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
08328    DenseMatrix u(Dof, Dim);
08329 #endif
08330 
08331    poly1d.CalcBasis(pm1, ip.x, shape_x);
08332    poly1d.CalcBasis(pm1, ip.y, shape_y);
08333    poly1d.CalcBasis(pm1, ip.z, shape_z);
08334    poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l);
08335 
08336    int n = 0;
08337    for (int k = 0; k <= pm1; k++)
08338       for (int j = 0; j + k <= pm1; j++)
08339          for (int i = 0; i + j + k <= pm1; i++)
08340          {
08341             double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k);
08342             u(n,0) =  s;  u(n,1) = 0.;  u(n,2) = 0.;  n++;
08343             u(n,0) = 0.;  u(n,1) =  s;  u(n,2) = 0.;  n++;
08344             u(n,0) = 0.;  u(n,1) = 0.;  u(n,2) =  s;  n++;
08345          }
08346    for (int k = 0; k <= pm1; k++)
08347       for (int j = 0; j + k <= pm1; j++)
08348       {
08349          double s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k);
08350          u(n,0) = s*(ip.y - c);  u(n,1) = -s*(ip.x - c);  u(n,2) =  0.;  n++;
08351          u(n,0) = s*(ip.z - c);  u(n,1) =  0.;  u(n,2) = -s*(ip.x - c);  n++;
08352       }
08353    for (int k = 0; k <= pm1; k++)
08354    {
08355       double s = shape_y(pm1-k)*shape_z(k);
08356       u(n,0) = 0.;  u(n,1) = s*(ip.z - c);  u(n,2) = -s*(ip.y - c);  n++;
08357    }
08358 
08359    Mult(T, u, shape);
08360 }
08361 
08362 void ND_TetrahedronElement::CalcCurlShape(const IntegrationPoint &ip,
08363                                           DenseMatrix &curl_shape) const
08364 {
08365    const int pm1 = Order - 1;
08366 
08367 #ifdef MFEM_USE_OPENMP
08368    const int p = Order;
08369    Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
08370    Vector dshape_x(p), dshape_y(p), dshape_z(p), dshape_l(p);
08371    DenseMatrix u(Dof, Dim);
08372 #endif
08373 
08374    poly1d.CalcBasis(pm1, ip.x, shape_x, dshape_x);
08375    poly1d.CalcBasis(pm1, ip.y, shape_y, dshape_y);
08376    poly1d.CalcBasis(pm1, ip.z, shape_z, dshape_z);
08377    poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
08378 
08379    int n = 0;
08380    for (int k = 0; k <= pm1; k++)
08381       for (int j = 0; j + k <= pm1; j++)
08382          for (int i = 0; i + j + k <= pm1; i++)
08383          {
08384             int l = pm1-i-j-k;
08385             const double dx = (dshape_x(i)*shape_l(l) -
08386                                shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k);
08387             const double dy = (dshape_y(j)*shape_l(l) -
08388                                shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k);
08389             const double dz = (dshape_z(k)*shape_l(l) -
08390                                shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j);
08391 
08392             u(n,0) =  0.;  u(n,1) =  dz;  u(n,2) = -dy;  n++;
08393             u(n,0) = -dz;  u(n,1) =  0.;  u(n,2) =  dx;  n++;
08394             u(n,0) =  dy;  u(n,1) = -dx;  u(n,2) =  0.;  n++;
08395          }
08396    for (int k = 0; k <= pm1; k++)
08397       for (int j = 0; j + k <= pm1; j++)
08398       {
08399          int i = pm1 - j - k;
08400          // s = shape_x(i)*shape_y(j)*shape_z(k);
08401          // curl of s*(ip.y - c, -(ip.x - c), 0):
08402          u(n,0) =  shape_x(i)*(ip.x - c)*shape_y(j)*dshape_z(k);
08403          u(n,1) =  shape_x(i)*shape_y(j)*(ip.y - c)*dshape_z(k);
08404          u(n,2) =
08405             -((dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k) +
08406               (dshape_y(j)*(ip.y - c) + shape_y(j))*shape_x(i)*shape_z(k));
08407          n++;
08408          // curl of s*(ip.z - c, 0, -(ip.x - c)):
08409          u(n,0) = -shape_x(i)*(ip.x - c)*dshape_y(j)*shape_z(k);
08410          u(n,1) = (shape_x(i)*shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k)) +
08411                    (dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k));
08412          u(n,2) = -shape_x(i)*dshape_y(j)*shape_z(k)*(ip.z - c);
08413          n++;
08414       }
08415    for (int k = 0; k <= pm1; k++)
08416    {
08417       int j = pm1 - k;
08418       // curl of shape_y(j)*shape_z(k)*(0, ip.z - c, -(ip.y - c)):
08419       u(n,0) = -((dshape_y(j)*(ip.y - c) + shape_y(j))*shape_z(k) +
08420                  shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k)));
08421       u(n,1) = 0.;
08422       u(n,2) = 0.;  n++;
08423    }
08424 
08425    Mult(T, u, curl_shape);
08426 }
08427 
08428 
08429 const double ND_TriangleElement::tk[8] =
08430 { 1.,0.,  -1.,1.,  0.,-1.,  0.,1. };
08431 
08432 const double ND_TriangleElement::c = 1./3.;
08433 
08434 ND_TriangleElement::ND_TriangleElement(const int p)
08435    : VectorFiniteElement(2, Geometry::TRIANGLE, p*(p + 2), p,
08436                          FunctionSpace::Pk), dof2tk(Dof), T(Dof)
08437 {
08438    const double *eop = poly1d.OpenPoints(p - 1);
08439    const double *iop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL;
08440 
08441    const int pm1 = p - 1, pm2 = p - 2;
08442 
08443 #ifndef MFEM_USE_OPENMP
08444    shape_x.SetSize(p);
08445    shape_y.SetSize(p);
08446    shape_l.SetSize(p);
08447    dshape_x.SetSize(p);
08448    dshape_y.SetSize(p);
08449    dshape_l.SetSize(p);
08450    u.SetSize(Dof, Dim);
08451 #else
08452    Vector shape_x(p), shape_y(p), shape_l(p);
08453 #endif
08454 
08455    int n = 0;
08456    // edges
08457    for (int i = 0; i < p; i++) // (0,1)
08458    {
08459       Nodes.IntPoint(n).Set2(eop[i], 0.);
08460       dof2tk[n++] = 0;
08461    }
08462    for (int i = 0; i < p; i++) // (1,2)
08463    {
08464       Nodes.IntPoint(n).Set2(eop[pm1-i], eop[i]);
08465       dof2tk[n++] = 1;
08466    }
08467    for (int i = 0; i < p; i++) // (2,0)
08468    {
08469       Nodes.IntPoint(n).Set2(0., eop[pm1-i]);
08470       dof2tk[n++] = 2;
08471    }
08472 
08473    // interior
08474    for (int j = 0; j <= pm2; j++)
08475       for (int i = 0; i + j <= pm2; i++)
08476       {
08477          double w = iop[i] + iop[j] + iop[pm2-i-j];
08478          Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w);
08479          dof2tk[n++] = 0;
08480          Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w);
08481          dof2tk[n++] = 3;
08482       }
08483 
08484    for (int m = 0; m < Dof; m++)
08485    {
08486       const IntegrationPoint &ip = Nodes.IntPoint(m);
08487       const double *tm = tk + 2*dof2tk[m];
08488       n = 0;
08489 
08490       poly1d.CalcBasis(pm1, ip.x, shape_x);
08491       poly1d.CalcBasis(pm1, ip.y, shape_y);
08492       poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l);
08493 
08494       for (int j = 0; j <= pm1; j++)
08495          for (int i = 0; i + j <= pm1; i++)
08496          {
08497             double s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j);
08498             T(n++, m) = s * tm[0];
08499             T(n++, m) = s * tm[1];
08500          }
08501       for (int j = 0; j <= pm1; j++)
08502       {
08503          T(n++ ,m) =
08504             shape_x(pm1-j)*shape_y(j)*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]);
08505       }
08506    }
08507 
08508    T.Invert();
08509    // cout << "ND_TriangleElement(" << p << ") : "; T.TestInversion();
08510 }
08511 
08512 void ND_TriangleElement::CalcVShape(const IntegrationPoint &ip,
08513                                     DenseMatrix &shape) const
08514 {
08515    const int pm1 = Order - 1;
08516 
08517 #ifdef MFEM_USE_OPENMP
08518    const int p = Order;
08519    Vector shape_x(p), shape_y(p), shape_l(p);
08520    DenseMatrix u(Dof, Dim);
08521 #endif
08522 
08523    poly1d.CalcBasis(pm1, ip.x, shape_x);
08524    poly1d.CalcBasis(pm1, ip.y, shape_y);
08525    poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l);
08526 
08527    int n = 0;
08528    for (int j = 0; j <= pm1; j++)
08529       for (int i = 0; i + j <= pm1; i++)
08530       {
08531          double s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j);
08532          u(n,0) =  s;  u(n,1) = 0.;  n++;
08533          u(n,0) = 0.;  u(n,1) =  s;  n++;
08534       }
08535    for (int j = 0; j <= pm1; j++)
08536    {
08537       double s = shape_x(pm1-j)*shape_y(j);
08538       u(n,0) =  s*(ip.y - c);
08539       u(n,1) = -s*(ip.x - c);
08540    }
08541 
08542    Mult(T, u, shape);
08543 }
08544 
08545 void ND_TriangleElement::CalcCurlShape(const IntegrationPoint &ip,
08546                                        DenseMatrix &curl_shape) const
08547 {
08548    mfem_error("ND_TriangleElement::CalcCurlShape");
08549 }
08550 
08551 
08552 void NURBS1DFiniteElement::CalcShape(const IntegrationPoint &ip,
08553                                      Vector &shape) const
08554 {
08555    kv[0]->CalcShape(shape, ijk[0], ip.x);
08556 
08557    double sum = 0.0;
08558    for (int i = 0; i <= Order; i++)
08559       sum += (shape(i) *= weights(i));
08560 
08561    shape /= sum;
08562 }
08563 
08564 void NURBS1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
08565                                       DenseMatrix &dshape) const
08566 {
08567    Vector grad(dshape.Data(), Dof);
08568 
08569    kv[0]->CalcShape (shape_x, ijk[0], ip.x);
08570    kv[0]->CalcDShape(grad,    ijk[0], ip.x);
08571 
08572    double sum = 0.0, dsum = 0.0;
08573    for (int i = 0; i <= Order; i++)
08574    {
08575       sum  += (shape_x(i) *= weights(i));
08576       dsum += (   grad(i) *= weights(i));
08577    }
08578 
08579    sum = 1.0/sum;
08580    add(sum, grad, -dsum*sum*sum, shape_x, grad);
08581 }
08582 
08583 void NURBS2DFiniteElement::CalcShape(const IntegrationPoint &ip,
08584                                      Vector &shape) const
08585 {
08586    kv[0]->CalcShape(shape_x, ijk[0], ip.x);
08587    kv[1]->CalcShape(shape_y, ijk[1], ip.y);
08588 
08589    double sum = 0.0;
08590    for (int o = 0, j = 0; j <= Order; j++)
08591    {
08592       const double sy = shape_y(j);
08593       for (int i = 0; i <= Order; i++, o++)
08594       {
08595          sum += ( shape(o) = shape_x(i)*sy*weights(o) );
08596       }
08597    }
08598 
08599    shape /= sum;
08600 }
08601 
08602 void NURBS2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
08603                                       DenseMatrix &dshape) const
08604 {
08605    double sum, dsum[2];
08606 
08607    kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
08608    kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
08609 
08610    kv[0]->CalcDShape(dshape_x, ijk[0], ip.x);
08611    kv[1]->CalcDShape(dshape_y, ijk[1], ip.y);
08612 
08613    sum = dsum[0] = dsum[1] = 0.0;
08614    for (int o = 0, j = 0; j <= Order; j++)
08615    {
08616       const double sy = shape_y(j), dsy = dshape_y(j);
08617       for (int i = 0; i <= Order; i++, o++)
08618       {
08619          sum += ( u(o) = shape_x(i)*sy*weights(o) );
08620 
08621          dsum[0] += ( dshape(o,0) = dshape_x(i)*sy *weights(o) );
08622          dsum[1] += ( dshape(o,1) =  shape_x(i)*dsy*weights(o) );
08623       }
08624    }
08625 
08626    sum = 1.0/sum;
08627    dsum[0] *= sum*sum;
08628    dsum[1] *= sum*sum;
08629 
08630    for (int o = 0; o < Dof; o++)
08631    {
08632       dshape(o,0) = dshape(o,0)*sum - u(o)*dsum[0];
08633       dshape(o,1) = dshape(o,1)*sum - u(o)*dsum[1];
08634    }
08635 }
08636 
08637 void NURBS3DFiniteElement::CalcShape(const IntegrationPoint &ip,
08638                                      Vector &shape) const
08639 {
08640    kv[0]->CalcShape(shape_x, ijk[0], ip.x);
08641    kv[1]->CalcShape(shape_y, ijk[1], ip.y);
08642    kv[2]->CalcShape(shape_z, ijk[2], ip.z);
08643 
08644    double sum = 0.0;
08645    for (int o = 0, k = 0; k <= Order; k++)
08646    {
08647       const double sz = shape_z(k);
08648       for (int j = 0; j <= Order; j++)
08649       {
08650          const double sy_sz = shape_y(j)*sz;
08651          for (int i = 0; i <= Order; i++, o++)
08652          {
08653             sum += ( shape(o) = shape_x(i)*sy_sz*weights(o) );
08654          }
08655       }
08656    }
08657 
08658    shape /= sum;
08659 }
08660 
08661 void NURBS3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
08662                                       DenseMatrix &dshape) const
08663 {
08664    double sum, dsum[3];
08665 
08666    kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
08667    kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
08668    kv[2]->CalcShape ( shape_z, ijk[2], ip.z);
08669 
08670    kv[0]->CalcDShape(dshape_x, ijk[0], ip.x);
08671    kv[1]->CalcDShape(dshape_y, ijk[1], ip.y);
08672    kv[2]->CalcDShape(dshape_z, ijk[2], ip.z);
08673 
08674    sum = dsum[0] = dsum[1] = dsum[2] = 0.0;
08675    for (int o = 0, k = 0; k <= Order; k++)
08676    {
08677       const double sz = shape_z(k), dsz = dshape_z(k);
08678       for (int j = 0; j <= Order; j++)
08679       {
08680          const double  sy_sz  =  shape_y(j)* sz;
08681          const double dsy_sz  = dshape_y(j)* sz;
08682          const double  sy_dsz =  shape_y(j)*dsz;
08683          for (int i = 0; i <= Order; i++, o++)
08684          {
08685             sum += ( u(o) = shape_x(i)*sy_sz*weights(o) );
08686 
08687             dsum[0] += ( dshape(o,0) = dshape_x(i)* sy_sz *weights(o) );
08688             dsum[1] += ( dshape(o,1) =  shape_x(i)*dsy_sz *weights(o) );
08689             dsum[2] += ( dshape(o,2) =  shape_x(i)* sy_dsz*weights(o) );
08690          }
08691       }
08692    }
08693 
08694    sum = 1.0/sum;
08695    dsum[0] *= sum*sum;
08696    dsum[1] *= sum*sum;
08697    dsum[2] *= sum*sum;
08698 
08699    for (int o = 0; o < Dof; o++)
08700    {
08701       dshape(o,0) = dshape(o,0)*sum - u(o)*dsum[0];
08702       dshape(o,1) = dshape(o,1)*sum - u(o)*dsum[1];
08703       dshape(o,2) = dshape(o,2)*sum - u(o)*dsum[2];
08704    }
08705 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines