Files
mfem/mesh/triangle.cpp
T
Veselin Dobrev f9694c3c2b Simplified data structures in class ParMesh
In class ParMesh:

* Introduced internal struct's Vert3 and Vert4 holding 3 and 4
  integers, respectively.

* Replaced 'shared_faces' with two separate arrays 'shared_trias'
  and 'shared_quads' with types Array<Vert3> and Array<Vert4>,
  respectively.

* Removed the arrays 'stria_lface', 'squad_lface', 'stria_sface',
  'squad_sface', and 'sface_stype'.

* Restore the array 'sface_lface' used previously. Shared face
  indices are shred triangle / quad indices offset by 0 / "number
  of shared triangles", respectively.

* Made the two RefineGroups methods protected.

* Added two new protected methods: UniformRefineGroups2D and
  UniformRefineGroups3D. These two methods simplify the
  implementations of almost all uniform-refinement methods in
  the class.

* Fixed a bug in ReorderTetMesh that was causing ex8p to fail with
  fichera-mixed.mesh.

* Updated the implementations of all ParMesh methods as necessary
  due to the above changes.

In class Triangle, add a static method MarkEdge that works on a
given array of 3 indices.

In class Array, add a method CopyTo - implemented using std::copy.
2018-09-16 14:30:09 -07:00

198 lines
5.0 KiB
C++

// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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) version 2.1 dated February 1999.
#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