* Changes to the Boundary Layer generation system

* More user feedback when saving and exporting mesh files to disk
This commit is contained in:
Philippose Rajan 2009-10-27 23:04:42 +00:00
parent 6f39164242
commit b2e8610f90
4 changed files with 302 additions and 270 deletions

View File

@ -141,10 +141,15 @@ namespace netgen
Currently, the layer height is calculated using: Currently, the layer height is calculated using:
height = h_first_layer * (growth_factor^(num_layers - 1)) height = h_first_layer * (growth_factor^(num_layers - 1))
*/ */
void GenerateBoundaryLayer (Mesh & mesh) void GenerateBoundaryLayer (Mesh & mesh, MeshingParameters & mp)
{ {
int i, j; int i, j;
// Angle between a surface element and a growth-vector below which
// a prism is project onto that surface as a quad
// (in degrees)
double angleThreshold = 15.0;
cout << "Generate Prismatic Boundary Layers (Experimental)...." << endl; cout << "Generate Prismatic Boundary Layers (Experimental)...." << endl;
// Use an array to support creation of boundary // Use an array to support creation of boundary
@ -168,6 +173,12 @@ namespace netgen
} }
cout << "Number of surfaces entered = " << surfid.Size() << endl; cout << "Number of surfaces entered = " << surfid.Size() << endl;
cout << "Selected surfaces are:" << endl;
for(i = 1; i <= surfid.Size(); i++)
{
cout << "Surface " << i << ": " << surfid.Elem(i) << endl;
}
cout << endl << "Enter number of prism layers: "; cout << endl << "Enter number of prism layers: ";
cin >> prismlayers; cin >> prismlayers;
@ -188,8 +199,18 @@ namespace netgen
{ {
cout << "Generating layer: " << layer << endl; cout << "Generating layer: " << layer << endl;
//double layerht = hfirst + growthfactor*(layer - 1)*hfirst; double layerht = hfirst;
double layerht = hfirst*pow(growthfactor,(double)(layer-1));
if(growthfactor == 1)
{
layerht = layer * hfirst;
}
else
{
layerht = hfirst*(pow(growthfactor,(layer+1)) - 1)/(growthfactor - 1);
}
cout << "Layer Height = " << layerht << endl;
// Need to store the old number of points and // Need to store the old number of points and
// surface elements because there are new points and // surface elements because there are new points and
@ -201,6 +222,9 @@ namespace netgen
// consistency // consistency
int nseg = mesh.GetNSeg(); int nseg = mesh.GetNSeg();
// Update the mesh topology structures
mesh.UpdateTopology();
const MeshTopology& meshtopo = mesh.GetTopology(); const MeshTopology& meshtopo = mesh.GetTopology();
// Indicate which points need to be remapped // Indicate which points need to be remapped
@ -213,9 +237,6 @@ namespace netgen
// the effective surface normal at a given point // the effective surface normal at a given point
Array<Vec3d> growthvectors(np); Array<Vec3d> growthvectors(np);
// Update the mesh topology structures
mesh.UpdateTopology();
// Bit array to identify all the points belonging // Bit array to identify all the points belonging
// to the surface of interest // to the surface of interest
bndnodes.Clear(); bndnodes.Clear();
@ -242,7 +263,7 @@ namespace netgen
bndnodes.Set(sel.PNum(j)); bndnodes.Set(sel.PNum(j));
// Vec3d& surfacenormal = Vec3d(); ???? // Vec3d& surfacenormal = Vec3d(); ????
Vec3d surfacenormal; Vec3d surfacenormal;
// Calculate the surface normal at the current point // Calculate the surface normal at the current point
// with respect to the current surface element // with respect to the current surface element
@ -369,8 +390,13 @@ namespace netgen
mesh.LineSegment(j)[1] = mapto.Get(seg_p1); mesh.LineSegment(j)[1] = mapto.Get(seg_p1);
mesh.LineSegment(j)[0] = mapto.Get(seg_p2); mesh.LineSegment(j)[0] = mapto.Get(seg_p2);
if(surfangle <= 1.5707) if(surfangle <= angleThreshold * 3.141592 / 180.0)
{ {
// Since the surface is lower than the threshold, change the effective
// prism growth vector to match with the surface vector, so that
// the Quad which is created lies on the original surface
growthvectors.Elem(segpair_p1) = surfelem_vect;
// Add a quad element to account for the prism volume // Add a quad element to account for the prism volume
// element which is going to be added // element which is going to be added
Element2d sel(QUAD); Element2d sel(QUAD);
@ -521,24 +547,27 @@ namespace netgen
{ {
double sfact = 0.9; double sfact = 0.9;
Element volel = mesh.VolumeElement(vertelems.Elem(j)); Element volel = mesh.VolumeElement(vertelems.Elem(j));
if((volel.GetType() == TET) || (volel.GetType() == TET10)) if(((volel.GetType() == TET) || (volel.GetType() == TET10)) && (!volel.IsDeleted()))
{ {
while((volel.Volume(mesh.Points()) <= 0.0) && (sfact >= 0.0)) //while((volel.Volume(mesh.Points()) <= 0.0) && (sfact >= 0.0))
{ //{
mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i)));
mesh.ImproveMesh(); // mesh.ImproveMesh();
// Try to move the point back by one step but // // Try to move the point back by one step but
// if the volume drops to below zero, double back // // if the volume drops to below zero, double back
mesh.Point(i).SetPoint(pointtomove + ((sfact + 0.1) * layerht * growthvectors.Elem(i))); // mesh.Point(i).SetPoint(pointtomove + ((sfact + 0.1) * layerht * growthvectors.Elem(i)));
if(volel.Volume(mesh.Points()) <= 0.0) // if(volel.Volume(mesh.Points()) <= 0.0)
{ // {
mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i)));
} // }
sfact -= 0.1; // sfact -= 0.1;
} //}
volel.Delete();
} }
} }
mesh.Compress();
} }
else else
{ {

View File

@ -7,7 +7,7 @@ extern void InsertVirtualBoundaryLayer (Mesh & mesh);
/// Create a typical prismatic boundary layer on the given /// Create a typical prismatic boundary layer on the given
/// surfaces /// surfaces
extern void GenerateBoundaryLayer (Mesh & mesh); extern void GenerateBoundaryLayer (Mesh & mesh, MeshingParameters & mp);
#endif #endif

View File

@ -13,298 +13,298 @@ namespace netgen
extern double teterrpow; extern double teterrpow;
MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d) MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d)
{ {
int i, oldne; int i, oldne;
PointIndex pi; PointIndex pi;
int meshed; int meshed;
int cntsteps; int cntsteps;
Array<INDEX_2> connectednodes; Array<INDEX_2> connectednodes;
if (&mesh3d.LocalHFunction() == NULL) mesh3d.CalcLocalH(); if (&mesh3d.LocalHFunction() == NULL) mesh3d.CalcLocalH();
mesh3d.Compress(); mesh3d.Compress();
// mesh3d.PrintMemInfo (cout); // mesh3d.PrintMemInfo (cout);
if (mp.checkoverlappingboundary) if (mp.checkoverlappingboundary)
if (mesh3d.CheckOverlappingBoundary()) if (mesh3d.CheckOverlappingBoundary())
throw NgException ("Stop meshing since boundary mesh is overlapping"); throw NgException ("Stop meshing since boundary mesh is overlapping");
int nonconsist = 0; int nonconsist = 0;
for (int k = 1; k <= mesh3d.GetNDomains(); k++) for (int k = 1; k <= mesh3d.GetNDomains(); k++)
{ {
PrintMessage (3, "Check subdomain ", k, " / ", mesh3d.GetNDomains()); PrintMessage (3, "Check subdomain ", k, " / ", mesh3d.GetNDomains());
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
/* /*
bool res = mesh3d.CheckOverlappingBoundary(); bool res = mesh3d.CheckOverlappingBoundary();
if (res) if (res)
{ {
PrintError ("Surface is overlapping !!"); PrintError ("Surface is overlapping !!");
nonconsist = 1; nonconsist = 1;
} }
*/ */
bool res = (mesh3d.CheckConsistentBoundary() != 0); bool res = (mesh3d.CheckConsistentBoundary() != 0);
if (res) if (res)
{ {
PrintError ("Surface mesh not consistent"); PrintError ("Surface mesh not consistent");
nonconsist = 1; nonconsist = 1;
} }
} }
if (nonconsist) if (nonconsist)
{ {
PrintError ("Stop meshing since surface mesh not consistent"); PrintError ("Stop meshing since surface mesh not consistent");
throw NgException ("Stop meshing since surface mesh not consistent"); throw NgException ("Stop meshing since surface mesh not consistent");
} }
double globmaxh = mp.maxh; double globmaxh = mp.maxh;
for (int k = 1; k <= mesh3d.GetNDomains(); k++) for (int k = 1; k <= mesh3d.GetNDomains(); k++)
{ {
if (multithread.terminate) if (multithread.terminate)
break; break;
PrintMessage (2, ""); PrintMessage (2, "");
PrintMessage (1, "Meshing subdomain ", k, " of ", mesh3d.GetNDomains()); PrintMessage (1, "Meshing subdomain ", k, " of ", mesh3d.GetNDomains());
(*testout) << "Meshing subdomain " << k << endl; (*testout) << "Meshing subdomain " << k << endl;
mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k)); mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k));
mesh3d.CalcSurfacesOfNode(); mesh3d.CalcSurfacesOfNode();
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
if (!mesh3d.GetNOpenElements()) if (!mesh3d.GetNOpenElements())
continue; continue;
Box<3> domain_bbox( Box<3>::EMPTY_BOX ); Box<3> domain_bbox( Box<3>::EMPTY_BOX );
/* /*
Point<3> (1e10, 1e10, 1e10), Point<3> (1e10, 1e10, 1e10),
Point<3> (-1e10, -1e10, -1e10)); Point<3> (-1e10, -1e10, -1e10));
*/ */
for (SurfaceElementIndex sei = 0; sei < mesh3d.GetNSE(); sei++) for (SurfaceElementIndex sei = 0; sei < mesh3d.GetNSE(); sei++)
{ {
const Element2d & el = mesh3d[sei]; const Element2d & el = mesh3d[sei];
if (el.IsDeleted() ) continue; if (el.IsDeleted() ) continue;
if (mesh3d.GetFaceDescriptor(el.GetIndex()).DomainIn() == k || if (mesh3d.GetFaceDescriptor(el.GetIndex()).DomainIn() == k ||
mesh3d.GetFaceDescriptor(el.GetIndex()).DomainOut() == k) mesh3d.GetFaceDescriptor(el.GetIndex()).DomainOut() == k)
for (int j = 0; j < el.GetNP(); j++) for (int j = 0; j < el.GetNP(); j++)
domain_bbox.Add (mesh3d[el[j]]); domain_bbox.Add (mesh3d[el[j]]);
} }
domain_bbox.Increase (0.01 * domain_bbox.Diam()); domain_bbox.Increase (0.01 * domain_bbox.Diam());
for (int qstep = 1; qstep <= 3; qstep++) for (int qstep = 1; qstep <= 3; qstep++)
{ {
if (mesh3d.HasOpenQuads()) if (mesh3d.HasOpenQuads())
{ {
string rulefile = ngdir; string rulefile = ngdir;
const char ** rulep = NULL; const char ** rulep = NULL;
switch (qstep) switch (qstep)
{ {
case 1: case 1:
rulefile += "/rules/prisms2.rls"; rulefile += "/rules/prisms2.rls";
rulep = prismrules2; rulep = prismrules2;
break; break;
case 2: // connect pyramid to triangle case 2: // connect pyramid to triangle
rulefile += "/rules/pyramids2.rls"; rulefile += "/rules/pyramids2.rls";
rulep = pyramidrules2; rulep = pyramidrules2;
break; break;
case 3: // connect to vis-a-vis point case 3: // connect to vis-a-vis point
rulefile += "/rules/pyramids.rls"; rulefile += "/rules/pyramids.rls";
rulep = pyramidrules; rulep = pyramidrules;
break; break;
} }
// Meshing3 meshing(rulefile); // Meshing3 meshing(rulefile);
Meshing3 meshing(rulep); Meshing3 meshing(rulep);
MeshingParameters mpquad = mp; MeshingParameters mpquad = mp;
mpquad.giveuptol = 15; mpquad.giveuptol = 15;
mpquad.baseelnp = 4; mpquad.baseelnp = 4;
mpquad.starshapeclass = 1000; mpquad.starshapeclass = 1000;
mpquad.check_impossible = qstep == 1; // for prisms only (air domain in trafo) mpquad.check_impossible = qstep == 1; // for prisms only (air domain in trafo)
for (pi = PointIndex::BASE; for (pi = PointIndex::BASE;
pi < mesh3d.GetNP()+PointIndex::BASE; pi++) pi < mesh3d.GetNP()+PointIndex::BASE; pi++)
meshing.AddPoint (mesh3d[pi], pi); meshing.AddPoint (mesh3d[pi], pi);
mesh3d.GetIdentifications().GetPairs (0, connectednodes); mesh3d.GetIdentifications().GetPairs (0, connectednodes);
for (i = 1; i <= connectednodes.Size(); i++) for (i = 1; i <= connectednodes.Size(); i++)
meshing.AddConnectedPair (connectednodes.Get(i)); meshing.AddConnectedPair (connectednodes.Get(i));
for (i = 1; i <= mesh3d.GetNOpenElements(); i++) for (i = 1; i <= mesh3d.GetNOpenElements(); i++)
{ {
Element2d hel = mesh3d.OpenElement(i); Element2d hel = mesh3d.OpenElement(i);
meshing.AddBoundaryElement (hel); meshing.AddBoundaryElement (hel);
} }
oldne = mesh3d.GetNE(); oldne = mesh3d.GetNE();
meshing.GenerateMesh (mesh3d, mpquad); meshing.GenerateMesh (mesh3d, mpquad);
for (i = oldne + 1; i <= mesh3d.GetNE(); i++) for (i = oldne + 1; i <= mesh3d.GetNE(); i++)
mesh3d.VolumeElement(i).SetIndex (k); mesh3d.VolumeElement(i).SetIndex (k);
(*testout) (*testout)
<< "mesh has " << mesh3d.GetNE() << " prism/pyramid elements" << endl; << "mesh has " << mesh3d.GetNE() << " prism/pyramid elements" << endl;
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
} }
} }
if (mesh3d.HasOpenQuads()) if (mesh3d.HasOpenQuads())
{ {
PrintSysError ("mesh has still open quads"); PrintSysError ("mesh has still open quads");
throw NgException ("Stop meshing since too many attempts"); throw NgException ("Stop meshing since too many attempts");
// return MESHING3_GIVEUP; // return MESHING3_GIVEUP;
} }
if (mp.delaunay && mesh3d.GetNOpenElements()) if (mp.delaunay && mesh3d.GetNOpenElements())
{ {
Meshing3 meshing((const char**)NULL); Meshing3 meshing((const char**)NULL);
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
for (pi = PointIndex::BASE; for (pi = PointIndex::BASE;
pi < mesh3d.GetNP()+PointIndex::BASE; pi++) pi < mesh3d.GetNP()+PointIndex::BASE; pi++)
meshing.AddPoint (mesh3d[pi], pi); meshing.AddPoint (mesh3d[pi], pi);
for (i = 1; i <= mesh3d.GetNOpenElements(); i++) for (i = 1; i <= mesh3d.GetNOpenElements(); i++)
meshing.AddBoundaryElement (mesh3d.OpenElement(i)); meshing.AddBoundaryElement (mesh3d.OpenElement(i));
oldne = mesh3d.GetNE(); oldne = mesh3d.GetNE();
meshing.Delaunay (mesh3d, k, mp); meshing.Delaunay (mesh3d, k, mp);
for (i = oldne + 1; i <= mesh3d.GetNE(); i++) for (i = oldne + 1; i <= mesh3d.GetNE(); i++)
mesh3d.VolumeElement(i).SetIndex (k); mesh3d.VolumeElement(i).SetIndex (k);
PrintMessage (3, mesh3d.GetNP(), " points, ", PrintMessage (3, mesh3d.GetNP(), " points, ",
mesh3d.GetNE(), " elements"); mesh3d.GetNE(), " elements");
} }
cntsteps = 0; cntsteps = 0;
if (mesh3d.GetNOpenElements()) if (mesh3d.GetNOpenElements())
do do
{ {
if (multithread.terminate) if (multithread.terminate)
break; break;
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
PrintMessage (5, mesh3d.GetNOpenElements(), " open faces"); PrintMessage (5, mesh3d.GetNOpenElements(), " open faces");
cntsteps++; cntsteps++;
if (cntsteps > mp.maxoutersteps) if (cntsteps > mp.maxoutersteps)
throw NgException ("Stop meshing since too many attempts"); throw NgException ("Stop meshing since too many attempts");
string rulefile = ngdir + "/tetra.rls"; string rulefile = ngdir + "/tetra.rls";
PrintMessage (1, "start tetmeshing"); PrintMessage (1, "start tetmeshing");
// Meshing3 meshing(rulefile); // Meshing3 meshing(rulefile);
Meshing3 meshing(tetrules); Meshing3 meshing(tetrules);
Array<int, PointIndex::BASE> glob2loc(mesh3d.GetNP()); Array<int, PointIndex::BASE> glob2loc(mesh3d.GetNP());
glob2loc = -1; glob2loc = -1;
for (pi = PointIndex::BASE; for (pi = PointIndex::BASE;
pi < mesh3d.GetNP()+PointIndex::BASE; pi++) pi < mesh3d.GetNP()+PointIndex::BASE; pi++)
if (domain_bbox.IsIn (mesh3d[pi])) if (domain_bbox.IsIn (mesh3d[pi]))
glob2loc[pi] = glob2loc[pi] =
meshing.AddPoint (mesh3d[pi], pi); meshing.AddPoint (mesh3d[pi], pi);
for (i = 1; i <= mesh3d.GetNOpenElements(); i++) for (i = 1; i <= mesh3d.GetNOpenElements(); i++)
{ {
Element2d hel = mesh3d.OpenElement(i); Element2d hel = mesh3d.OpenElement(i);
for (int j = 0; j < hel.GetNP(); j++) for (int j = 0; j < hel.GetNP(); j++)
hel[j] = glob2loc[hel[j]]; hel[j] = glob2loc[hel[j]];
meshing.AddBoundaryElement (hel); meshing.AddBoundaryElement (hel);
// meshing.AddBoundaryElement (mesh3d.OpenElement(i)); // meshing.AddBoundaryElement (mesh3d.OpenElement(i));
} }
oldne = mesh3d.GetNE(); oldne = mesh3d.GetNE();
mp.giveuptol = 15 + 10 * cntsteps; mp.giveuptol = 15 + 10 * cntsteps;
mp.sloppy = 5; mp.sloppy = 5;
meshing.GenerateMesh (mesh3d, mp); meshing.GenerateMesh (mesh3d, mp);
for (ElementIndex ei = oldne; ei < mesh3d.GetNE(); ei++) for (ElementIndex ei = oldne; ei < mesh3d.GetNE(); ei++)
mesh3d[ei].SetIndex (k); mesh3d[ei].SetIndex (k);
mesh3d.CalcSurfacesOfNode(); mesh3d.CalcSurfacesOfNode();
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
teterrpow = 2; teterrpow = 2;
if (mesh3d.GetNOpenElements() != 0) if (mesh3d.GetNOpenElements() != 0)
{ {
meshed = 0; meshed = 0;
PrintMessage (5, mesh3d.GetNOpenElements(), " open faces found"); PrintMessage (5, mesh3d.GetNOpenElements(), " open faces found");
// mesh3d.Save ("tmp.vol"); // mesh3d.Save ("tmp.vol");
MeshOptimize3d optmesh; MeshOptimize3d optmesh;
const char * optstr = "mcmstmcmstmcmstmcm"; const char * optstr = "mcmstmcmstmcmstmcm";
size_t j; size_t j;
for (j = 1; j <= strlen(optstr); j++) for (j = 1; j <= strlen(optstr); j++)
{ {
mesh3d.CalcSurfacesOfNode(); mesh3d.CalcSurfacesOfNode();
mesh3d.FreeOpenElementsEnvironment(2); mesh3d.FreeOpenElementsEnvironment(2);
mesh3d.CalcSurfacesOfNode(); mesh3d.CalcSurfacesOfNode();
switch (optstr[j-1]) switch (optstr[j-1])
{ {
case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break;
case 'd': optmesh.SplitImprove(mesh3d, OPT_REST); break; case 'd': optmesh.SplitImprove(mesh3d, OPT_REST); break;
case 's': optmesh.SwapImprove(mesh3d, OPT_REST); break; case 's': optmesh.SwapImprove(mesh3d, OPT_REST); break;
case 't': optmesh.SwapImprove2(mesh3d, OPT_REST); break; case 't': optmesh.SwapImprove2(mesh3d, OPT_REST); break;
case 'm': mesh3d.ImproveMesh(OPT_REST); break; case 'm': mesh3d.ImproveMesh(OPT_REST); break;
} }
} }
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
PrintMessage (3, "Call remove problem"); PrintMessage (3, "Call remove problem");
RemoveProblem (mesh3d, k); RemoveProblem (mesh3d, k);
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);
} }
else else
{ {
meshed = 1; meshed = 1;
PrintMessage (1, "Success !"); PrintMessage (1, "Success !");
} }
} }
while (!meshed); while (!meshed);
PrintMessage (1, mesh3d.GetNP(), " points, ", PrintMessage (1, mesh3d.GetNP(), " points, ",
mesh3d.GetNE(), " elements"); mesh3d.GetNE(), " elements");
} }
mp.maxh = globmaxh; mp.maxh = globmaxh;
MeshQuality3d (mesh3d); MeshQuality3d (mesh3d);
return MESHING3_OK; return MESHING3_OK;
} }

