MFEM v2.0
tetrahedron.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 // Implementation of class Tetrahedron
00013 
00014 #include "mesh_headers.hpp"
00015 #include <math.h>
00016 
00017 const int Tetrahedron::edges[6][2] =
00018 {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
00019 
00020 void Tetrahedron::ParseRefinementFlag(int refinement_edges[2], int &type,
00021                                       int &flag)
00022 {
00023    int i, f = refinement_flag;
00024 
00025    if (f == 0)
00026       mfem_error("Tetrahedron::ParseRefinementFlag :"
00027                  " tetrahedron is not marked");
00028 
00029    for (i = 0; i < 2; i++)
00030    {
00031       refinement_edges[i] = f & 7;
00032       f = f >> 3;
00033    }
00034    type = f & 7;
00035    flag = (f >> 3);
00036 }
00037 
00038 void Tetrahedron::CreateRefinementFlag(int refinement_edges[2], int type,
00039                                        int flag)
00040 {
00041 // Check for correct type
00042 #ifdef MFEM_DEBUG
00043    int e1, e2;
00044    e1 = refinement_edges[0];
00045    e2 = refinement_edges[1];
00046    // if (e1 > e2)  e1 = e2, e2 = refinement_edges[0];
00047    switch (type)
00048    {
00049    case Tetrahedron::TYPE_PU:
00050       if (e1 == 2 && e2 == 1) break;
00051       // if (e1 == 3 && e2 == 4) break;
00052       mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #1");
00053       break;
00054    case Tetrahedron::TYPE_A:
00055       if (e1 == 3 && e2 == 1) break;
00056       if (e1 == 2 && e2 == 4) break;
00057       // if (flag == 0)  // flag is assumed to be the generation
00058       //   if (e2 == 5)
00059       //      if (e1 >= 1 && e1 <= 5) break; // type is actually O or M
00060       //                                     //   ==>  ok for generation = 0
00061       mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #2");
00062       break;
00063    case Tetrahedron::TYPE_PF:
00064       if (flag > 0)  // PF is ok only for generation > 0
00065       {
00066          if (e1 == 2 && e2 == 1) break;
00067          // if (e1 == 3 && e2 == 4) break;
00068       }
00069       mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #3");
00070       break;
00071    case Tetrahedron::TYPE_O:
00072       if (flag == 0 && e1 == 5 && e2 == 5)
00073          break;
00074       mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #4");
00075       break;
00076    case Tetrahedron::TYPE_M:
00077       if (flag == 0)
00078       {
00079          if (e1 == 5 && e2 == 1)  break;
00080          if (e1 == 2 && e2 == 5)  break;
00081       }
00082       mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #5");
00083       break;
00084    default:
00085       mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #6");
00086       break;
00087    }
00088 #endif
00089 
00090    refinement_flag = flag;
00091    refinement_flag = refinement_flag << 3;
00092 
00093    refinement_flag = refinement_flag | type;
00094    refinement_flag = refinement_flag << 3;
00095 
00096    refinement_flag = refinement_flag | refinement_edges[1];
00097    refinement_flag = refinement_flag << 3;
00098 
00099    refinement_flag = refinement_flag | refinement_edges[0];
00100 }
00101 
00102 Tetrahedron::Tetrahedron(int *ind, int attr) : Element(Geometry::TETRAHEDRON)
00103 {
00104    attribute = attr;
00105    for (int i = 0; i < 4; i++)
00106       indices[i] = ind[i];
00107    refinement_flag = 0;
00108 }
00109 
00110 Tetrahedron::Tetrahedron(int ind1, int ind2, int ind3, int ind4, int attr)
00111    : Element(Geometry::TETRAHEDRON)
00112 {
00113    attribute  = attr;
00114    indices[0] = ind1;
00115    indices[1] = ind2;
00116    indices[2] = ind3;
00117    indices[3] = ind4;
00118    refinement_flag = 0;
00119 }
00120 
00121 int Tetrahedron::NeedRefinement(DSTable &v_to_v, int *middle) const
00122 {
00123    int m;
00124 
00125    if ((m = v_to_v(indices[0], indices[1])) != -1)
00126       if (middle[m] != -1) return 1;
00127    if ((m = v_to_v(indices[1], indices[2])) != -1)
00128       if (middle[m] != -1) return 1;
00129    if ((m = v_to_v(indices[2], indices[0])) != -1)
00130       if (middle[m] != -1) return 1;
00131    if ((m = v_to_v(indices[0], indices[3])) != -1)
00132       if (middle[m] != -1) return 1;
00133    if ((m = v_to_v(indices[1], indices[3])) != -1)
00134       if (middle[m] != -1) return 1;
00135    if ((m = v_to_v(indices[2], indices[3])) != -1)
00136       if (middle[m] != -1) return 1;
00137    return 0;
00138 }
00139 
00140 void Tetrahedron::SetVertices(const int *ind)
00141 {
00142    for (int i = 0; i < 4; i++)
00143       indices[i] = ind[i];
00144 }
00145 
00146 void Tetrahedron::MarkEdge(const DSTable &v_to_v, const int *length)
00147 {
00148    int ind[4], i, j, l, L, type;
00149 
00150    // determine the longest edge
00151    L = length[v_to_v(indices[0], indices[1])]; j = 0;
00152    if ((l = length[v_to_v(indices[1], indices[2])]) > L) { L = l; j = 1; }
00153    if ((l = length[v_to_v(indices[2], indices[0])]) > L) { L = l; j = 2; }
00154    if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; j = 3; }
00155    if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; j = 4; }
00156    if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; j = 5; }
00157 
00158    for (i = 0; i < 4; i++)
00159       ind[i] = indices[i];
00160 
00161    switch (j)
00162    {
00163    case 1:
00164       indices[0] = ind[1]; indices[1] = ind[2];
00165       indices[2] = ind[0]; indices[3] = ind[3];
00166       break;
00167    case 2:
00168       indices[0] = ind[2]; indices[1] = ind[0];
00169       indices[2] = ind[1]; indices[3] = ind[3];
00170       break;
00171    case 3:
00172       indices[0] = ind[3]; indices[1] = ind[0];
00173       indices[2] = ind[2]; indices[3] = ind[1];
00174       break;
00175    case 4:
00176       indices[0] = ind[1]; indices[1] = ind[3];
00177       indices[2] = ind[2]; indices[3] = ind[0];
00178       break;
00179    case 5:
00180       indices[0] = ind[2]; indices[1] = ind[3];
00181       indices[2] = ind[0]; indices[3] = ind[1];
00182       break;
00183    }
00184 
00185    // Determine the two longest edges for the other two faces and
00186    // store them in ind[0] and ind[1]
00187    ind[0] = 2; ind[1] = 1;
00188    L = length[v_to_v(indices[0], indices[2])];
00189    if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; ind[0] = 3; }
00190    if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[0] = 5; }
00191 
00192    L = length[v_to_v(indices[1], indices[2])];
00193    if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; ind[1] = 4; }
00194    if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[1] = 5; }
00195 
00196    j = 0;
00197    switch (ind[0])
00198    {
00199    case 2:
00200       switch (ind[1])
00201       {
00202       case 1:  type = Tetrahedron::TYPE_PU; break;
00203       case 4:  type = Tetrahedron::TYPE_A;  break;
00204       case 5:  type = Tetrahedron::TYPE_M;
00205       }
00206       break;
00207    case 3:
00208       switch (ind[1])
00209       {
00210       case 1:  type = Tetrahedron::TYPE_A;  break;
00211       case 4:  type = Tetrahedron::TYPE_PU;
00212          j = 1; ind[0] = 2; ind[1] = 1; break;
00213       case 5:  type = Tetrahedron::TYPE_M;
00214          j = 1; ind[0] = 5; ind[1] = 1;
00215       }
00216       break;
00217    case 5:
00218       switch (ind[1])
00219       {
00220       case 1:  type = Tetrahedron::TYPE_M;  break;
00221       case 4:  type = Tetrahedron::TYPE_M;
00222          j = 1; ind[0] = 2; ind[1] = 5; break;
00223       case 5:  type = Tetrahedron::TYPE_O;
00224       }
00225    }
00226 
00227    if (j)
00228    {
00229       j = indices[0]; indices[0] = indices[1]; indices[1] = j;
00230       j = indices[2]; indices[2] = indices[3]; indices[3] = j;
00231    }
00232 
00233    CreateRefinementFlag(ind, type);
00234 }
00235 
00236 void Tetrahedron::GetVertices(Array<int> &v) const
00237 {
00238    v.SetSize(4);
00239    for (int i = 0; i < 4; i++)
00240    {
00241       v[i] = indices[i];
00242    }
00243 }
00244 
00245 Element *Tetrahedron::Duplicate(Mesh *m) const
00246 {
00247 #ifdef MFEM_USE_MEMALLOC
00248    Tetrahedron *tet = m->TetMemory.Alloc();
00249 #else
00250    Tetrahedron *tet = new Tetrahedron;
00251 #endif
00252    tet->SetVertices(indices);
00253    tet->SetAttribute(attribute);
00254    tet->SetRefinementFlag(refinement_flag);
00255    return tet;
00256 }
00257 
00258 Linear3DFiniteElement TetrahedronFE;
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines