src/tetmesh/tet.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           tet.cpp  -  description
00003                              -------------------
00004     begin                : Fri Dec 12 2003
00005     copyright            : (C) 2003 by Roman Geus
00006     email                : roman.geus@psi.ch
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <stdexcept>
00019 #include "vector.h"
00020 #include "linalg.h"
00021 #include "point.h"
00022 #include "tet.h"
00023 #include "tetmesh.h"
00024 #include "fmxxtopology.h"
00025 
00026 namespace mesh {
00027 
00028 using namespace colarray;
00029 
00030   Tet::Tet(const TetMesh& mesh, id_t id, id_t corners[4], id_t material) :
00031     Entity(id), _edge_orientation(0), _material(material)
00032 {
00033     // store corners
00034     for (int i = 0; i < 4; i ++)
00035         _corners[i] = corners[i];
00036 
00037     // calculate Tet volume
00038     double volume = get_volume();
00039     
00040     // check for degenerate elements
00041     if (1.0 + volume == 1.0)
00042         throw std::runtime_error("Tetrahedron has zero volume.");
00043 
00044     // enforce positive orientation
00045     if (volume < 0.0)
00046         std::swap<id_t>(_corners[0], _corners[1]);
00047 }
00048 
00049 void Tet::set_face_id(int i, id_t id) {
00050     _faces[i] = id;
00051 }
00052 
00053 void Tet::set_edge_id(int i, id_t id) {
00054     _edges[i] = id;
00055 }
00056 
00057 void Tet::set_edge_orientation(int edge_lid, bool orientation) {
00058     if (orientation)
00059         _edge_orientation |= 1 << edge_lid;
00060     else
00061         _edge_orientation &= ~(1 << edge_lid);
00062 }
00063 
00064 id_t Tet::get_material_ID() const { 
00065   return _material;
00066 }
00067 
00068 double Tet::get_volume() const { 
00069     CoordinateMatrix X(*this);
00070     return linalg::determinant(X) / 6.0;
00071 }
00072 
00074 Vector3 Tet::get_center_of_gravity() const
00075 {
00076         int i; 
00077         Vector3 cog(0,0,0);
00078         
00079         for(i=0;i<NCORNERTET;i++)
00080         {
00081                 cog+=0.25 * this->get_corner(i)->get_coord();
00082         }
00083                 
00084         /* go back */
00085         return(cog);
00086 }
00087 
00088 
00091 void Tet::cartesian_to_simplex(const Vector3& cartesian, Vector4& simplex) const {
00092     CoordinateMatrix X(*this);
00093     ColumnVector<double> t(3);
00094 
00095     for (int i = 0; i < 4; i ++) {
00096         RowVector<double> r(X, i);           // create alias to row i
00097         Vector<double> r1(r, 1, 4);          // skip 1st element in row i
00098         t.inject(r1);                        // save row i
00099         r1(0) = cartesian.x;                 // overwrite row i with x
00100         r1(1) = cartesian.y;
00101         r1(2) = cartesian.z;
00102         simplex[i] = linalg::determinant(X) / (6.0 * get_volume()); // _volume;
00103         r1.inject(t);                        // restore row i
00104     }
00105 }
00106 
00107 bool Tet::is_inside(const Vector3& point) const {
00108     Vector4 simplex_coord;
00109     cartesian_to_simplex(point, simplex_coord);
00110     for (int i = 0; i < 4; i ++)
00111         if (simplex_coord[i] < 0.0)
00112             return false;
00113     for (int i = 0; i < 4; i ++)
00114         if (simplex_coord[i] > 1.0)
00115             return false;
00116     return true;
00117 }
00118 
00119 bool Tet::is_inside_gracious(const Vector3& point) const {
00120     const double grace_tolerance = 1e-14;
00121     Vector4 simplex_coord;
00122 
00123     cartesian_to_simplex(point, simplex_coord);
00124     for (int i = 0; i < 4; i ++)
00125         if (simplex_coord[i] < -grace_tolerance)
00126             return false;
00127     for (int i = 0; i < 4; i ++)
00128         if (simplex_coord[i] > 1.0 + grace_tolerance)
00129             return false;
00130     return true;    
00131 }
00132 
00133 void Tet::get_bounding_box(Vector3& center, Vector3& extent) const {
00134     Vector3 min, max, coord;
00135 
00136     min = get_corner(0)->get_coord();
00137     max = min;
00138     for (int i = 1; i < 4; i ++) {
00139         coord = get_corner(i)->get_coord();
00140         min.make_floor(coord);
00141         max.make_ceil(coord);
00142     }
00143     center = max.mid_point(min);
00144     extent = 0.5 * (max - min);
00145 }
00146 
00147 Tet::CoordinateMatrix::CoordinateMatrix(const Tet& tet) : colarray::Matrix<double>(4, 4) {
00148     Vector3 coord;
00149 
00150     for (int i = 0; i < 4; i ++) {
00151         this->operator()(i,0) = 1.0;
00152         coord = tet.get_mesh()->get_point(tet._corners[i])->get_coord();
00153         for (int j = 0; j < 3; j ++)
00154             this->operator()(i,j+1) = coord[j];
00155     }
00156 }
00157 
00158 Tet::GradientMatrix::GradientMatrix(const CoordinateMatrix& X) : colarray::Matrix<double>(3, 4) {
00159     colarray::Matrix<double> Xinv(4, 4);
00160     // compute inverse of coordinate matrix
00161     linalg::inverse(X, Xinv);
00162     // rows 1, 2, 3 are gradients
00163     this->inject(colarray::Matrix<double>(Xinv, 1, 4, 0, 4));
00164 }
00165 
00166 Tet::GradientMatrix::GradientMatrix(const Tet& tet) : colarray::Matrix<double>(3, 4) {
00167     Tet::CoordinateMatrix X(tet);
00168     colarray::Matrix<double> Xinv(4, 4);
00169     // compute inverse of coordinate matrix
00170     linalg::inverse(X, Xinv);
00171     // rows 1, 2, 3 are gradients
00172     this->inject(colarray::Matrix<double>(Xinv, 1, 4, 0, 4));
00173 }
00174 
00175 Point* Tet::get_corner(int i) const {
00176     return get_mesh()->get_point(get_corner_id(i));
00177 }
00178 
00179 Edge* Tet::get_edge(int i) const {
00180     return get_mesh()->get_edge(get_edge_id(i));
00181 }
00182 
00183 Face* Tet::get_face(int i) const {
00184     return get_mesh()->get_face(get_face_id(i));
00185 }
00186 
00187 TetMesh* Tet::get_mesh() const {
00188     return TetMesh::get_instance();
00189 }
00190 
00191 } // namespace mesh

Generated on Fri Oct 26 13:35:13 2007 for FEMAXX (Finite Element Maxwell Eigensolver) by  doxygen 1.4.7