SundanceRivaraElement.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 #include "SundanceRivaraElement.hpp"
00044 #include "SundanceRivaraEdge.hpp"
00045 #include "SundanceRivaraNode.hpp"
00046 #include "SundanceRivaraMesh.hpp"
00047 #include "SundanceOut.hpp"
00048 
00049 
00050 
00051 using namespace Sundance::Rivara;
00052 using namespace Teuchos;
00053 using std::endl;
00054 
00055 
00056 Element::Element(RivaraMesh* mesh,
00057                  const RCP<Node>& a,
00058                  const RCP<Node>& b,
00059                  const RCP<Node>& c,
00060   int ownerProc,
00061   int label)
00062   : label_(label),
00063     nodes_(tuple(a,b,c)),
00064     edges_(3),
00065     faces_(0),
00066     edgeSigns_(3),
00067     ownerProc_(ownerProc)
00068 {
00069   for (int i=0; i<3; i++)
00070     {
00071       edges_[i] = mesh->tryEdge(nodes_[i], nodes_[(i+1)%3], edgeSigns_[i]);
00072       edges_[i]->addConnectingElement(this);
00073       nodes_[i]->addConnectingElement(this);
00074 
00075       nodes_[i]->addConnectingEdge(edges_[i].get());
00076       nodes_[(i+1) % 3]->addConnectingEdge(edges_[i].get());
00077     }
00078 }
00079 
00080 Element::Element(RivaraMesh* mesh,
00081                  const RCP<Node>& a,
00082                  const RCP<Node>& b,
00083                  const RCP<Node>& c,
00084                  const RCP<Node>& d,
00085   int ownerProc,
00086   int label)
00087   : label_(label),
00088     nodes_(tuple(a,b,c,d)),
00089     edges_(6),
00090     faces_(4),
00091     edgeSigns_(6),
00092     ownerProc_(ownerProc)
00093 {
00094 
00095   for (int i=0; i<4; i++)
00096     {
00097       nodes_[i]->addConnectingElement(this);
00098     }
00099 
00100   int k=0;
00101   for (int i=0; i<4; i++)
00102     {
00103       for (int j=0; j<i; j++)
00104         {
00105           edges_[k] = mesh->tryEdge(nodes_[i], nodes_[j], edgeSigns_[k]);
00106           edges_[k]->addConnectingElement(this);
00107           nodes_[i]->addConnectingEdge(edges_[k].get());          
00108           nodes_[j]->addConnectingEdge(edges_[k].get());          
00109           k++;
00110         }
00111     }
00112 
00113   faces_[0] = mesh->tryFace(a,b,d);
00114   faces_[1] = mesh->tryFace(b,c,d);
00115   faces_[2] = mesh->tryFace(a,d,c);
00116   faces_[3] = mesh->tryFace(c,b,a);
00117 }
00118 
00119 int Element::longestEdgeIndex() const 
00120 {
00121   int e = 0;
00122   double L = -1.0;
00123   for (int i=0; i<edges_.length(); i++)
00124     {
00125       if (edges_[i]->length() > L) {e = i; L = edges_[i]->length();}
00126     }
00127   return e;
00128 }
00129 
00130 bool Element::hasHangingNode() const 
00131 {
00132   bool hasHangingNode = false;
00133   for (int i=0; i<edges_.length(); i++)
00134     {
00135       if (edges_[i]->hasChildren()) hasHangingNode = true;
00136     }
00137   return hasHangingNode;
00138 }
00139 
00140 void Element::refine(RivaraMesh* mesh, double maxArea)
00141 {
00142   /* if have children, refine the children */
00143   if (hasChildren())
00144     {
00145       dynamic_cast<Element*>(left())->refine(mesh, maxArea);
00146       dynamic_cast<Element*>(right())->refine(mesh, maxArea);
00147       return;
00148     }
00149 
00150 
00151   /* We will not need to refine if there is no hanging node and if
00152    * the area is already small enough */
00153   if (!hasHangingNode() && volume() < maxArea)
00154     {
00155       return;
00156     }
00157   if (!hasHangingNode() && maxArea < 0.0)
00158     {
00159       return;
00160     }
00161 
00162   /* --- If we're to this point, we need to refine --- */
00163 
00164   
00165   /* find the longest edge */
00166   int e = longestEdgeIndex();
00167 
00168   Element* sub1;
00169   Element* sub2;
00170   
00171   if (nodes_.length()==3)
00172     {
00173       /* classify the nodes relative to the longest edge:
00174        * Nodes a and b are on the longest edge.
00175        * Node c is opposite the longest edge.
00176        */
00177       RCP<Node> a, b, c;
00178       if (edgeSigns_[e] > 0)
00179         {
00180           a = edges_[e]->node(0);
00181           b = edges_[e]->node(1);
00182         }
00183       else
00184         {
00185           b = edges_[e]->node(0);
00186           a = edges_[e]->node(1);
00187         }
00188       /* find the node that's not on the longest edge */
00189       for (int i=0; i<nodes_.length(); i++)
00190         {
00191           if (nodes_[i].get() == a.get() || nodes_[i].get() == b.get()) continue;
00192           c = nodes_[i];
00193           break;
00194         }
00195 
00196       /* bisect the edge, creating a new node at the midpoint and two child
00197        * edges */
00198       RCP<Node> mid = edges_[e]->bisect(mesh);
00199 
00200       /* create the triangles defined by bisecting the longest edge */
00201       sub1 = new Element(mesh, a, mid, c, ownerProc_, label_);
00202       sub2 = new Element(mesh, c, mid, b, ownerProc_, label_);
00203     }
00204   else
00205     {
00206       /* classify the nodes relative to the longest edge:
00207        * Nodes a and b are on the longest edge.
00208        * Nodes c and d are on the edge that does not intersect the 
00209        * longest edge.
00210        */
00211       RCP<Node> a, b, c, d;
00212       if (edgeSigns_[e] > 0)
00213         {
00214           a = edges_[e]->node(0);
00215           b = edges_[e]->node(1);
00216         }
00217       else
00218         {
00219           b = edges_[e]->node(0);
00220           a = edges_[e]->node(1);
00221         }
00222       /* find the edge whose nodes are not on the longest edge */
00223       for (int i=0; i<edges_.length(); i++)
00224         {
00225           const RCP<Node>& node1 = edges_[i]->node(0);
00226           const RCP<Node>& node2 = edges_[i]->node(1);
00227           if (node1.get()==a.get() || node1.get()==b.get()
00228               || node2.get()==a.get() || node2.get()==b.get())
00229             {
00230               continue;
00231             }
00232           if (edgeSigns_[i] > 0)
00233             {
00234               c = edges_[i]->node(0);
00235               d = edges_[i]->node(1);
00236             }
00237           else
00238             {
00239               d = edges_[i]->node(0);
00240               c = edges_[i]->node(1);
00241             }
00242           break;
00243         }
00244 
00245       /* bisect the edge, creating a new node at the midpoint and two child
00246        * edges */
00247       RCP<Node> mid = edges_[e]->bisect(mesh);
00248 
00249       /* create the tets defined by bisecting the longest edge */
00250       sub1 = new Element(mesh, a, mid, c, d, ownerProc_, label_);
00251       sub2 = new Element(mesh, b, c, mid, d, ownerProc_, label_);
00252 
00253 
00254       /* if I have a label, then label the new faces */
00255       
00256       if (label_ != -1)
00257       {
00258         RCP<Face> abc = mesh->getFace(a,b,c);
00259         RCP<Face> abd = mesh->getFace(a,b,d);
00260         RCP<Face> acd = mesh->getFace(a,c,d);
00261         RCP<Face> bcd = mesh->getFace(b,c,d);
00262         
00263         RCP<Face> amd = mesh->getFace(a,mid,d);
00264         RCP<Face> amc = mesh->getFace(a,mid,c);
00265         RCP<Face> bmc = mesh->getFace(b,mid,c);
00266         RCP<Face> bmd = mesh->getFace(b,mid,d);
00267         
00268         amd->setLabel(abd->label());
00269         amc->setLabel(abc->label());
00270         
00271         bmd->setLabel(abd->label());
00272         bmc->setLabel(abc->label());
00273       }
00274       
00275     }
00276 
00277   sub1->setParent(this);
00278   sub2->setParent(this);
00279 
00280   setChildren(sub1, sub2);
00281 
00282   /* if the new node is hanging on the edge's other cofacets, mark the
00283    * other cofacets for refinement */
00284   Array<Element*> others;
00285   edges_[e]->getUnrefinedCofacets(others);
00286   for (int i=0; i<others.length(); i++)
00287     {
00288       Element* other = others[i];
00289       if (other==0) continue;
00290       mesh->refinementSet().push(other);
00291       mesh->refinementAreas().push(-1.0);
00292     }
00293 
00294   if (sub1->hasHangingNode() || maxArea > 0.0) 
00295     sub1->refine(mesh, maxArea);
00296   if (sub2->hasHangingNode() || maxArea > 0.0) 
00297     sub2->refine(mesh, maxArea);
00298 }
00299 
00300 namespace Sundance
00301 {
00302 inline Point cross3(const Point& a, const Point& b)
00303 {
00304   return Point(a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2],
00305     a[0]*b[1]-a[1]*b[0]);
00306 }
00307 
00308 inline double cross2(const Point& a, const Point& b)
00309 {
00310   return a[0]*b[1] - a[1]*b[0];
00311 }
00312 }
00313 
00314 double Element::volume() const 
00315 {
00316   if (nodes_.length()==3)
00317     {
00318       return 0.5*::fabs(cross2(nodes_[2]->pt()-nodes_[0]->pt(), 
00319           nodes_[1]->pt()-nodes_[0]->pt()));
00320     }
00321   else
00322     {
00323       Point AB = nodes_[1]->pt() - nodes_[0]->pt();
00324       Point AC = nodes_[2]->pt() - nodes_[0]->pt();
00325       Point AD = nodes_[3]->pt() - nodes_[0]->pt();
00326       return 1.0/6.0 * fabs( AB * cross3(AC, AD) );
00327     }
00328 }
00329 
00330 
00331 Array<int> Element::showNodes() const
00332 {
00333   Array<int> rtn(nodes_.length());
00334   for (int i=0; i<nodes_.length(); i++) rtn[i]=nodes_[i]->localIndex();
00335   return rtn;
00336 }
00337 
00338 bool Element::hasNoEdgeLabels() const
00339 {
00340   for (int i=0; i<3; i++) 
00341   {
00342     if (edges_[i]->label() != -1) return false;
00343   }
00344   return true;
00345 }
00346 
00347 bool Element::hasNoFaceLabels() const
00348 {
00349   for (int i=0; i<4; i++) 
00350   {
00351     if (faces_[i]->label() != -1) return false;
00352   }
00353   return true;
00354 }

Site Contact