198 lines
5.0 KiB
C++
198 lines
5.0 KiB
C++
// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
|
|
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
|
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
|
//
|
|
// This file is part of the MFEM library. For more information and source code
|
|
// availability visit https://mfem.org.
|
|
//
|
|
// MFEM is free software; you can redistribute it and/or modify it under the
|
|
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
|
// CONTRIBUTING.md for details.
|
|
|
|
#include "mesh_headers.hpp"
|
|
|
|
namespace mfem
|
|
{
|
|
|
|
Triangle::Triangle(const int *ind, int attr) : Element(Geometry::TRIANGLE)
|
|
{
|
|
attribute = attr;
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
indices[i] = ind[i];
|
|
}
|
|
transform = 0;
|
|
}
|
|
|
|
Triangle::Triangle(int ind1, int ind2, int ind3, int attr)
|
|
: Element(Geometry::TRIANGLE)
|
|
{
|
|
attribute = attr;
|
|
indices[0] = ind1;
|
|
indices[1] = ind2;
|
|
indices[2] = ind3;
|
|
transform = 0;
|
|
}
|
|
|
|
int Triangle::NeedRefinement(HashTable<Hashed2> &v_to_v) const
|
|
{
|
|
if (v_to_v.FindId(indices[0], indices[1]) != -1) { return 1; }
|
|
if (v_to_v.FindId(indices[1], indices[2]) != -1) { return 1; }
|
|
if (v_to_v.FindId(indices[2], indices[0]) != -1) { return 1; }
|
|
return 0;
|
|
}
|
|
|
|
void Triangle::SetVertices(const int *ind)
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
indices[i] = ind[i];
|
|
}
|
|
}
|
|
|
|
void Triangle::MarkEdge(DenseMatrix &pmat)
|
|
{
|
|
double d[3];
|
|
int shift, v;
|
|
|
|
d[0] = ( (pmat(0,1)-pmat(0,0))*(pmat(0,1)-pmat(0,0)) +
|
|
(pmat(1,1)-pmat(1,0))*(pmat(1,1)-pmat(1,0)) );
|
|
d[1] = ( (pmat(0,2)-pmat(0,1))*(pmat(0,2)-pmat(0,1)) +
|
|
(pmat(1,2)-pmat(1,1))*(pmat(1,2)-pmat(1,1)) );
|
|
d[2] = ( (pmat(0,2)-pmat(0,0))*(pmat(0,2)-pmat(0,0)) +
|
|
(pmat(1,2)-pmat(1,0))*(pmat(1,2)-pmat(1,0)) );
|
|
|
|
// if pmat has 3 rows, then use extra term in each sum
|
|
if (pmat.Height()==3)
|
|
{
|
|
d[0] += (pmat(2,1)-pmat(2,0))*(pmat(2,1)-pmat(2,0));
|
|
d[1] += (pmat(2,2)-pmat(2,1))*(pmat(2,2)-pmat(2,1));
|
|
d[2] += (pmat(2,2)-pmat(2,0))*(pmat(2,2)-pmat(2,0));
|
|
}
|
|
|
|
if (d[0] >= d[1])
|
|
{
|
|
if (d[0] >= d[2]) { shift = 0; }
|
|
else { shift = 2; }
|
|
}
|
|
else if (d[1] >= d[2]) { shift = 1; }
|
|
else { shift = 2; }
|
|
|
|
switch (shift)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
v = indices[0];
|
|
indices[0] = indices[1];
|
|
indices[1] = indices[2];
|
|
indices[2] = v;
|
|
break;
|
|
case 2:
|
|
v = indices[0];
|
|
indices[0] = indices[2];
|
|
indices[2] = indices[1];
|
|
indices[1] = v;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Static method
|
|
void Triangle::MarkEdge(int *indices, const DSTable &v_to_v, const int *length)
|
|
{
|
|
int l, L, j, ind[3], i;
|
|
|
|
L = length[ v_to_v(indices[0], indices[1]) ]; j = 0;
|
|
if ( (l = length[ v_to_v(indices[1], indices[2]) ]) > L ) { L = l; j = 1; }
|
|
if ( (l = length[ v_to_v(indices[2], indices[0]) ]) > L ) { j = 2; }
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
ind[i] = indices[i];
|
|
}
|
|
|
|
switch (j)
|
|
{
|
|
case 1:
|
|
indices[0] = ind[1]; indices[1] = ind[2]; indices[2] = ind[0];
|
|
break;
|
|
case 2:
|
|
indices[0] = ind[2]; indices[1] = ind[0]; indices[2] = ind[1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// static method
|
|
void Triangle::GetPointMatrix(unsigned transform, DenseMatrix &pm)
|
|
{
|
|
double *a = &pm(0,0), *b = &pm(0,1), *c = &pm(0,2);
|
|
|
|
// initialize to identity
|
|
a[0] = 0.0; a[1] = 0.0;
|
|
b[0] = 1.0; b[1] = 0.0;
|
|
c[0] = 0.0; c[1] = 1.0;
|
|
|
|
int chain[12], n = 0;
|
|
while (transform)
|
|
{
|
|
chain[n++] = (transform & 7) - 1;
|
|
transform >>= 3;
|
|
}
|
|
|
|
/* The transformations and orientations here match
|
|
Mesh::UniformRefinement and Mesh::Bisection for triangles:
|
|
|
|
c c
|
|
* *
|
|
| \ |\\
|
|
| \ | \ \
|
|
| 2 \ e | \ \
|
|
f *-------* | \ \
|
|
| \ 3 | \ | \ \
|
|
| \ | \ | 4 \ 5 \
|
|
| 0 \ | 1 \ | \ \
|
|
*-------*-------* *-------*-------*
|
|
a d b a d b
|
|
*/
|
|
|
|
double d[2], e[2], f[2];
|
|
#define ASGN(a, b) (a[0] = b[0], a[1] = b[1])
|
|
#define AVG(a, b, c) (a[0] = (b[0] + c[0])*0.5, a[1] = (b[1] + c[1])*0.5)
|
|
|
|
while (n)
|
|
{
|
|
switch (chain[--n])
|
|
{
|
|
case 0: AVG(b, a, b); AVG(c, a, c); break;
|
|
case 1: AVG(a, a, b); AVG(c, b, c); break;
|
|
case 2: AVG(a, a, c); AVG(b, b, c); break;
|
|
|
|
case 3:
|
|
AVG(d, a, b); AVG(e, b, c); AVG(f, c, a);
|
|
ASGN(a, e); ASGN(b, f); ASGN(c, d); break;
|
|
|
|
case 4:
|
|
AVG(d, a, b); // N.B.: orientation
|
|
ASGN(b, a); ASGN(a, c); ASGN(c, d); break;
|
|
|
|
case 5:
|
|
AVG(d, a, b); // N.B.: orientation
|
|
ASGN(a, b); ASGN(b, c); ASGN(c, d); break;
|
|
|
|
default:
|
|
MFEM_ABORT("Invalid transform.");
|
|
}
|
|
}
|
|
}
|
|
|
|
void Triangle::GetVertices(Array<int> &v) const
|
|
{
|
|
v.SetSize(3);
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
v[i] = indices[i];
|
|
}
|
|
}
|
|
|
|
} // namespace mfem
|