Files
mfem/examples/maxwell-solver/ToroidST/MeshPart.cpp
T

228 lines
6.0 KiB
C++

#include "MeshPart.hpp"
void GetMeshAngleRange(Mesh * mesh, double & amin, double & amax)
{
amin = infinity();
amax = -infinity();
int nbe = mesh->GetNBE();
int dim = mesh->Dimension();
for (int i = 0; i < nbe; ++i)
{
const Element *el = mesh->GetBdrElement(i);
Vector center(dim);
int geom = mesh->GetBdrElementBaseGeometry(i);
ElementTransformation * T = mesh->GetBdrElementTransformation(i);
T->Transform(Geometries.GetCenter(geom),center);
double x = center[0];
double y = center[1];
x = (abs(x)<1e-12) ? 0.0 : x;
y = (abs(y)<1e-12) ? 0.0 : y;
double theta = (x == 0) ? M_PI/2.0 : atan(y/x);
int k = (x<=0.0) ? 1 : ((y<0.0) ? 2 : 0.0);
theta += k*M_PI;
double thetad = theta * 180.0/M_PI;
amin = min(amin,thetad);
amax = max(amax,thetad);
}
}
int get_angle_range(double angle, Array<double> angles)
{
auto it = std::upper_bound(angles.begin(), angles.end(), angle);
return std::distance(angles.begin(),it)-1;
}
void SetMeshAttributes(Mesh * mesh, int subdivisions, double ovlp)
{
Array<double> angles(2*subdivisions);
double amin = 0.0;
angles[0] = amin;
double amax = 270;
double pmin, pmax;
GetMeshAngleRange(mesh,pmin,pmax);
cout << "pmin = " << pmin << endl;
cout << "pmax = " << pmax << endl;
double length = (amax-amin)/subdivisions;
double range;
for (int i = 1; i<subdivisions; i++)
{
range = i*length;
angles[2*i-1] = range-ovlp;
angles[2*i] = range+ovlp;
}
angles[2* subdivisions-1] = amax;
int ne = mesh->GetNE();
int dim = mesh->Dimension();
// set element attributes
for (int i = 0; i < ne; ++i)
{
Element *el = mesh->GetElement(i);
// roughly the element center
Vector center(dim);
mesh->GetElementCenter(i,center);
double x = center[0];
double y = center[1];
double theta = (x == 0) ? M_PI/2.0 : atan(y/x);
int k = 0;
if (x<0)
{
k = 1;
}
else if (y<0)
{
k = 2;
}
theta += k*M_PI;
double thetad = theta * 180.0/M_PI;
// Find the angle relative to (0,0,z)
int attr = get_angle_range(thetad, angles) + 1;
el->SetAttribute(attr);
}
mesh->SetAttributes();
cout << "Max attributes " << mesh->attributes.Max() << endl;
}
// remove/leave elements with attributes given by attr
Mesh * GetPartMesh(const Mesh * mesh0, const Array<int> & attr_, Array<int> & elem_map,
bool complement)
{
Array<int> bdr_attr;
int max_attr = mesh0->attributes.Max();
int min_attr = mesh0->attributes.Min();
Array<int> attr;
Array<int> all_attr(max_attr); all_attr = 0;
for (int i = 0; i<attr_.Size(); i++)
{
all_attr[attr_[i]-1] = 1;
}
for (int i = min_attr; i<=max_attr; i++)
{
if (complement && all_attr[i-1]==0) attr.Append(i);
if (!complement && all_attr[i-1]==1) attr.Append(i);
}
int max_bdr_attr = mesh0->bdr_attributes.Max();
bdr_attr.SetSize(attr.Size());
for (int i=0; i<attr.Size(); i++)
{
bdr_attr[i] = max_bdr_attr + attr[i];
}
Array<int> marker(max_attr);
Array<int> attr_inv(max_attr);
marker = 0;
attr_inv = 0;
for (int i=0; i<attr.Size(); i++)
{
marker[attr[i]-1] = 1;
attr_inv[attr[i]-1] = i;
}
// Count the number of elements in the final mesh
int num_elements = 0;
for (int e=0; e<mesh0->GetNE(); e++)
{
int elem_attr = mesh0->GetElement(e)->GetAttribute();
if (!marker[elem_attr-1]) { num_elements++; }
}
Mesh * mesh = new Mesh(mesh0->Dimension(), mesh0->GetNV(), num_elements);
// Copy vertices
for (int v=0; v<mesh0->GetNV(); v++)
{
mesh->AddVertex(mesh0->GetVertex(v));
}
// Copy elements
elem_map.SetSize(num_elements);
int k = 0;
for (int e=0; e<mesh0->GetNE(); e++)
{
const Element * el = mesh0->GetElement(e);
int elem_attr = el->GetAttribute();
if (!marker[elem_attr-1])
{
Element * nel = mesh->NewElement(el->GetGeometryType());
nel->SetAttribute(elem_attr);
nel->SetVertices(el->GetVertices());
mesh->AddElement(nel);
elem_map[k++] = e;
}
}
mesh->FinalizeTopology();
mesh->RemoveUnusedVertices();
const GridFunction * nodes0 = mesh0->GetNodes();
int order = nodes0->FESpace()->GetOrder(0);
if (order > 1)
{
mesh->SetCurvature(order, false, 3, Ordering::byVDIM);
}
GridFunction * nodes = mesh->GetNodes();
int nel = mesh0->GetNE();
// copy nodes
int jel = 0;
for (int iel = 0; iel< nel; iel++)
{
int elem_attr = mesh0->GetElement(iel)->GetAttribute();
if (!marker[elem_attr-1])
{
Array<int> vdofs0,vdofs;
nodes0->FESpace()->GetElementVDofs(iel,vdofs0);
Vector x;
nodes0->GetSubVector(vdofs0,x);
nodes->FESpace()->GetElementVDofs(jel++,vdofs);
nodes->SetSubVector(vdofs,x);
}
}
return mesh;
}
// Partition mesh to nrsubmeshes (equally spaced in the azimuthal direction)
void PartitionMesh(Mesh * mesh, int nrsubmeshes, double ovlp,
Array<Mesh*> & SubMeshes, Array<Array<int> *> & elems)
{
cout << "Partitioning the global Mesh" << endl;
SetMeshAttributes(mesh,nrsubmeshes,ovlp);
int maxattr = mesh->attributes.Max();
// Produce the subdomains
char vishost[] = "localhost";
int visport = 19916;
SubMeshes.SetSize(nrsubmeshes);
elems.SetSize(nrsubmeshes);
for (int i = 0; i<nrsubmeshes; i++)
{
Array<int> attr;
for (int j = 0; j<3; j++)
{
if (2*i+j >0 && 2*i+j <= maxattr) attr.Append(2*i+j);
}
Array<int> elem_map;
// attr.Print();
elems[i] = new Array<int>(0);
SubMeshes[i] = GetPartMesh(mesh,attr,*elems[i],true);
socketstream mesh_sock(vishost, visport);
mesh_sock << "parallel " << nrsubmeshes << " " << i << "\n";
mesh_sock.precision(8);
mesh_sock << "mesh\n" << *SubMeshes[i] << flush;
// cout << "nrelemes = " << mesh1->GetNE() << endl;
}
}