Mesh *StockMeshes::NewSphereMesh(float width, float height, float depth, const Color &color, int precision, const Texture *texture) { Mesh *result = new Mesh(precision*precision+2, 2*precision*precision, true, true, true); float w = width/2, h = height/2, d = depth/2; // Create points result->AddPoint(Point3(0, h, 0), Point3(0, h, 0), color, 0.5f, 0); for (int i = 0; i < precision; i++) for (int j = 0; j < precision; j++) { float v = float(i+1) / (precision+1); float u = float(j) / precision; float r = sin(v*kPi); Point3 p(-cos(2*u*kPi)*w*r, cos(v*kPi)*h, sin(2*u*kPi)*w*d*r); result->AddPoint(p, p, color, u, v); } result->AddPoint(Point3(0, -h, 0), Point3(0, -h, 0), color, 0.5f, 0); // Create triangles for (int j = 0; j < precision; j++) { int j2 = (j+1) % precision; result->AddTriangle(0, 1 + j, 1 + j2, texture); } for (int i = 0; i < precision-1; i++) for (int j = 0; j < precision; j++) { int j2 = (j+1) % precision; result->AddTriangle(1 + i*precision + j, 1 + (i+1)*precision + j, 1 + (i+1)*precision + j2, texture); result->AddTriangle(1 + i*precision + j, 1 + (i+1)*precision + j2, 1 + i*precision + j2, texture); } for (int j = 0; j < precision; j++) { int j2 = (j+1) % precision; result->AddTriangle(precision*(precision-1) + j + 1, 1 + precision*precision, precision*(precision-1) + j2 + 1, texture); } return result; }
void Meshing2 :: BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp) { double filldist = mp.filldist; cout << "blockfill local h" << endl; cout << "rel filldist = " << filldist << endl; PrintMessage (3, "blockfill local h"); Array<Point<3> > npoints; // adfront -> CreateTrees(); Box<3> bbox ( Box<3>::EMPTY_BOX ); double maxh = 0; for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine (i); const Point<3> & p1 = adfront->GetPoint(line.L().I1()); const Point<3> & p2 = adfront->GetPoint(line.L().I2()); double hi = Dist (p1, p2); if (hi > maxh) maxh = hi; bbox.Add (p1); bbox.Add (p2); } cout << "bbox = " << bbox << endl; // Point<3> mpc = bbox.Center(); bbox.Increase (bbox.Diam()/2); Box<3> meshbox = bbox; LocalH loch2 (bbox, 1); if (mp.maxh < maxh) maxh = mp.maxh; bool changed; do { mesh.LocalHFunction().ClearFlags(); for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine(i); Box<3> bbox (adfront->GetPoint (line.L().I1())); bbox.Add (adfront->GetPoint (line.L().I2())); double filld = filldist * bbox.Diam(); bbox.Increase (filld); mesh.LocalHFunction().CutBoundary (bbox); } mesh.LocalHFunction().FindInnerBoxes (adfront, NULL); npoints.SetSize(0); mesh.LocalHFunction().GetInnerPoints (npoints); changed = false; for (int i = 0; i < npoints.Size(); i++) { if (mesh.LocalHFunction().GetH(npoints[i]) > 1.5 * maxh) { mesh.LocalHFunction().SetH (npoints[i], maxh); changed = true; } } } while (changed); if (debugparam.slowchecks) (*testout) << "Blockfill with points: " << endl; *testout << "loch = " << mesh.LocalHFunction() << endl; *testout << "npoints = " << endl << npoints << endl; for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn (npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint (npoints.Get(i)); adfront->AddPoint (npoints.Get(i), gpnum); if (debugparam.slowchecks) { (*testout) << npoints.Get(i) << endl; Point<2> p2d (npoints.Get(i)(0), npoints.Get(i)(1)); if (!adfront->Inside(p2d)) { cout << "add outside point" << endl; (*testout) << "outside" << endl; } } } } // find outer points loch2.ClearFlags(); for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine(i); Box<3> bbox (adfront->GetPoint (line.L().I1())); bbox.Add (adfront->GetPoint (line.L().I2())); loch2.SetH (bbox.Center(), bbox.Diam()); } for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine(i); Box<3> bbox (adfront->GetPoint (line.L().I1())); bbox.Add (adfront->GetPoint (line.L().I2())); bbox.Increase (filldist * bbox.Diam()); loch2.CutBoundary (bbox); } loch2.FindInnerBoxes (adfront, NULL); npoints.SetSize(0); loch2.GetOuterPoints (npoints); for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn (npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint (npoints.Get(i)); adfront->AddPoint (npoints.Get(i), gpnum); } } }
/* ------------------ 2D Meshing Functions ------------------------- */ DLL_HEADER void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x) { Mesh * m = (Mesh*)mesh; m->AddPoint (Point3d (x[0], x[1], 0)); }
Mesh *StockMeshes::NewBoxMesh(float width, float height, float depth, const Color &color, const Texture *texture) { float x = width/2, y = height/2, z = depth/2; Mesh *result = new Mesh(24, 12, true, true, true); // Top face result->AddPoint(Point3(-x, y, -z), Point3(0, 1, 0), color, 0, 1); result->AddPoint(Point3(-x, y, z), Point3(0, 1, 0), color, 0, 0); result->AddPoint(Point3( x, y, z), Point3(0, 1, 0), color, 1, 0); result->AddPoint(Point3( x, y, -z), Point3(0, 1, 0), color, 1, 1); result->AddTriangle(0, 1, 2, texture); result->AddTriangle(0, 2, 3, texture); // Front face result->AddPoint(Point3(-x, -y, -z), Point3(0, 0, -1), color, 0, 1); result->AddPoint(Point3(-x, y, -z), Point3(0, 0, -1), color, 0, 0); result->AddPoint(Point3( x, y, -z), Point3(0, 0, -1), color, 1, 0); result->AddPoint(Point3( x, -y, -z), Point3(0, 0, -1), color, 1, 1); result->AddTriangle(4, 5, 6, texture); result->AddTriangle(4, 6, 7, texture); // Left face result->AddPoint(Point3(-x, -y, z), Point3(-1, 0, 0), color, 0, 1); result->AddPoint(Point3(-x, y, z), Point3(-1, 0, 0), color, 0, 0); result->AddPoint(Point3(-x, y, -z), Point3(-1, 0, 0), color, 1, 0); result->AddPoint(Point3(-x, -y, -z), Point3(-1, 0, 0), color, 1, 1); result->AddTriangle(8, 9, 10, texture); result->AddTriangle(8, 10, 11, texture); // Back face result->AddPoint(Point3( x, -y, z), Point3(0, 0, 1), color, 0, 1); result->AddPoint(Point3( x, y, z), Point3(0, 0, 1), color, 0, 0); result->AddPoint(Point3(-x, y, z), Point3(0, 0, 1), color, 1, 0); result->AddPoint(Point3(-x, -y, z), Point3(0, 0, 1), color, 1, 1); result->AddTriangle(12, 13, 14, texture); result->AddTriangle(12, 14, 15, texture); // Right face result->AddPoint(Point3( x, -y, -z), Point3(1, 0, 0), color, 0, 1); result->AddPoint(Point3( x, y, -z), Point3(1, 0, 0), color, 0, 0); result->AddPoint(Point3( x, y, z), Point3(1, 0, 0), color, 1, 0); result->AddPoint(Point3( x, -y, z), Point3(1, 0, 0), color, 1, 1); result->AddTriangle(16, 17, 18, texture); result->AddTriangle(16, 18, 19, texture); // Bottom face result->AddPoint(Point3(-x, -y, z), Point3(0, -1, 0), color, 0, 1); result->AddPoint(Point3(-x, -y, -z), Point3(0, -1, 0), color, 0, 0); result->AddPoint(Point3( x, -y, -z), Point3(0, -1, 0), color, 1, 0); result->AddPoint(Point3( x, -y, z), Point3(0, -1, 0), color, 1, 1); result->AddTriangle(20, 21, 22, texture); result->AddTriangle(20, 22, 23, texture); return result; }
void RefinePrisms (Mesh & mesh, const CSGeometry * geom, ZRefinementOptions & opt) { int i, j; bool found, change; int cnt = 0; // markers for z-refinement: p1, p2, levels // p1-p2 is an edge to be refined ARRAY<INDEX_3> ref_uniform; ARRAY<INDEX_3> ref_singular; ARRAY<INDEX_4 > ref_slices; BitArray first_id(geom->identifications.Size()); first_id.Set(); INDEX_2_HASHTABLE<int> & identpts = mesh.GetIdentifications().GetIdentifiedPoints (); if (&identpts) { for (i = 1; i <= identpts.GetNBags(); i++) for (j = 1; j <= identpts.GetBagSize(i); j++) { INDEX_2 pair; int idnr; identpts.GetData(i, j, pair, idnr); const CloseSurfaceIdentification * csid = dynamic_cast<const CloseSurfaceIdentification*> (geom->identifications.Get(idnr)); if (csid) { if (!csid->GetSlices().Size()) { if (first_id.Test (idnr)) { first_id.Clear(idnr); ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels())); ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1())); ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2())); } } else { //const ARRAY<double> & slices = csid->GetSlices(); INDEX_4 i4; i4[0] = pair.I1(); i4[1] = pair.I2(); i4[2] = idnr; i4[3] = csid->GetSlices().Size(); ref_slices.Append (i4); } } } } ARRAY<EdgePointGeomInfo> epgi; while (1) { cnt++; PrintMessage (3, "Z-Refinement, level = ", cnt); INDEX_2_HASHTABLE<int> refedges(mesh.GetNSE()+1); found = 0; // mark prisms due to close surface flags: int oldsize = ref_uniform.Size(); for (i = 1; i <= oldsize; i++) { int pi1 = ref_uniform.Get(i).I1(); int pi2 = ref_uniform.Get(i).I2(); int levels = ref_uniform.Get(i).I3(); if (levels > 0) { const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); int npi(0); INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } ref_uniform.Elem(i) = INDEX_3(pi1, npi, levels-1); ref_uniform.Append (INDEX_3(pi2, npi, levels-1)); } } for (i = 1; i <= ref_singular.Size(); i++) { int pi1 = ref_singular.Get(i).I1(); int pi2 = ref_singular.Get(i).I2(); int levels = ref_singular.Get(i).I3(); if (levels > 0) { const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); int npi; INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } else npi = refedges.Get (edge); ref_singular.Elem(i) = INDEX_3(pi1, npi, levels-1); } } for (i = 1; i <= ref_slices.Size(); i++) { int pi1 = ref_slices.Get(i)[0]; int pi2 = ref_slices.Get(i)[1]; int idnr = ref_slices.Get(i)[2]; int slicenr = ref_slices.Get(i)[3]; if (slicenr > 0) { const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); int npi; const CloseSurfaceIdentification * csid = dynamic_cast<const CloseSurfaceIdentification*> (geom->identifications.Get(idnr)); INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { const ARRAY<double> & slices = csid->GetSlices(); //(*testout) << "idnr " << idnr << " i " << i << endl; //(*testout) << "slices " << slices << endl; double slicefac = slices.Get(slicenr); double slicefaclast = (slicenr == slices.Size()) ? 1 : slices.Get(slicenr+1); Point3d np = p1 + (slicefac / slicefaclast) * (p2-p1); //(*testout) << "slicenr " << slicenr << " slicefac " << slicefac << " quot " << (slicefac / slicefaclast) << " np " << np << endl; npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } else npi = refedges.Get (edge); ref_slices.Elem(i)[1] = npi; ref_slices.Elem(i)[3] --; } } for (i = 1; i <= mesh.GetNE(); i++) { Element & el = mesh.VolumeElement (i); if (el.GetType() != PRISM) continue; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); bool ref = 0; /* if (Dist (p1, p2) > mesh.GetH (Center (p1, p2))) ref = 1; */ /* if (cnt <= opt.minref) ref = 1; */ /* if ((pi1 == 460 || pi2 == 460 || pi1 == 461 || pi2 == 461) && cnt <= 8) ref = 1; */ if (ref == 1) { INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); int npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } } } } if (!found) break; // build closure: PrintMessage (5, "start closure"); do { PrintMessage (5, "start loop"); change = 0; for (i = 1; i <= mesh.GetNE(); i++) { Element & el = mesh.VolumeElement (i); if (el.GetType() != PRISM) continue; bool hasref = 0, hasnonref = 0; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); if (pi1 != pi2) { INDEX_2 edge(pi1, pi2); edge.Sort(); if (refedges.Used(edge)) hasref = 1; else hasnonref = 1; } } if (hasref && hasnonref) { // cout << "el " << i << " in closure" << endl; change = 1; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); int npi = mesh.AddPoint (np); refedges.Set (edge, npi); } } } } } while (change); PrintMessage (5, "Do segments"); // (*testout) << "closure formed, np = " << mesh.GetNP() << endl; int oldns = mesh.GetNSeg(); for (i = 1; i <= oldns; i++) { const Segment & el = mesh.LineSegment(i); INDEX_2 i2(el.p1, el.p2); i2.Sort(); int pnew; EdgePointGeomInfo ngi; if (refedges.Used(i2)) { pnew = refedges.Get(i2); // ngi = epgi.Get(pnew); } else { continue; // Point3d pb; // /* // geom->PointBetween (mesh.Point (el.p1), // mesh.Point (el.p2), // el.surfnr1, el.surfnr2, // el.epgeominfo[0], el.epgeominfo[1], // pb, ngi); // */ // pb = Center (mesh.Point (el.p1), mesh.Point (el.p2)); // pnew = mesh.AddPoint (pb); // refedges.Set (i2, pnew); // if (pnew > epgi.Size()) // epgi.SetSize (pnew); // epgi.Elem(pnew) = ngi; } Segment ns1 = el; Segment ns2 = el; ns1.p2 = pnew; ns1.epgeominfo[1] = ngi; ns2.p1 = pnew; ns2.epgeominfo[0] = ngi; mesh.LineSegment(i) = ns1; mesh.AddSegment (ns2); } PrintMessage (5, "Segments done, NSeg = ", mesh.GetNSeg()); // do refinement int oldne = mesh.GetNE(); for (i = 1; i <= oldne; i++) { Element & el = mesh.VolumeElement (i); if (el.GetNP() != 6) continue; int npi[3]; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); if (pi1 == pi2) npi[j-1] = pi1; else { INDEX_2 edge(pi1, pi2); edge.Sort(); if (refedges.Used (edge)) npi[j-1] = refedges.Get(edge); else { /* (*testout) << "ERROR: prism " << i << " has hanging node !!" << ", edge = " << edge << endl; cerr << "ERROR: prism " << i << " has hanging node !!" << endl; */ npi[j-1] = 0; } } } if (npi[0]) { Element nel1(6), nel2(6); for (j = 1; j <= 3; j++) { nel1.PNum(j) = el.PNum(j); nel1.PNum(j+3) = npi[j-1]; nel2.PNum(j) = npi[j-1]; nel2.PNum(j+3) = el.PNum(j+3); } nel1.SetIndex (el.GetIndex()); nel2.SetIndex (el.GetIndex()); mesh.VolumeElement (i) = nel1; mesh.AddVolumeElement (nel2); } } PrintMessage (5, "Elements done, NE = ", mesh.GetNE()); // do surface elements int oldnse = mesh.GetNSE(); // cout << "oldnse = " << oldnse << endl; for (i = 1; i <= oldnse; i++) { Element2d & el = mesh.SurfaceElement (i); if (el.GetType() != QUAD) continue; int index = el.GetIndex(); int npi[2]; for (j = 1; j <= 2; j++) { int pi1, pi2; if (j == 1) { pi1 = el.PNum(1); pi2 = el.PNum(4); } else { pi1 = el.PNum(2); pi2 = el.PNum(3); } if (pi1 == pi2) npi[j-1] = pi1; else { INDEX_2 edge(pi1, pi2); edge.Sort(); if (refedges.Used (edge)) npi[j-1] = refedges.Get(edge); else { npi[j-1] = 0; } } } if (npi[0]) { Element2d nel1(QUAD), nel2(QUAD); for (j = 1; j <= 4; j++) { nel1.PNum(j) = el.PNum(j); nel2.PNum(j) = el.PNum(j); } nel1.PNum(3) = npi[1]; nel1.PNum(4) = npi[0]; nel2.PNum(1) = npi[0]; nel2.PNum(2) = npi[1]; /* for (j = 1; j <= 2; j++) { nel1.PNum(j) = el.PNum(j); nel1.PNum(j+2) = npi[j-1]; nel2.PNum(j) = npi[j-1]; nel2.PNum(j+2) = el.PNum(j+2); } */ nel1.SetIndex (el.GetIndex()); nel2.SetIndex (el.GetIndex()); mesh.SurfaceElement (i) = nel1; mesh.AddSurfaceElement (nel2); int si = mesh.GetFaceDescriptor (index).SurfNr(); Point<3> hp = mesh.Point(npi[0]); geom->GetSurface(si)->Project (hp); mesh.Point (npi[0]).SetPoint (hp); hp = mesh.Point(npi[1]); geom->GetSurface(si)->Project (hp); mesh.Point (npi[1]).SetPoint (hp); // geom->GetSurface(si)->Project (mesh.Point(npi[0])); // geom->GetSurface(si)->Project (mesh.Point(npi[1])); } } PrintMessage (5, "Surface elements done, NSE = ", mesh.GetNSE()); } }
/* Philippose Rajan - 11 June 2009 Added an initial experimental function for generating prismatic boundary layers on a given set of surfaces. The number of layers, height of the first layer and the growth / shrink factor can be specified by the user Currently, the layer height is calculated using: height = h_first_layer * (growth_factor^(num_layers - 1)) */ void GenerateBoundaryLayer (Mesh & mesh, MeshingParameters & mp) { int i, j; ofstream dbg("BndLayerDebug.log"); // 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 = 5.0; cout << "Generate Prismatic Boundary Layers (Experimental)...." << endl; // Use an array to support creation of boundary // layers for multiple surfaces in the future... Array<int> surfid; int surfinp = 0; int prismlayers = 1; double hfirst = 0.01; double growthfactor = 1.0; // Monitor and print out the number of prism and quad elements // added to the mesh int numprisms = 0; int numquads = 0; while(surfinp >= 0) { cout << "Enter Surface ID (-1 to end list): "; cin >> surfinp; if(surfinp >= 0) surfid.Append(surfinp); } 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: "; cin >> prismlayers; if(prismlayers < 1) prismlayers = 1; cout << "Enter height of first layer: "; cin >> hfirst; if(hfirst <= 0.0) hfirst = 0.01; cout << "Enter layer growth / shrink factor: "; cin >> growthfactor; if(growthfactor <= 0.0) growthfactor = 0.5; cout << "Old NP: " << mesh.GetNP() << endl; cout << "Old NSE: " << mesh.GetNSE() << endl; for(int layer = prismlayers; layer >= 1; layer--) { cout << "Generating layer: " << layer << endl; const MeshTopology& meshtopo = mesh.GetTopology(); const_cast<MeshTopology &> (meshtopo).SetBuildEdges(true); const_cast<MeshTopology &> (meshtopo).SetBuildFaces(true); const_cast<MeshTopology &> (meshtopo).Update(); double layerht = hfirst; 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 // surface elements because there are new points and // surface elements being added during the process int np = mesh.GetNP(); int nse = mesh.GetNSE(); // Safety measure to ensure no issues with mesh // consistency int nseg = mesh.GetNSeg(); // Indicate which points need to be remapped BitArray bndnodes(np); // Map of the old points to the new points Array<int> mapto(np); // Growth vectors for the prismatic layer based on // the effective surface normal at a given point Array<Vec3d> growthvectors(np); // Bit array to identify all the points belonging // to the surface of interest bndnodes.Clear(); // Run through all the surface elements and mark the points // belonging to those where a boundary layer has to be created. // In addition, also calculate the effective surface normal // vectors at each of those points to determine the mesh motion // direction cout << "Marking points for remapping...." << endl; for (i = 1; i <= nse; i++) { int snr = mesh.SurfaceElement(i).GetIndex(); // cout << "snr = " << snr << endl; if (surfid.Contains(snr)) { Element2d & sel = mesh.SurfaceElement(i); int selNP = sel.GetNP(); for(j = 1; j <= selNP; j++) { // Set the bitarray to indicate that the // point is part of the required set bndnodes.Set(sel.PNum(j)); // Vec3d& surfacenormal = Vec3d(); ???? Vec3d surfacenormal; // Calculate the surface normal at the current point // with respect to the current surface element GetSurfaceNormal(mesh,sel,j,surfacenormal); // Add the surface normal to the already existent one // (This gives the effective normal direction at corners // and curved areas) growthvectors.Elem(sel.PNum(j)) = growthvectors.Elem(sel.PNum(j)) + surfacenormal; } } } // Add additional points into the mesh structure in order to // clone the surface elements. // Also invert the growth vectors so that they point inwards, // and normalize them cout << "Cloning points and calculating growth vectors...." << endl; for (i = 1; i <= np; i++) { if (bndnodes.Test(i)) { mapto.Elem(i) = mesh.AddPoint (mesh.Point (i)); growthvectors.Elem(i).Normalize(); growthvectors.Elem(i) *= -1.0; } else { mapto.Elem(i) = 0; growthvectors.Elem(i) = Vec3d(0,0,0); } } // Add quad surface elements at edges for surfaces which // dont have boundary layers // Bit array to keep track of segments already processed BitArray segsel(nseg); // Set them all to "1" to initially activate all segments segsel.Set(); cout << "Adding 2D Quad elements on required surfaces...." << endl; for (i = 1; i <= nseg; i++) { int seg_p1 = mesh.LineSegment(i)[0]; int seg_p2 = mesh.LineSegment(i)[1]; // Only go in if the segment is still active, and if both its // surface index is part of the "hit-list" if(segsel.Test(i) && surfid.Contains(mesh.LineSegment(i).si)) { // clear the bit to indicate that this segment has been processed segsel.Clear(i); // Find matching segment pair on other surface for(j = 1; j <= nseg; j++) { int segpair_p1 = mesh.LineSegment(j)[1]; int segpair_p2 = mesh.LineSegment(j)[0]; // Find the segment pair on the neighbouring surface element // Identified by: seg1[0] = seg_pair[1] and seg1[1] = seg_pair[0] if(segsel.Test(j) && ((segpair_p1 == seg_p1) && (segpair_p2 == seg_p2))) { // clear bit to indicate that processing of this segment is done segsel.Clear(j); // Only worry about those surfaces which are not in the // boundary layer list if(!surfid.Contains(mesh.LineSegment(j).si)) { int pnt_commelem = 0; int pnum_commelem = 0; Array<int> pnt1_elems; Array<int> pnt2_elems; meshtopo.GetVertexSurfaceElements(segpair_p1,pnt1_elems); meshtopo.GetVertexSurfaceElements(segpair_p2,pnt2_elems); for(int k = 1; k <= pnt1_elems.Size(); k++) { Element2d pnt1_sel = mesh.SurfaceElement(pnt1_elems.Elem(k)); for(int l = 1; l <= pnt2_elems.Size(); l++) { Element2d pnt2_sel = mesh.SurfaceElement(pnt2_elems.Elem(l)); if((pnt1_sel.GetIndex() == mesh.LineSegment(j).si) && (pnt2_sel.GetIndex() == mesh.LineSegment(j).si) && (pnt1_elems.Elem(k) == pnt2_elems.Elem(l))) { pnt_commelem = pnt1_elems.Elem(k); } } } for(int k = 1; k <= mesh.SurfaceElement(pnt_commelem).GetNP(); k++) { if((mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p1) && (mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p2)) { pnum_commelem = mesh.SurfaceElement(pnt_commelem).PNum(k); } } Vec3d surfelem_vect, surfelem_vect1; Element2d & commsel = mesh.SurfaceElement(pnt_commelem); dbg << "NP= " << commsel.GetNP() << " : "; for(int k = 1; k <= commsel.GetNP(); k++) { GetSurfaceNormal(mesh,commsel,k,surfelem_vect1); surfelem_vect += surfelem_vect1; } surfelem_vect.Normalize(); double surfangle = Angle(growthvectors.Elem(segpair_p1),surfelem_vect); dbg << "V1= " << surfelem_vect1 << " : V2= " << surfelem_vect1 << " : V= " << surfelem_vect << " : GV= " << growthvectors.Elem(segpair_p1) << " : Angle= " << surfangle * 180 / 3.141592; // remap the segments to the new points mesh.LineSegment(i)[0] = mapto.Get(seg_p1); mesh.LineSegment(i)[1] = mapto.Get(seg_p2); mesh.LineSegment(j)[1] = mapto.Get(seg_p1); mesh.LineSegment(j)[0] = mapto.Get(seg_p2); if((surfangle < (90 + angleThreshold) * 3.141592 / 180.0) && (surfangle > (90 - angleThreshold) * 3.141592 / 180.0)) { dbg << " : quad\n"; // 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 // element which is going to be added Element2d sel(QUAD); sel.PNum(4) = mapto.Get(seg_p1); sel.PNum(3) = mapto.Get(seg_p2); sel.PNum(2) = segpair_p2; sel.PNum(1) = segpair_p1; sel.SetIndex(mesh.LineSegment(j).si); mesh.AddSurfaceElement(sel); numquads++; } else { dbg << "\n"; for (int k = 1; k <= pnt1_elems.Size(); k++) { Element2d & pnt_sel = mesh.SurfaceElement(pnt1_elems.Elem(k)); if(pnt_sel.GetIndex() == mesh.LineSegment(j).si) { for(int l = 1; l <= pnt_sel.GetNP(); l++) { if(pnt_sel.PNum(l) == segpair_p1) { pnt_sel.PNum(l) = mapto.Get(seg_p1); } else if(pnt_sel.PNum(l) == segpair_p2) { pnt_sel.PNum(l) = mapto.Get(seg_p2); } } } } for (int k = 1; k <= pnt2_elems.Size(); k++) { Element2d & pnt_sel = mesh.SurfaceElement(pnt2_elems.Elem(k)); if(pnt_sel.GetIndex() == mesh.LineSegment(j).si) { for(int l = 1; l <= pnt_sel.GetNP(); l++) { if(pnt_sel.PNum(l) == segpair_p1) { pnt_sel.PNum(l) = mapto.Get(seg_p1); } else if(pnt_sel.PNum(l) == segpair_p2) { pnt_sel.PNum(l) = mapto.Get(seg_p2); } } } } } } else { // If the code comes here, it indicates that we are at // a line segment pair which is at the intersection // of two surfaces, both of which have to grow boundary // layers.... here too, remapping the segments to the // new points is required mesh.LineSegment(i)[0] = mapto.Get(seg_p1); mesh.LineSegment(i)[1] = mapto.Get(seg_p2); mesh.LineSegment(j)[1] = mapto.Get(seg_p1); mesh.LineSegment(j)[0] = mapto.Get(seg_p2); } } } } } // Add prismatic cells at the boundaries cout << "Generating prism boundary layer volume elements...." << endl; for (i = 1; i <= nse; i++) { Element2d & sel = mesh.SurfaceElement(i); if(surfid.Contains(sel.GetIndex())) { Element el(PRISM); for (j = 1; j <= sel.GetNP(); j++) { // Check (Doublecheck) if the corresponding point has a // copy available for remapping if (mapto.Get(sel.PNum(j))) { // Define the points of the newly added Prism cell el.PNum(j+3) = mapto.Get(sel.PNum(j)); el.PNum(j) = sel.PNum(j); } } el.SetIndex(1); el.Invert(); mesh.AddVolumeElement(el); numprisms++; } } // Finally switch the point indices of the surface elements // to the newly added ones cout << "Transferring boundary layer surface elements to new vertex references...." << endl; for (i = 1; i <= nse; i++) { Element2d & sel = mesh.SurfaceElement(i); if(surfid.Contains(sel.GetIndex())) { for (j = 1; j <= sel.GetNP(); j++) { // Check (Doublecheck) if the corresponding point has a // copy available for remapping if (mapto.Get(sel.PNum(j))) { // Map the surface elements to the new points sel.PNum(j) = mapto.Get(sel.PNum(j)); } } } } // Lock all the prism points so that the rest of the mesh can be // optimised without invalidating the entire mesh for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) { if(bndnodes.Test(i)) mesh.AddLockedPoint(pi); } // Now, actually pull back the old surface points to create // the actual boundary layers cout << "Moving and optimising boundary layer points...." << endl; for (i = 1; i <= np; i++) { Array<ElementIndex> vertelems; if(bndnodes.Test(i)) { MeshPoint pointtomove; pointtomove = mesh.Point(i); if(layer == prismlayers) { mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i)); meshtopo.GetVertexElements(i,vertelems); for(j = 1; j <= vertelems.Size(); j++) { // double sfact = 0.9; Element volel = mesh.VolumeElement(vertelems.Elem(j)); if(((volel.GetType() == TET) || (volel.GetType() == TET10)) && (!volel.IsDeleted())) { //while((volel.Volume(mesh.Points()) <= 0.0) && (sfact >= 0.0)) //{ // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // mesh.ImproveMesh(); // // Try to move the point back by one step but // // if the volume drops to below zero, double back // mesh.Point(i).SetPoint(pointtomove + ((sfact + 0.1) * layerht * growthvectors.Elem(i))); // if(volel.Volume(mesh.Points()) <= 0.0) // { // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // } // sfact -= 0.1; //} volel.Delete(); } } mesh.Compress(); } else { mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i)); } } } } // Optimise the tet part of the volume mesh after all the modifications // to the system are completed //OptimizeVolume(mparam,mesh); cout << "New NP: " << mesh.GetNP() << endl; cout << "Num of Quads: " << numquads << endl; cout << "Num of Prisms: " << numprisms << endl; cout << "Boundary Layer Generation....Done!" << endl; dbg.close(); }
void SplineSeg<D> :: Partition (double h, double elto0, Mesh & mesh, Point3dTree & searchtree, int segnr) const { int i, j; double l, r1, r2, ra; double lold, dt, frac; int n = 100; Point<D> p, pold, mark, oldmark; ARRAY<double> curvepoints; double edgelength, edgelengthold; l = Length(); r1 = StartPI().refatpoint; r2 = EndPI().refatpoint; ra = reffak; // cout << "Partition, l = " << l << ", h = " << h << endl; CalcPartition (l, h, r1, r2, ra, elto0, curvepoints); // cout << "curvepoints = " << curvepoints << endl; dt = 1.0 / n; l = 0; j = 1; pold = GetPoint (0); lold = 0; oldmark = pold; edgelengthold = 0; ARRAY<int> locsearch; for (i = 1; i <= n; i++) { p = GetPoint (i*dt); l = lold + Dist (p, pold); while (j < curvepoints.Size() && (l >= curvepoints[j] || i == n)) { frac = (curvepoints[j]-lold) / (l-lold); mark = pold + frac * (p-pold); edgelength = i*dt + (frac-1)*dt; { PointIndex pi1 = -1, pi2 = -1; Point3d mark3(mark(0), mark(1), 0); Point3d oldmark3(oldmark(0), oldmark(1), 0); Vec<3> v (1e-4*h, 1e-4*h, 1e-4*h); searchtree.GetIntersecting (oldmark3 - v, oldmark3 + v, locsearch); if (locsearch.Size()) pi1 = locsearch[0]; searchtree.GetIntersecting (mark3 - v, mark3 + v, locsearch); if (locsearch.Size()) pi2 = locsearch[0]; /* for (PointIndex pk = PointIndex::BASE; pk < mesh.GetNP()+PointIndex::BASE; pk++) { if (Dist (mesh[pk], oldmark3) < 1e-4 * h) pi1 = pk; if (Dist (mesh[pk], mark3) < 1e-4 * h) pi2 = pk; } */ // cout << "pi1 = " << pi1 << endl; // cout << "pi2 = " << pi2 << endl; if (pi1 == -1) { pi1 = mesh.AddPoint(oldmark3); searchtree.Insert (oldmark3, pi1); } if (pi2 == -1) { pi2 = mesh.AddPoint(mark3); searchtree.Insert (mark3, pi2); } // cout << "pi1 = " << pi1 << endl; // cout << "pi2 = " << pi2 << endl; Segment seg; seg.edgenr = segnr; seg.si = bc; // segnr; seg.p1 = pi1; seg.p2 = pi2; seg.domin = leftdom; seg.domout = rightdom; seg.epgeominfo[0].edgenr = segnr; seg.epgeominfo[0].dist = edgelengthold; seg.epgeominfo[1].edgenr = segnr; seg.epgeominfo[1].dist = edgelength; seg.singedge_left = hpref_left; seg.singedge_right = hpref_right; mesh.AddSegment (seg); } oldmark = mark; edgelengthold = edgelength; j++; } pold = p; lold = l; } }
void Refinement :: MakeSecondOrder (Mesh & mesh) { int nseg, nse, ne; mesh.ComputeNVertices(); mesh.SetNP(mesh.GetNV()); INDEX_2_HASHTABLE<int> between(mesh.GetNP() + 5); bool thinlayers = 0; for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) if (mesh[ei].GetType() == PRISM || mesh[ei].GetType() == PRISM12) thinlayers = 1; nseg = mesh.GetNSeg(); for (SegmentIndex si = 0; si < nseg; si++) { Segment & el = mesh.LineSegment(si); INDEX_2 i2 = INDEX_2::Sort (el[0], el[1]); if (between.Used(i2)) el[2] = between.Get(i2); else { Point<3> pb; EdgePointGeomInfo ngi; PointBetween (mesh.Point (el[0]), mesh.Point (el[1]), 0.5, el.surfnr1, el.surfnr2, el.epgeominfo[0], el.epgeominfo[1], pb, ngi); el[2] = mesh.AddPoint (pb, mesh.Point(el[0]).GetLayer(), EDGEPOINT); between.Set (i2, el[2]); } } // refine surface elements nse = mesh.GetNSE(); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { int j; const Element2d & el = mesh.SurfaceElement(sei); int onp(0); Element2d newel; newel.SetIndex (el.GetIndex()); static int betw_trig[3][3] = { { 1, 2, 3 }, { 0, 2, 4 }, { 0, 1, 5 } }; static int betw_quad6[2][3] = { { 0, 1, 4 }, { 3, 2, 5 } }; static int betw_quad8[4][3] = { { 0, 1, 4 }, { 3, 2, 5 }, { 0, 3, 6 }, { 1, 2, 7 } }; int (*betw)[3] = NULL; switch (el.GetType()) { case TRIG: case TRIG6: { betw = betw_trig; newel.SetType (TRIG6); onp = 3; break; } case QUAD: case QUAD6: case QUAD8: { if (thinlayers) { betw = betw_quad6; newel.SetType (QUAD6); } else { betw = betw_quad8; newel.SetType (QUAD8); } onp = 4; break; } default: PrintSysError ("Unhandled element in secondorder:", int(el.GetType())); } for (j = 0; j < onp; j++) newel[j] = el[j]; int nnp = newel.GetNP(); for (j = 0; j < nnp-onp; j++) { int pi1 = newel[betw[j][0]]; int pi2 = newel[betw[j][1]]; INDEX_2 i2 = INDEX_2::Sort (pi1, pi2); if (between.Used(i2)) newel[onp+j] = between.Get(i2); else { Point<3> pb; PointGeomInfo newgi; PointBetween (mesh.Point (pi1), mesh.Point (pi2), 0.5, mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(), el.GeomInfoPi (betw[j][0]+1), el.GeomInfoPi (betw[j][1]+1), pb, newgi); newel[onp+j] = mesh.AddPoint (pb, mesh.Point(pi1).GetLayer(), SURFACEPOINT); between.Set (i2, newel[onp+j]); } } mesh.SurfaceElement(sei) = newel; } // int i, j; // refine volume elements ne = mesh.GetNE(); for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); int onp = 0; Element newel; newel.SetIndex (el.GetIndex()); static int betw_tet[6][3] = { { 0, 1, 4 }, { 0, 2, 5 }, { 0, 3, 6 }, { 1, 2, 7 }, { 1, 3, 8 }, { 2, 3, 9 } }; static int betw_prism[6][3] = { { 0, 2, 6 }, { 0, 1, 7 }, { 1, 2, 8 }, { 3, 5, 9 }, { 3, 4, 10 }, { 4, 5, 11 }, }; int (*betw)[3] = NULL; switch (el.GetType()) { case TET: case TET10: { betw = betw_tet; newel.SetType (TET10); onp = 4; break; } case PRISM: case PRISM12: { betw = betw_prism; newel.SetType (PRISM12); onp = 6; break; } default: PrintSysError ("MakeSecondOrder, illegal vol type ", el.GetType()); } for (int j = 1; j <= onp; j++) newel.PNum(j) = el.PNum(j); int nnp = newel.GetNP(); for (int j = 0; j < nnp-onp; j++) { INDEX_2 i2(newel[betw[j][0]], newel[betw[j][1]]); i2.Sort(); if (between.Used(i2)) newel.PNum(onp+1+j) = between.Get(i2); else { newel.PNum(onp+1+j) = mesh.AddPoint (Center (mesh.Point(i2.I1()), mesh.Point(i2.I2())), mesh.Point(i2.I1()).GetLayer(), INNERPOINT); between.Set (i2, newel.PNum(onp+1+j)); } } mesh.VolumeElement (i) = newel; } // makes problems after linear mesh refinement, since // 2nd order identifications are not removed // update identification tables for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) { Array<int,PointIndex::BASE> identmap; mesh.GetIdentifications().GetMap (i, identmap); for (INDEX_2_HASHTABLE<int>::Iterator it = between.Begin(); it != between.End(); it++) { INDEX_2 i2; int newpi; between.GetData (it, i2, newpi); INDEX_2 oi2(identmap.Get(i2.I1()), identmap.Get(i2.I2())); oi2.Sort(); if (between.Used (oi2)) { int onewpi = between.Get(oi2); mesh.GetIdentifications().Add (newpi, onewpi, i); } } /* for (int j = 1; j <= between.GetNBags(); j++) for (int k = 1; k <= between.GetBagSize(j); k++) { INDEX_2 i2; int newpi; between.GetData (j, k, i2, newpi); INDEX_2 oi2(identmap.Get(i2.I1()), identmap.Get(i2.I2())); oi2.Sort(); if (between.Used (oi2)) { int onewpi = between.Get(oi2); mesh.GetIdentifications().Add (newpi, onewpi, i); } } */ } // mesh.mglevels++; int oldsize = mesh.mlbetweennodes.Size(); mesh.mlbetweennodes.SetSize(mesh.GetNP()); for (int i = oldsize; i < mesh.GetNP(); i++) mesh.mlbetweennodes[i] = INDEX_2(0,0); /* for (i = 1; i <= between.GetNBags(); i++) for (j = 1; j <= between.GetBagSize(i); j++) { INDEX_2 oldp; int newp; between.GetData (i, j, oldp, newp); mesh.mlbetweennodes.Elem(newp) = oldp; } */ for (INDEX_2_HASHTABLE<int>::Iterator it = between.Begin(); it != between.End(); it++) { mesh.mlbetweennodes[between.GetData (it)] = between.GetHash(it); } mesh.ComputeNVertices(); mesh.RebuildSurfaceElementLists(); // ValidateSecondOrder (mesh); }