View File

@ -399,7 +399,7 @@ namespace netgen
} }
const string filename (argv[1]); const string filename (argv[1]);
PrintMessage (1, "Save mesh to file ", filename); PrintMessage (1, "Save mesh to file ", filename, ".... Please Wait!");
ofstream outfile(filename.c_str()); ofstream outfile(filename.c_str());
mesh -> Save (outfile); mesh -> Save (outfile);
@ -408,6 +408,7 @@ namespace netgen
if (geometry && geometry->GetNSurf()) geometry->SaveSurfaces(outfile); if (geometry && geometry->GetNSurf()) geometry->SaveSurfaces(outfile);
PrintMessage (1, "Save mesh to file .... DONE!");
return TCL_OK; return TCL_OK;
} }
@ -465,6 +466,7 @@ namespace netgen
string filename (argv[1]); string filename (argv[1]);
string filetype (argv[2]); string filetype (argv[2]);
PrintMessage (1, "Export mesh to file ", filename, ".... Please Wait!");
if (WriteUserFormat (filetype, *mesh, *geometry, filename)) if (WriteUserFormat (filetype, *mesh, *geometry, filename))
{ {
@ -474,6 +476,7 @@ namespace netgen
return TCL_ERROR; return TCL_ERROR;
} }
PrintMessage (1, "Export mesh to file .... DONE!");
return TCL_OK; return TCL_OK;
} }
@ -1868,7 +1871,7 @@ namespace netgen
return TCL_ERROR; return TCL_ERROR;
} }
GenerateBoundaryLayer (*mesh); GenerateBoundaryLayer (*mesh, mparam);
return TCL_OK; return TCL_OK;
} }