⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fe_hermite_shape_2d.c

📁 一个用来实现偏微分方程中网格的计算库
💻 C
字号:
// $Id: fe_hermite_shape_2D.C 2789 2008-04-13 02:24:40Z roystgnr $// The libMesh Finite Element Library.// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson  // This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.  // This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU// Lesser General Public License for more details.  // You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA// C++ inlcludes// Local includes#include "fe.h"#include "elem.h"#include "number_lookups.h"// Anonymous namespace for persistant variables.// This allows us to cache the global-to-local mapping transformation// FIXME: This should also screw up multithreading royallynamespace{  static unsigned int old_elem_id = libMesh::invalid_uint;  // Mapping functions - derivatives at each dofpt  std::vector<std::vector<Real> > dxdxi(2, std::vector<Real>(2, 0));#ifdef DEBUG  std::vector<Real> dxdeta(2), dydxi(2);#endif// Compute the static coefficients for an elementvoid hermite_compute_coefs(const Elem* elem){  // Coefficients are cached from old elements  if (elem->id() == old_elem_id)    return;  old_elem_id = elem->id();  const Order mapping_order        (elem->default_order());  const ElemType mapping_elem_type (elem->type());  const int n_mapping_shape_functions =    FE<2,LAGRANGE>::n_shape_functions(mapping_elem_type,				      mapping_order);  std::vector<Point> dofpt;  dofpt.push_back(Point(-1,-1));  dofpt.push_back(Point(1,1));  for (int p = 0; p != 2; ++p)    {      dxdxi[0][p] = 0;      dxdxi[1][p] = 0;#ifdef DEBUG      dxdeta[p] = 0;      dydxi[p] = 0;#endif      for (int i = 0; i != n_mapping_shape_functions; ++i)        {          const Real ddxi = FE<2,LAGRANGE>::shape_deriv             (mapping_elem_type, mapping_order, i, 0, dofpt[p]);          const Real ddeta = FE<2,LAGRANGE>::shape_deriv             (mapping_elem_type, mapping_order, i, 1, dofpt[p]);          dxdxi[0][p] += elem->point(i)(0) * ddxi;          dxdxi[1][p] += elem->point(i)(1) * ddeta;// dxdeta and dydxi should be 0!#ifdef DEBUG          dxdeta[p] += elem->point(i)(0) * ddeta;          dydxi[p] += elem->point(i)(1) * ddxi;#endif        }      // No singular elements!      libmesh_assert(dxdxi[0][p]);      libmesh_assert(dxdxi[1][p]);      // No non-rectilinear or non-axis-aligned elements!#ifdef DEBUG      libmesh_assert(std::abs(dxdeta[p]) < 1e-9);      libmesh_assert(std::abs(dydxi[p]) < 1e-9);#endif    }}Real hermite_bases_2D (std::vector<unsigned int> &bases1D,  const std::vector<std::vector<Real> > &dxdxi,  const Order &o,  unsigned int i){  bases1D.clear();  bases1D.resize(2,0);  Real coef = 1.0;  unsigned int e = o-3;  // Nodes  if (i < 16)    {      switch (i / 4)        {        case 0:          break;        case 1:          bases1D[0] = 1;          break;        case 2:          bases1D[0] = 1;          bases1D[1] = 1;          break;        case 3:          bases1D[1] = 1;          break;        }      unsigned int basisnum = i%4;      switch (basisnum)        {          case 0: // DoF = value at node            coef = 1.0;            break;          case 1: // DoF = x derivative at node            coef = dxdxi[0][bases1D[0]];            bases1D[0] += 2; break;          case 2: // DoF = y derivative at node            coef = dxdxi[1][bases1D[1]];            bases1D[1] += 2; break;          case 3: // DoF = xy derivative at node            coef = dxdxi[0][bases1D[0]] * dxdxi[1][bases1D[1]];            bases1D[0] += 2; bases1D[1] += 2; break;          default:            libmesh_error();        }    }  // Edges  else if (i < 16 + 4*2*e)    {      unsigned int basisnum = (i - 16) % (2*e);      switch ((i - 16) / (2*e))        {        case 0:          bases1D[0] = basisnum/2 + 4;          bases1D[1] = basisnum%2*2;          if (basisnum%2)            coef = dxdxi[1][0];          break;        case 1:          bases1D[0] = basisnum%2*2 + 1;          bases1D[1] = basisnum/2 + 4;          if (basisnum%2)            coef = dxdxi[0][1];          break;        case 2:          bases1D[0] = basisnum/2 + 4;          bases1D[1] = basisnum%2*2 + 1;          if (basisnum%2)            coef = dxdxi[1][1];          break;        case 3:          bases1D[0] = basisnum%2*2;          bases1D[1] = basisnum/2 + 4;          if (basisnum%2)            coef = dxdxi[0][0];          break;        default:          libmesh_error();        }    }  // Interior  else    {      unsigned int basisnum = i - 16 - 8*e;      bases1D[0] = square_number_row[basisnum]+4;      bases1D[1] = square_number_column[basisnum]+4;    }  // No singular elements  libmesh_assert(coef);  return coef;}} // end anonymous namespacetemplate <>Real FE<2,HERMITE>::shape(const ElemType,			  const Order,			  const unsigned int,			  const Point&){  std::cerr << "Hermite elements require the real element\n"	    << "to construct gradient-based degrees of freedom."	    << std::endl;    libmesh_error();  return 0.;}template <>Real FE<2,HERMITE>::shape(const Elem* elem,			  const Order order,			  const unsigned int i,			  const Point& p){  libmesh_assert (elem != NULL);  hermite_compute_coefs(elem);  const ElemType type = elem->type();    const Order totalorder = static_cast<Order>(order + elem->p_level());    switch (type)    {    case QUAD4:      libmesh_assert (totalorder < 4);    case QUAD8:    case QUAD9:      {        libmesh_assert (i<(totalorder+1u)*(totalorder+1u));        std::vector<unsigned int> bases1D;        Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i);        return coef * FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *               FEHermite<1>::hermite_raw_shape(bases1D[1],p(1));      }    default:      std::cerr << "ERROR: Unsupported element type!" << std::endl;      libmesh_error();    }    libmesh_error();  return 0.;}template <>Real FE<2,HERMITE>::shape_deriv(const ElemType,				const Order,			    				const unsigned int,				const unsigned int,				const Point&){  std::cerr << "Hermite elements require the real element\n"	    << "to construct gradient-based degrees of freedom."	    << std::endl;  libmesh_error();  return 0.;}template <>Real FE<2,HERMITE>::shape_deriv(const Elem* elem,				const Order order,				const unsigned int i,				const unsigned int j,				const Point& p){  libmesh_assert (elem != NULL);  libmesh_assert (j == 0 || j == 1);  hermite_compute_coefs(elem);  const ElemType type = elem->type();    const Order totalorder = static_cast<Order>(order + elem->p_level());    switch (type)    {    case QUAD4:      libmesh_assert (totalorder < 4);    case QUAD8:    case QUAD9:      {        libmesh_assert (i<(totalorder+1u)*(totalorder+1u));        std::vector<unsigned int> bases1D;        Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i);        switch (j)          {            case 0:              return coef *                FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *                FEHermite<1>::hermite_raw_shape(bases1D[1],p(1));            case 1:              return coef *                FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *                FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1));            default:              libmesh_error();          }      }    default:      std::cerr << "ERROR: Unsupported element type!" << std::endl;      libmesh_error();    }    libmesh_error();  return 0.;}template <>Real FE<2,HERMITE>::shape_second_deriv(const Elem* elem,                                       const Order order,                                       const unsigned int i,                                       const unsigned int j,                                       const Point& p){  libmesh_assert (elem != NULL);  libmesh_assert (j == 0 || j == 1 || j == 2);  hermite_compute_coefs(elem);  const ElemType type = elem->type();    const Order totalorder = static_cast<Order>(order + elem->p_level());    switch (type)    {    case QUAD4:      libmesh_assert (totalorder < 4);    case QUAD8:    case QUAD9:      {        libmesh_assert (i<(totalorder+1u)*(totalorder+1u));        std::vector<unsigned int> bases1D;        Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i);        switch (j)          {          case 0:            return coef *              FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[0],p(0)) *              FEHermite<1>::hermite_raw_shape(bases1D[1],p(1));          case 1:            return coef *              FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *              FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1));          case 2:            return coef *              FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *              FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[1],p(1));          default:            libmesh_error();          }      }    default:      std::cerr << "ERROR: Unsupported element type!" << std::endl;      libmesh_error();    }    libmesh_error();  return 0.;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -