static INDEX_2 Sort (int i1, int i2) { if (i1 > i2) return INDEX_2 (i2,i1); else return INDEX_2 (i1,i2); }
int AdFront2 :: AddLine (int pi1, int pi2, const PointGeomInfo & gi1, const PointGeomInfo & gi2) { int minfn; int li; FrontPoint2 & p1 = points[pi1]; FrontPoint2 & p2 = points[pi2]; nfl++; p1.AddLine(); p2.AddLine(); minfn = min2 (p1.FrontNr(), p2.FrontNr()); p1.DecFrontNr (minfn+1); p2.DecFrontNr (minfn+1); if (dellinel.Size() != 0) { li = dellinel.Last(); dellinel.DeleteLast (); lines[li] = FrontLine (INDEX_2(pi1, pi2)); } else { li = lines.Append(FrontLine (INDEX_2(pi1, pi2))) - 1; } if (!gi1.trignum || !gi2.trignum) { cout << "ERROR: in AdFront::AddLine, illegal geominfo" << endl; } lines[li].SetGeomInfo (gi1, gi2); Box3d lbox; lbox.SetPoint(p1.P()); lbox.AddPoint(p2.P()); linesearchtree.Insert (lbox.PMin(), lbox.PMax(), li); if (allflines) { if (allflines->Used (INDEX_2 (GetGlobalIndex (pi1), GetGlobalIndex (pi2)))) { cerr << "ERROR Adfront2::AddLine: line exists" << endl; (*testout) << "ERROR Adfront2::AddLine: line exists" << endl; } allflines->Set (INDEX_2 (GetGlobalIndex (pi1), GetGlobalIndex (pi2)), 1); } return li; }
int AdFront2 :: ExistsLine (int pi1, int pi2) { if (!allflines) return 0; if (allflines->Used (INDEX_2(pi1, pi2))) return allflines->Get (INDEX_2 (pi1, pi2)); else return 0; }
HPREF_ELEMENT_TYPE ClassifySegm(HPRefElement & hpel, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint) { int cp1 = cornerpoint.Test (hpel[0]); int cp2 = cornerpoint.Test (hpel[1]); INDEX_2 i2; i2 = INDEX_2(hpel[0], hpel[1]); i2.Sort(); if (!edges.Used (i2)) { cp1 = edgepoint.Test (hpel[0]); cp2 = edgepoint.Test (hpel[1]); } if(!edges.Used(i2) && !face_edges.Used(i2)) { if(facepoint[hpel[0]]!=0) cp1=1; if(facepoint[hpel[1]]!=0) cp2=1; } if(edges.Used(i2) && !face_edges.Used(i2)) { if(facepoint[hpel[0]]) cp1 = 1; if(facepoint[hpel[1]]) cp2 = 1; } if (!cp1 && !cp2) hpel.type = HP_SEGM; else if (cp1 && !cp2) hpel.type = HP_SEGM_SINGCORNERL; else if (!cp1 && cp2) hpel.type = HP_SEGM_SINGCORNERR; else hpel.type = HP_SEGM_SINGCORNERS; // cout << " SEGM found with " << hpel[0] << " \t" << hpel[1] << endl << " of type " << hpel.type << endl; return(hpel.type) ; }
void AdFront2 :: DeleteLine (int li) { int pi; nfl--; for (int i = 1; i <= 2; i++) { pi = lines[li].L().I(i); points[pi].RemoveLine(); if (!points[pi].Valid()) { delpointl.Append (pi); if (points[pi].mgi) { cpointsearchtree.DeleteElement (pi); delete points[pi].mgi; points[pi].mgi = NULL; } pointsearchtree.DeleteElement (pi); } } if (allflines) { allflines->Set (INDEX_2 (GetGlobalIndex (lines[li].L().I1()), GetGlobalIndex (lines[li].L().I2())), 2); } lines[li].Invalidate(); linesearchtree.DeleteElement (li); dellinel.Append (li); }
void Refinement :: ValidateSecondOrder (Mesh & mesh) { PrintMessage (3, "Validate mesh"); int np = mesh.GetNP(); int ne = mesh.GetNE(); // int i, j; Array<INDEX_2> parents(np); for (int i = 1; i <= np; i++) parents.Elem(i) = INDEX_2(0,0); for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); if (el.GetType() == TET10) { static int betweentab[6][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 4, 10 } }; for (int j = 0; j < 6; j++) { int f1 = el.PNum (betweentab[j][0]); int f2 = el.PNum (betweentab[j][1]); int son = el.PNum (betweentab[j][2]); parents.Elem(son).I1() = f1; parents.Elem(son).I2() = f2; } } } ValidateRefinedMesh (mesh, parents); }
void WriteTETFormat (const Mesh & mesh, const string & filename)//, const string& problemType ) { string problemType = ""; if(!mesh.PureTetMesh()) throw NgException("Can only export pure tet mesh in this format"); cout << "starting .tet export to file " << filename << endl; ARRAY<int> point_ids,edge_ids,face_ids; ARRAY<int> elnum(mesh.GetNE()); elnum = -1; ARRAY<int> userdata_int; ARRAY<double> userdata_double; ARRAY<int> ports; ARRAY<int> uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D; int pos_int = 0; int pos_double = 0; bool haveuserdata = (mesh.GetUserData("TETmesh:double",userdata_double) && mesh.GetUserData("TETmesh:int",userdata_int) && mesh.GetUserData("TETmesh:ports",ports) && mesh.GetUserData("TETmesh:point_id",point_ids,PointIndex::BASE) && mesh.GetUserData("TETmesh:uid_to_group_3D",uid_to_group_3D) && mesh.GetUserData("TETmesh:uid_to_group_2D",uid_to_group_2D) && mesh.GetUserData("TETmesh:uid_to_group_1D",uid_to_group_1D) && mesh.GetUserData("TETmesh:uid_to_group_0D",uid_to_group_0D)); int version,subversion; if(haveuserdata) { version = int(userdata_double[0]); subversion = int(10*(userdata_double[0] - version)); pos_double++; } else { version = 2; subversion = 0; } if(version >= 2) { // test if ids are disjunct, if not version 2.0 not possible int maxbc(-1),mindomain(-1); for(ElementIndex i=0; i<mesh.GetNE(); i++) if(i==0 || mesh[i].GetIndex() < mindomain) mindomain = mesh[i].GetIndex(); for(int i=1; i<=mesh.GetNFD(); i++) if(i==1 || mesh.GetFaceDescriptor(i).BCProperty() > maxbc) maxbc = mesh.GetFaceDescriptor(i).BCProperty(); if(maxbc >= mindomain) { cout << "WARNING: writing version " << version << "." << subversion << " tetfile not possible, "; version = 1; subversion = 1; cout << "using version " << version << "." << subversion << endl; } } int startsize = point_ids.Size(); point_ids.SetSize(mesh.GetNP()+1); for(int i=startsize; i<point_ids.Size(); i++) point_ids[i] = -1; for(int i=0; i<PointIndex::BASE; i++) point_ids[i] = -1; INDEX_2_CLOSED_HASHTABLE<int> edgenumbers(6*mesh.GetNE()+3*mesh.GetNSE());; INDEX_3_CLOSED_HASHTABLE<int> facenumbers(4*mesh.GetNE()+mesh.GetNSE()); ARRAY<INDEX_2> edge2node; ARRAY<INDEX_3> face2edge; ARRAY<INDEX_4> element2face; int numelems(0),numfaces(0),numedges(0),numnodes(0); for(SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { const Segment & seg = mesh[si]; INDEX_2 i2(seg.p1,seg.p2); i2.Sort(); if(edgenumbers.Used(i2)) continue; numedges++; edgenumbers.Set(i2,numedges); edge2node.Append(i2); edge_ids.Append(seg.edgenr); if(point_ids[seg.p1] == -1) point_ids[seg.p1] = (version >= 2) ? seg.edgenr : 0; if(point_ids[seg.p2] == -1) point_ids[seg.p2] = (version >= 2) ? seg.edgenr : 0; } for(SurfaceElementIndex si = 0; si < mesh.GetNSE(); si++) { if(mesh[si].IsDeleted()) continue; const Element2d & elem = mesh[si]; numfaces++; INDEX_3 i3(elem[0], elem[1], elem[2]); int min = i3[0]; int minpos = 0; for(int j=1; j<3; j++) if(i3[j] < min) { min = i3[j]; minpos = j; } if(minpos == 1) { int aux = i3[0]; i3[0] = i3[1]; i3[1] = i3[2]; i3[2] = aux; } else if(minpos == 2) { int aux = i3[0]; i3[0] = i3[2]; i3[2] = i3[1]; i3[1] = aux; } facenumbers.Set(i3,numfaces); int bc = mesh.GetFaceDescriptor(elem.GetIndex()).BCProperty(); face_ids.Append(bc); for(int j=0; j<3; j++) if(point_ids[elem[j]] == -1) point_ids[elem[j]] = (version >= 2) ? bc : 0; INDEX_2 i2a,i2b; INDEX_3 f_to_n; for(int j=0; j<3; j++) { i2a = INDEX_2(i3[j],i3[(j+1)%3]); i2b[0] = i2a[1]; i2b[1] = i2a[0]; if(edgenumbers.Used(i2a)) f_to_n[j] = edgenumbers.Get(i2a); else if(edgenumbers.Used(i2b)) f_to_n[j] = -edgenumbers.Get(i2b); else { numedges++; edgenumbers.Set(i2a,numedges); edge2node.Append(i2a); f_to_n[j] = numedges; if(version >= 2) edge_ids.Append(bc); else edge_ids.Append(0); } } face2edge.Append(f_to_n); } for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; if(el.IsDeleted()) continue; numelems++; elnum[ei] = numelems; static int tetfaces[4][3] = { { 0, 2, 1 }, { 0, 1, 3 }, { 1, 2, 3 }, { 2, 0, 3 } }; for(int j=0; j<4; j++) if(point_ids[el[j]] == -1) point_ids[el[j]] = (version >= 2) ? el.GetIndex() : 0; INDEX_4 e_to_f; for(int i = 0; i < 4; i++) { INDEX_3 i3a(el[tetfaces[i][0]],el[tetfaces[i][1]],el[tetfaces[i][2]]); int min = i3a[0]; int minpos = 0; for(int j=1; j<3; j++) if(i3a[j] < min) { min = i3a[j]; minpos = j; } if(minpos == 1) { int aux = i3a[0]; i3a[0] = i3a[1]; i3a[1] = i3a[2]; i3a[2] = aux; } else if(minpos == 2) { int aux = i3a[0]; i3a[0] = i3a[2]; i3a[2] = i3a[1]; i3a[1] = aux; } INDEX_3 i3b(i3a[0],i3a[2],i3a[1]); if(facenumbers.Used(i3a)) e_to_f[i] = facenumbers.Get(i3a); else if(facenumbers.Used(i3b)) e_to_f[i] = -facenumbers.Get(i3b); else { numfaces++; facenumbers.Set(i3a,numfaces); e_to_f[i] = numfaces; if(version >= 2) face_ids.Append(el.GetIndex()); else face_ids.Append(0); INDEX_2 i2a,i2b; INDEX_3 f_to_n; for(int j=0; j<3; j++) { i2a = INDEX_2(i3a[j],i3a[(j+1)%3]); i2b[0] = i2a[1]; i2b[1] = i2a[0]; if(edgenumbers.Used(i2a)) f_to_n[j] = edgenumbers.Get(i2a); else if(edgenumbers.Used(i2b)) f_to_n[j] = -edgenumbers.Get(i2b); else { numedges++; edgenumbers.Set(i2a,numedges); edge2node.Append(i2a); f_to_n[j] = numedges; if(version >= 2) edge_ids.Append(el.GetIndex()); else edge_ids.Append(0); } } face2edge.Append(f_to_n); } } element2face.Append(e_to_f); } ofstream outfile(filename.c_str()); outfile.precision(16); int unitcode; double tolerance; double dS1,dS2, alphaDeg; double x3D,y3D,z3D; int modelverts(0), modeledges(0), modelfaces(0), modelcells(0); int numObj0D,numObj1D,numObj2D,numObj3D; int numports = ports.Size(); ARRAY<int> nodenum(point_ids.Size()+1); nodenum = -1; numnodes = 0; for(int i=0; i<point_ids.Size(); i++) { if(point_ids[i] != -1) { numnodes++; nodenum[i] = numnodes; } } if(haveuserdata) { unitcode = userdata_int[pos_int]; pos_int++; tolerance = userdata_double[pos_double]; pos_double++; dS1 = userdata_double[pos_double]; pos_double++; dS2 = userdata_double[pos_double]; pos_double++; alphaDeg = userdata_double[pos_double]; pos_double++; x3D = userdata_double[pos_double]; pos_double++; y3D = userdata_double[pos_double]; pos_double++; z3D = userdata_double[pos_double]; pos_double++; if(version == 2) { modelverts = userdata_int[pos_int]; pos_int++; modeledges = userdata_int[pos_int]; pos_int++; modelfaces = userdata_int[pos_int]; pos_int++; modelcells = userdata_int[pos_int]; pos_int++; } numObj3D = userdata_int[pos_int]; pos_int++; numObj2D = userdata_int[pos_int]; pos_int++; numObj1D = userdata_int[pos_int]; pos_int++; numObj0D = userdata_int[pos_int]; pos_int++; } else { unitcode = 3; tolerance = 1e-5; dS1 = dS2 = alphaDeg = 0; x3D = y3D = z3D = 0; modelverts = modeledges = modelfaces = modelcells = 0; numObj3D = numObj2D = numObj1D = numObj0D = 0; } string uidpid; if(version == 1) uidpid = "PID"; else if (version == 2) uidpid = "UID"; ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps; for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) { if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) { idmaps.Append(new ARRAY<int,PointIndex::BASE>); mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true); } } ARRAY<int> id_num,id_type; ARRAY< ARRAY<int> *> id_groups; // sst 2008-03-12: Write problem class... { std::string block; block = "// CST Tetrahedral "; block += !problemType.empty() ? problemType : "High Frequency"; block += " Mesh, Version no.:\n"; size_t size = block.size()-3; block += "// "; block.append( size, '^' ); block += "\n"; outfile << block << version << "." << subversion << "\n\n"; } outfile << "// User Units Code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << unitcode << "\n\n" \ << "// Geometric coord \"zero\" tolerance threshold:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << tolerance << "\n\n" \ << "// Periodic UnitCell dS1 , dS2 , alphaDeg:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << dS1 << " " << dS2 << " " << alphaDeg <<"\n\n" \ << "// Periodic UnitCell origin in global coords (x3D,y3D,z3D):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << x3D << " " << y3D << " " << z3D << "\n" << endl; if(version == 2) { outfile << "// Model entity count: Vertices, Edges, Faces, Cells:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << modelverts << " " << modeledges << " " << modelfaces << " " << modelcells << endl << endl; } outfile << "// Topological mesh-entity counts (#elements,#faces,#edges,#nodes):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; outfile << numelems << " " << numfaces << " " << numedges << " " << numnodes << endl << endl; outfile << "// NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<< uidpid <<":\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; id_num.SetSize(mesh.GetNP()+1); id_type.SetSize(mesh.GetNP()+1); id_num = 0; id_type = 0; int n2,n4,n8; n2 = n4 = n8 = 0; for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) { if(id_num[i] != 0) continue; if(nodenum[i] == -1) continue; ARRAY<int> group; group.Append(i); for(int j=0; j<idmaps.Size(); j++) { startsize = group.Size(); for(int k=0; k<startsize; k++) { int id = (*idmaps[j])[group[k]]; if(id != 0 && !group.Contains(id) && nodenum[id] != -1) { group.Append(id); id_num[id] = j+1+id_num[group[k]]; } } } if(group.Size() > 1) { id_groups.Append(new ARRAY<int>(group)); if(group.Size() == 2) { id_type[i] = 1; id_type[group[1]] = 2; n2++; } else if(group.Size() == 4) { id_type[i] = 3; for(int j=1; j<group.Size(); j++) id_type[group[j]] = 4; n4++; } else if(group.Size() == 8) { id_type[i] = 5; for(int j=1; j<group.Size(); j++) id_type[group[j]] = 6; n8++; } else cerr << "ERROR: Identification group size = " << group.Size() << endl; } } for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) { if(nodenum[i] == -1) continue; outfile << nodenum[i] << " " << mesh[i](0) << " " << mesh[i](1) << " " << mesh[i](2) << " " << id_type[i] << " "; if(i-PointIndex::BASE < point_ids.Size()) outfile << point_ids[i]; else outfile << "0"; outfile << "\n"; } outfile << endl; outfile << "\n// Number of Periodic Master Nodes:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << n2 << "\n" \ << "\n" \ << "// MasterNodeID, SlaveNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<id_groups.Size(); i++) { if(id_groups[i]->Size() != 2) continue; for(int j=0; j<id_groups[i]->Size(); j++) outfile << nodenum[(*id_groups[i])[j]] << " "; for(int j=1; j<id_groups[i]->Size(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// Number of Corner Periodic Master Nodes:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << n4 << "\n" \ << "\n" \ << "// MasterNodeID, 3-SlaveNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<id_groups.Size(); i++) { if(!id_groups[i] || id_groups[i]->Size() != 4) continue; for(int j=0; j<id_groups[i]->Size(); j++) outfile << nodenum[(*id_groups[i])[j]] << " "; for(int j=1; j<id_groups[i]->Size(); j++) { outfile << id_num[(*id_groups[i])[j]] << " "; } outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// Number of Cubic Periodic Master Nodes:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << n8 << "\n" \ << "\n" \ << "// MasterNodeID, 7-SlaveNodeID's, TranslCodes:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<id_groups.Size(); i++) { if(!id_groups[i] || id_groups[i]->Size() != 8) continue; for(int j=0; j<id_groups[i]->Size(); j++) outfile << nodenum[(*id_groups[i])[j]] << " "; for(int j=1; j<id_groups[i]->Size(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<<uidpid<<":\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; ARRAY< ARRAY<int>* > vertex_to_edge(mesh.GetNP()+1); for(int i=0; i<=mesh.GetNP(); i++) vertex_to_edge[i] = new ARRAY<int>; ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps_edge(idmaps.Size()); for(int i=0; i<idmaps_edge.Size(); i++) { idmaps_edge[i] = new ARRAY<int,PointIndex::BASE>(numedges); (*idmaps_edge[i]) = 0; } ARRAY<int> possible; for(int i=0; i<edge2node.Size(); i++) { const INDEX_2 & v = edge2node[i]; for(int j=0; j<idmaps.Size(); j++) { INDEX_2 vid((*idmaps[j])[v[0]], (*idmaps[j])[v[1]]); if(vid[0] != 0 && vid[0] != v[0] && vid[1] != 0 && vid[1] != v[1]) { Intersection(*vertex_to_edge[vid[0]],*vertex_to_edge[vid[1]],possible); if(possible.Size() == 1) { (*idmaps_edge[j])[possible[0]] = i+1; (*idmaps_edge[j])[i+1] = possible[0]; } else if(possible.Size() > 0) { cerr << "ERROR: too many possible edge identifications" << endl; (*testout) << "ERROR: too many possible edge identifications" << endl << "*vertex_to_edge["<<vid[0]<<"] " << *vertex_to_edge[vid[0]] << endl << "*vertex_to_edge["<<vid[1]<<"] " << *vertex_to_edge[vid[1]] << endl << "possible " << possible << endl; } } } vertex_to_edge[v[0]]->Append(i+1); vertex_to_edge[v[1]]->Append(i+1); } for(int i=0; i<vertex_to_edge.Size(); i++) delete vertex_to_edge[i]; id_groups.SetSize(0); id_num.SetSize(numedges+1); id_num = 0; id_type.SetSize(numedges+1); id_type = 0; n2 = n4 = n8 = 0; for(int i=1; i<=edge2node.Size(); i++) { if(id_num[i] != 0) continue; ARRAY<int> group; group.Append(i); for(int j=0; j<idmaps_edge.Size(); j++) { startsize = group.Size(); for(int k=0; k<startsize; k++) { int id = (*idmaps_edge[j])[group[k]]; if(id != 0 && !group.Contains(id)) { group.Append(id); id_num[id] = j+1+id_num[group[k]]; } } } if(group.Size() > 1) { id_num[i] = 1; id_groups.Append(new ARRAY<int>(group)); if(group.Size() == 2) { id_type[i] = 1; id_type[group[1]] = 2; n2++; } else if(group.Size() == 4) { id_type[i] = 3; for(int j=1; j<group.Size(); j++) id_type[group[j]] = 4; n4++; } else { cerr << "ERROR: edge identification group size = " << group.Size() << endl; (*testout) << "edge group " << group << endl; for(int j=0; j<idmaps_edge.Size(); j++) { (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl; } } } } for(int i=1; i<=edge2node.Size(); i++) { if(id_num[i] != 0) continue; ARRAY<int> group; group.Append(i); for(int j=0; j<idmaps_edge.Size(); j++) { startsize = group.Size(); for(int k=0; k<startsize; k++) { int id = (*idmaps_edge[j])[group[k]]; if(id != 0 && !group.Contains(id)) { group.Append(id); id_num[id] = j+1+id_num[group[k]]; } } } if(group.Size() > 1) { id_num[i] = 1; id_groups.Append(new ARRAY<int>(group)); if(group.Size() == 2) { id_type[i] = 1; id_type[group[1]] = 2; n2++; } else if(group.Size() == 4) { id_type[i] = 3; for(int j=1; j<group.Size(); j++) id_type[group[j]] = 4; n4++; } else { cerr << "ERROR: edge identification group size = " << group.Size() << endl; (*testout) << "edge group " << group << endl; for(int j=0; j<idmaps_edge.Size(); j++) { (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl; } } } } for(int i=0; i<edge2node.Size(); i++) outfile << i+1 << " " << nodenum[edge2node[i][0]] << " " << nodenum[edge2node[i][1]] << " " << id_type[i+1] << " " << edge_ids[i] << "\n"; outfile << endl; outfile << "// Number of Periodic Master Edges:\n"\ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ << n2 << "\n" \ << "\n"\ << "// MasterEdgeID, SlaveEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<id_groups.Size(); i++) { if(id_groups[i]->Size() != 2) continue; for(int j=0; j<id_groups[i]->Size(); j++) outfile << (*id_groups[i])[j] << " "; for(int j=1; j<id_groups[i]->Size(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// Number of Corner Periodic Master Edges:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ << n4 << "\n" \ << "\n"\ << "// MasterEdgeID, 3 SlaveEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<id_groups.Size(); i++) { if(!id_groups[i] || id_groups[i]->Size() != 4) continue; for(int j=0; j<id_groups[i]->Size(); j++) outfile << (*id_groups[i])[j] << " "; for(int j=1; j<id_groups[i]->Size(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PSlave), "<<uidpid<<":\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; ARRAY< ARRAY<int>* > edge_to_face(numedges+1); for(int i=0; i<edge_to_face.Size(); i++) edge_to_face[i] = new ARRAY<int>; for(int i=0; i<idmaps.Size(); i++) { idmaps[i]->SetSize(numfaces); (*idmaps[i]) = 0; } for(int i=0; i<face2edge.Size(); i++) { for(int j=0; j<idmaps_edge.Size(); j++) { int e1id,e2id,e3id; e1id = (*idmaps_edge[j])[abs(face2edge[i][0])]; e2id = (*idmaps_edge[j])[abs(face2edge[i][1])]; e3id = (*idmaps_edge[j])[abs(face2edge[i][2])]; if(e1id != 0 && e1id != abs(face2edge[i][0]) && e2id != 0 && e2id != abs(face2edge[i][1]) && e3id != 0 && e3id != abs(face2edge[i][2])) { Intersection(*edge_to_face[e1id],*edge_to_face[e2id],*edge_to_face[e3id],possible); if(possible.Size() == 1) { (*idmaps[j])[possible[0]] = i+1; (*idmaps[j])[i+1] = possible[0]; } else if(possible.Size() > 0) cerr << "ERROR: too many possible face identifications" << endl; } } edge_to_face[abs(face2edge[i][0])]->Append(i+1); edge_to_face[abs(face2edge[i][1])]->Append(i+1); edge_to_face[abs(face2edge[i][2])]->Append(i+1); } for(int i=0; i<edge_to_face.Size(); i++) delete edge_to_face[i]; for(int i=0; i<idmaps_edge.Size(); i++) delete idmaps_edge[i]; id_groups.SetSize(0); id_num.SetSize(numfaces+1); id_num = 0; n2 = n4 = n8 = 0; for(int i=1; i<=numfaces; i++) { if(id_num[i] != 0) continue; ARRAY<int> group; group.Append(i); for(int j=0; j<idmaps.Size(); j++) { startsize = group.Size(); for(int k=0; k<startsize; k++) { int id = (*idmaps[j])[group[k]]; if(id != 0 && !group.Contains(id)) { group.Append(id); id_num[id] = j+1+id_num[group[k]]; } } } if(group.Size() > 1) { id_num[i] = -1; id_groups.Append(new ARRAY<int>(group)); if(group.Size() == 2) n2++; else cerr << "ERROR: face identification group size = " << group.Size() << endl; } } for(int i=0; i<idmaps.Size(); i++) delete idmaps[i]; for(int i=0; i<face2edge.Size(); i++) { outfile << i+1 << " "; for(int j=0; j<3; j++) outfile << face2edge[i][j] << " "; if(id_num[i+1] == 0) outfile << 0; else if(id_num[i+1] == -1) outfile << 1; else outfile << 2; outfile << " " << face_ids[i] <<"\n"; } outfile << endl; outfile << "// Number of Periodic Master Faces:\n"\ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ << n2 << "\n" \ << "\n"\ << "// MasterFaceID, SlaveFaceID, TranslCode (1=dS1 2=dS2):\n"\ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<id_groups.Size(); i++) { if(id_groups[i]->Size() != 2) continue; for(int j=0; j<id_groups[i]->Size(); j++) outfile << (*id_groups[i])[j] << " "; for(int j=1; j<id_groups[i]->Size(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; } outfile << endl; outfile << "// ElemID, FaceID0, FaceID1, FaceID2, FaceID3, "<<uidpid<<":\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(ElementIndex i=0; i<mesh.GetNE(); i++) { if(elnum[i] >= 0) { outfile << elnum[i] << " "; for(int j=0; j<4; j++) outfile << element2face[elnum[i]-1][j] << " "; outfile << mesh[i].GetIndex() << "\n"; } } outfile << endl; outfile << "// ElemID, NodeID0, NodeID1, NodeID2, NodeID3:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(ElementIndex i=0; i<mesh.GetNE(); i++) { if(elnum[i] >= 0) outfile << elnum[i] << " " << nodenum[mesh[i][1]] << " " << nodenum[mesh[i][0]] << " " << nodenum[mesh[i][2]] << " " << nodenum[mesh[i][3]] << "\n"; } outfile << endl; outfile << "// Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D):\n" << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" << " "<< numObj3D << " " << numObj2D << " " << numObj1D << " " << numObj0D << "\n" \ << "\n" \ << "// Number of Ports (Ports are a subset of Object2D list):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << numports << "\n" \ << endl; ARRAY< ARRAY<int> * > groups; int maxg = -1; for(int i = 0; i<uid_to_group_3D.Size(); i++) if(uid_to_group_3D[i] > maxg) maxg = uid_to_group_3D[i]; for(int i = 0; i<uid_to_group_2D.Size(); i++) if(uid_to_group_2D[i] > maxg) maxg = uid_to_group_2D[i]; for(int i = 0; i<uid_to_group_1D.Size(); i++) if(uid_to_group_1D[i] > maxg) maxg = uid_to_group_1D[i]; for(int i = 0; i<uid_to_group_0D.Size(); i++) if(uid_to_group_0D[i] > maxg) maxg = uid_to_group_0D[i]; groups.SetSize(maxg+1); for(int i=0; i<groups.Size(); i++) groups[i] = new ARRAY<int>; for(ElementIndex i=0; i<mesh.GetNE(); i++) if(uid_to_group_3D[mesh[i].GetIndex()] >= 0) groups[uid_to_group_3D[mesh[i].GetIndex()]]->Append(i+1); outfile << "// Object3D GroupID, #Elems <immediately followed by> ElemID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<numObj3D; i++) { outfile << i << " " << groups[i]->Size() << "\n"; for(int j=0; j<groups[i]->Size(); j++) outfile << (*groups[i])[j] << "\n"; } for(int i=0; i<groups.Size(); i++) groups[i]->SetSize(0); for(int i=0; i<face_ids.Size(); i++) if(uid_to_group_2D[face_ids[i]] >= 0) groups[uid_to_group_2D[face_ids[i]]]->Append(i+1); outfile << "// Object2D GroupID, #Faces <immediately followed by> FaceID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<numObj2D; i++) { outfile << i << " " << groups[i]->Size() << "\n"; for(int j=0; j<groups[i]->Size(); j++) { outfile << (*groups[i])[j]; if(ports.Contains(face_ids[(*groups[i])[j]-1])) outfile << " P"; outfile << "\n"; } } outfile << endl; for(int i=0; i<groups.Size(); i++) groups[i]->SetSize(0); for(int i=0; i<edge_ids.Size(); i++) if(uid_to_group_1D[edge_ids[i]] >= 0) groups[uid_to_group_1D[edge_ids[i]]]->Append(i+1); outfile << "// Object1D GroupID, #Edges <immediately followed by> EdgeID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<numObj1D; i++) { outfile << i << " " << groups[i]->Size() << "\n"; for(int j=0; j<groups[i]->Size(); j++) outfile << (*groups[i])[j] << "\n"; } outfile << endl; for(int i=0; i<groups.Size(); i++) groups[i]->SetSize(0); for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) { if(i-PointIndex::BASE < point_ids.Size()) { if(uid_to_group_0D[point_ids[i]] >= 0) groups[uid_to_group_0D[point_ids[i]]]->Append(i+1-PointIndex::BASE); } else groups[uid_to_group_0D[0]]->Append(i+1-PointIndex::BASE); } outfile << "// Object0D GroupID, #Nodes <immediately followed by> NodeID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; i<numObj0D; i++) { outfile << i << " " << groups[i]->Size() << "\n"; for(int j=0; j<groups[i]->Size(); j++) outfile << (*groups[i])[j] << "\n"; } outfile << endl; for(int i=0; i<groups.Size(); i++) delete groups[i]; outfile.close(); cout << ".tet export done" << endl; }
HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int pnums[3]; INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); i3.Sort(); bool sing_face = faces.Used (i3); for (int j = 1; j <= 3; j++) { int ep1 = edgepoint.Test (el.PNumMod (j)); int ep2 = edgepoint.Test (el.PNumMod (j+1)); int ep3 = edgepoint.Test (el.PNumMod (j+2)); if (dim == 2) { // JS, Dec 11 ep1 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+1))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+2))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+2))); /* ep1 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+2))); */ // ep3 = edgepoint_dom.Used (INDEX_2 (mesh.SurfaceElement(i).GetIndex(), el.PNumMod(j+2))); } int cp1 = cornerpoint.Test (el.PNumMod (j)); int cp2 = cornerpoint.Test (el.PNumMod (j+1)); int cp3 = cornerpoint.Test (el.PNumMod (j+2)); ep1 |= cp1; ep2 |= cp2; ep3 |= cp3; // (*testout) << "cp = " << cp1 << cp2 << cp3 << ", ep = " << ep1 << ep2 << ep3 << endl; int p[3] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2)}; if(ep1) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[0], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp1 = 1; } if(ep2) { INDEX_2 i2a=INDEX_2::Sort(p[1], p[0]); INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp2 = 1; } if(ep3) { INDEX_2 i2a=INDEX_2::Sort(p[2], p[0]); INDEX_2 i2b=INDEX_2::Sort(p[2], p[1]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp3= 1; } int isedge1=0, isedge2=0, isedge3=0; if(dim == 3 ) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); isedge1 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge1=1; ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); isedge2 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge2=1; ep2 = 1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); isedge3 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge3=1; ep1 = 1; ep3=1; } // cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; if (!sing_face) { /* if (!isedge1) { cp1 |= ep1; cp2 |= ep2; } if (!isedge2) { cp2 |= ep2; cp3 |= ep3; } if (!isedge3) { cp3 |= ep3; cp1 |= ep1; } */ ep1 |= facepoint [el.PNumMod(j)] != 0; ep2 |= facepoint [el.PNumMod(j+1)] != 0; ep3 |= facepoint [el.PNumMod(j+2)] != 0; isedge1 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))); isedge2 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+1), el.PNumMod(j+2))); isedge3 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+2), el.PNumMod(j+3))); } } if(dim ==2) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); i2.Sort(); isedge1 = edges.Used (i2); if(isedge1) { ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); i2.Sort(); isedge2 = edges.Used (i2); if(isedge2) { ep2 = 1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); i2.Sort(); isedge3 = edges.Used (i2); if(isedge3) { ep1 = 1; ep3=1; } } /* cout << " used " << face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))) << endl; cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; cout << " ep " << ep1 << "\t" << ep2 << " \t " << ep3 << endl; cout << " cp " << cp1 << "\t" << cp2 << " \t " << cp3 << endl; */ if (isedge1 + isedge2 + isedge3 == 0) { if (!ep1 && !ep2 && !ep3) type = HP_TRIG; if (ep1 && !ep2 && !ep3) type = HP_TRIG_SINGCORNER; if (ep1 && ep2 && !ep3) type = HP_TRIG_SINGCORNER12; if (ep1 && ep2 && ep3) { if (dim == 2) type = HP_TRIG_SINGCORNER123_2D; else type = HP_TRIG_SINGCORNER123; } if (type != HP_NONE) { pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } } if (isedge1 && !isedge2 && !isedge3) { int code = 0; if (cp1) code += 1; if (cp2) code += 2; if (ep3) code += 4; HPREF_ELEMENT_TYPE types[] = { HP_TRIG_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER12, HP_TRIG_SINGEDGECORNER3, HP_TRIG_SINGEDGECORNER13, HP_TRIG_SINGEDGECORNER23, HP_TRIG_SINGEDGECORNER123, }; type = types[code]; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } if (isedge1 && !isedge2 && isedge3) { if (!cp3) { if (!cp2) type = HP_TRIG_SINGEDGES; else type = HP_TRIG_SINGEDGES2; } else { if (!cp2) type = HP_TRIG_SINGEDGES3; else type = HP_TRIG_SINGEDGES23; } pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } if (isedge1 && isedge2 && isedge3) { type = HP_TRIG_3SINGEDGES; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } } for(int k=0;k<3;k++) el[k] = pnums[k]; /*if(type != HP_NONE) { cout << " TRIG with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << endl; cout << " type " << type << endl; } */ return(type); }
// #ifdef SABINE HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int pnums[3]; int p[3]; INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); i3.Sort(); bool sing_face = faces.Used (i3); // *testout << " facepoint " << facepoint << endl; // Try all rotations of the trig for (int j=0;j<3;j++) { int point_sing[3] = {0,0,0}; int edge_sing[3] = {0,0,0}; // *testout << " actual rotation of trig points " ; for(int m=0;m<3;m++) { p[m] = (j+m)%3 +1; // local vertex number pnums[m] = el.PNum(p[m]); // global vertex number // *testout << pnums[m] << " \t "; } // *testout << endl ; if(dim == 3) { // face point for(int k=0;k<3;k++) if(!sing_face) { // *testout << " fp [" << k << "] = " << facepoint[pnums[k]] << endl; // *testout << " fd.DomainIn()" << fd.DomainIn() << endl; // *testout << " fd.DomainOut()" << fd.DomainOut() << endl; if( facepoint[pnums[k]] && (facepoint[pnums[k]] ==-1 || facepoint[pnums[k]] == fd.DomainIn() || facepoint[pnums[k]] == fd.DomainOut())) point_sing[p[k]-1] = 1; } // if point is on face_edge in next step sing = 2 /* *testout << " pointsing NACH FACEPOints ... FALLS EDGEPOINT UMSETZEN" ; for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; *testout << endl; */ } const ELEMENT_EDGE * eledges = MeshTopology::GetEdges(TRIG); if(dim==3) { for(int k=0;k<3;k++) { int ep1=p[eledges[k][0]-1]; int ep2=p[eledges[k][1]-1]; INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); if(edges.Used(i2)) { edge_sing[k]=2; point_sing[ep1-1] = 2; point_sing[ep2-1] = 2; } else // face_edge? { i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1) // edge not face_edge acc. to surface in which trig lies if(face_edges.Get(i2)==-1 ||face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut() ) { edge_sing[k]=1; } else { point_sing[ep1-1] = 0; // set to edge_point point_sing[ep2-1] = 0; // set to edge_point } } /* *testout << " pointsing NACH edges UND FACEEDGES UMSETZEN ... " ; for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; *testout << endl; */ } } /* *testout << " dim " << dim << endl; *testout << " edgepoint_dom " << edgepoint_dom << endl; */ if(dim==2) { for(int k=0;k<3;k++) { int ep1=p[eledges[k][0]-1]; int ep2=p[eledges[k][1]-1]; INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); if(edges.Used(i2)) { if(edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep1-1])) || edgepoint_dom.Used(INDEX_2(-1,pnums[ep1-1])) || edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep2-1])) || edgepoint_dom.Used(INDEX_2(-1,pnums[ep2-1]))) { edge_sing[k]=2; point_sing[ep1-1] = 2; point_sing[ep2-1] = 2; } } } } for(int k=0;k<3;k++) if(edgepoint.Test(pnums[k])) //edgepoint, but not member of sing_edge on trig -> cp { INDEX_2 i2a=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+1)%3])); INDEX_2 i2b=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+2)%3])); if(!edges.Used(i2a) && !edges.Used(i2b)) point_sing[p[k]-1] = 3; } for(int k=0;k<3;k++) if(cornerpoint.Test(el.PNum(p[k]))) point_sing[p[k]-1] = 3; *testout << "point_sing = " << point_sing[0] << point_sing[1] << point_sing[2] << endl; if(edge_sing[0] + edge_sing[1] + edge_sing[2] == 0) { int ps = point_sing[0] + point_sing[1] + point_sing[2]; if(ps==0) type = HP_TRIG; else if(point_sing[p[0]-1] && !point_sing[p[1]-1] && !point_sing[p[2]-1]) type = HP_TRIG_SINGCORNER; else if(point_sing[p[0]-1] && point_sing[p[1]-1] && !point_sing[p[2]-1]) type = HP_TRIG_SINGCORNER12; else if(point_sing[p[0]-1] && point_sing[p[1]-1] && point_sing[p[2]-1]) { if(dim==2) type = HP_TRIG_SINGCORNER123_2D; else type = HP_TRIG_SINGCORNER123; } } else if (edge_sing[2] && !edge_sing[0] && !edge_sing[1]) //E[2]=(1,2) { int code = 0; if(point_sing[p[0]-1] > edge_sing[2]) code+=1; if(point_sing[p[1]-1] > edge_sing[2]) code+=2; if(point_sing[p[2]-1]) code+=4; HPREF_ELEMENT_TYPE types[] = { HP_TRIG_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER12, HP_TRIG_SINGEDGECORNER3, HP_TRIG_SINGEDGECORNER13, HP_TRIG_SINGEDGECORNER23, HP_TRIG_SINGEDGECORNER123, }; type = types[code]; } // E[0] = [0,2], E[1] =[1,2], E[2] = [0,1] else if(edge_sing[2] && !edge_sing[1] && edge_sing[0]) { if(point_sing[p[2]-1] <= edge_sing[0] ) { if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES; else type = HP_TRIG_SINGEDGES2; } else { if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES3; else type = HP_TRIG_SINGEDGES23; } } else if (edge_sing[2] && edge_sing[1] && edge_sing[0]) type = HP_TRIG_3SINGEDGES; // cout << " run for " << j << " gives type " << type << endl; //*testout << " run for " << j << " gives type " << type << endl; if(type!=HP_NONE) break; } *testout << "type = " << type << endl; for(int k=0;k<3;k++) el[k] = pnums[k]; /*if(type != HP_NONE) { cout << " TRIG with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << endl; cout << " type " << type << endl; } */ return(type); }
HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int ep1(-1), ep2(-1), ep3(-1), ep4(-1), cp1(-1), cp2(-1), cp3(-1), cp4(-1); int isedge1, isedge2, isedge3, isedge4; *testout << "edges = " << edges << endl; for (int j = 1; j <= 4; j++) { ep1 = edgepoint.Test (el.PNumMod (j)); ep2 = edgepoint.Test (el.PNumMod (j+1)); ep3 = edgepoint.Test (el.PNumMod (j+2)); ep4 = edgepoint.Test (el.PNumMod (j+3)); if (dim == 2) { ep1 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+2))); ep4 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+3))); } cp1 = cornerpoint.Test (el.PNumMod (j)); cp2 = cornerpoint.Test (el.PNumMod (j+1)); cp3 = cornerpoint.Test (el.PNumMod (j+2)); cp4 = cornerpoint.Test (el.PNumMod (j+3)); ep1 |= cp1; ep2 |= cp2; ep3 |= cp3; ep4 |= cp4; int p[4] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2), el.PNumMod(j+4)}; //int epp[4] = { ep1, ep2, ep3, ep4}; int cpp[4] = { cp1, cp2, cp3, cp4}; for(int k=0;k<0;k++) { INDEX_2 i2a=INDEX_2::Sort(p[k], p[(k+1)%4]); INDEX_2 i2b=INDEX_2::Sort(p[k], p[(k-1)%4]); if(!edges.Used(i2a) && !edges.Used(i2b)) cpp[k] = 1; } cp1= cpp[0]; cp2=cpp[1]; cp3=cpp[2]; cp4=cpp[3]; if(dim ==3) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); // i2.Sort(); isedge1 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge1=1; ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); // i2.Sort(); isedge2 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge2=1; ep2=1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); // i2.Sort(); isedge3 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge3=1; ep3=1; ep4=1; } i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); // i2.Sort(); isedge4 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge4=1; ep4=1; ep1=1; } //MH*********************************************************************************************************** if(ep1) if(edgepoint.Test(p[0])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[0], p[3]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp1 = 1; } if(ep2) if(edgepoint.Test(p[1])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp2 = 1; } if(ep3) if(edgepoint.Test(p[2])) { INDEX_2 i2a=INDEX_2::Sort(p[2], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp3 = 1; } if(ep4) if(edgepoint.Test(p[3])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[3]); INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp4 = 1; } //MH***************************************************************************************************************************** } else { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); i2.Sort(); isedge1 = edges.Used (i2); if(isedge1) { ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); i2.Sort(); isedge2 = edges.Used (i2); if(isedge2) { ep2=1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); i2.Sort(); isedge3 = edges.Used (i2); if(isedge3) { ep3=1; ep4=1; } i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); i2.Sort(); isedge4 = edges.Used (i2); if(isedge4) { ep4=1; ep1=1; } } int sumcp = cp1 + cp2 + cp3 + cp4; int sumep = ep1 + ep2 + ep3 + ep4; int sumedge = isedge1 + isedge2 + isedge3 + isedge4; *testout << "isedge = " << isedge1 << isedge2 << isedge3 << isedge4 << endl; *testout << "iscp = " << cp1 << cp2 << cp3 << cp4 << endl; *testout << "isep = " << ep1 << ep2 << ep3 << ep4 << endl; switch (sumedge) { case 0: { switch (sumep) { case 0: type = HP_QUAD; break; case 1: if (ep1) type = HP_QUAD_SINGCORNER; break; case 2: { if (ep1 && ep2) type = HP_QUAD_0E_2VA; if (ep1 && ep3) type = HP_QUAD_0E_2VB; break; } case 3: if (!ep4) type = HP_QUAD_0E_3V; break; case 4: type = HP_QUAD_0E_4V; break; } break; } case 1: { if (isedge1) { switch (cp1+cp2+ep3+ep4) { case 0: type = HP_QUAD_SINGEDGE; break; case 1: { if (cp1) type = HP_QUAD_1E_1VA; if (cp2) type = HP_QUAD_1E_1VB; if (ep3) type = HP_QUAD_1E_1VC; if (ep4) type = HP_QUAD_1E_1VD; break; } case 2: { if (cp1 && cp2) type = HP_QUAD_1E_2VA; if (cp1 && ep3) type = HP_QUAD_1E_2VB; if (cp1 && ep4) type = HP_QUAD_1E_2VC; if (cp2 && ep3) type = HP_QUAD_1E_2VD; if (cp2 && ep4) type = HP_QUAD_1E_2VE; if (ep3 && ep4) type = HP_QUAD_1E_2VF; break; } case 3: { if (cp1 && cp2 && ep3) type = HP_QUAD_1E_3VA; if (cp1 && cp2 && ep4) type = HP_QUAD_1E_3VB; if (cp1 && ep3 && ep4) type = HP_QUAD_1E_3VC; if (cp2 && ep3 && ep4) type = HP_QUAD_1E_3VD; break; } case 4: { type = HP_QUAD_1E_4V; break; } } } break; } case 2: { if (isedge1 && isedge4) { if (!cp2 && !ep3 && !cp4) type = HP_QUAD_2E; if (cp2 && !ep3 && !cp4) type = HP_QUAD_2E_1VA; if (!cp2 && ep3 && !cp4) type = HP_QUAD_2E_1VB; if (!cp2 && !ep3 && cp4) type = HP_QUAD_2E_1VC; if (cp2 && ep3 && !cp4) type = HP_QUAD_2E_2VA; if (cp2 && !ep3 && cp4) type = HP_QUAD_2E_2VB; if (!cp2 && ep3 && cp4) type = HP_QUAD_2E_2VC; if (cp2 && ep3 && cp4) type = HP_QUAD_2E_3V; } if (isedge1 && isedge3) { switch (sumcp) { case 0: type = HP_QUAD_2EB_0V; break; case 1: { if (cp1) type = HP_QUAD_2EB_1VA; if (cp2) type = HP_QUAD_2EB_1VB; break; } case 2: { if (cp1 && cp2) { type = HP_QUAD_2EB_2VA; } if (cp1 && cp3) { type = HP_QUAD_2EB_2VB; } if (cp1 && cp4) { type = HP_QUAD_2EB_2VC; } if (cp2 && cp4) { type = HP_QUAD_2EB_2VD; } break; } case 3: { if (cp1 && cp2 && cp3) { type = HP_QUAD_2EB_3VA; } if (cp1 && cp2 && cp4) { type = HP_QUAD_2EB_3VB; } break; } case 4: { type = HP_QUAD_2EB_4V; break; } } } break; } case 3: { if (isedge1 && isedge2 && isedge4) { if (!cp3 && !cp4) type = HP_QUAD_3E; if (cp3 && !cp4) type = HP_QUAD_3E_3VA; if (!cp3 && cp4) type = HP_QUAD_3E_3VB; if (cp3 && cp4) type = HP_QUAD_3E_4V; } break; } case 4: { type = HP_QUAD_4E; break; } } if (type != HP_NONE) { int pnums[4]; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); pnums[3] = el.PNumMod (j+3); for (int k=0;k<4;k++) el[k] = pnums[k]; /* cout << " QUAD with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << "\t" << pnums[3] << endl << " of type " << type << endl; */ break; } } if (type == HP_NONE) { (*testout) << "undefined element" << endl << "cp = " << cp1 << cp2 << cp3 << cp4 << endl << "ep = " << ep1 << ep2 << ep3 << ep4 << endl << "isedge = " << isedge1 << isedge2 << isedge3 << isedge4 << endl; } *testout << "quad type = " << type << endl; return type; }
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); }
void MeshOptimize2d :: GenericImprove (Mesh & mesh) { if (!faceindex) { if (writestatus) PrintMessage (3, "Generic Improve"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) GenericImprove (mesh); faceindex = 0; } // int j, k, l, ri; int np = mesh.GetNP(); int ne = mesh.GetNSE(); // SurfaceElementIndex sei; // for (SurfaceElementIndex sei = 0; sei < ne; sei++) // { // const Element2d & el = mesh[sei]; // (*testout) << "element " << sei << ": " <<flush; // for(int j=0; j<el.GetNP(); j++) // (*testout) << el[j] << " " << flush; // (*testout) << "IsDeleted() " << el.IsDeleted()<< endl; // } bool ok; int olddef, newdef; ARRAY<ImprovementRule*> rules; ARRAY<SurfaceElementIndex> elmap; ARRAY<int> elrot; ARRAY<PointIndex> pmap; ARRAY<PointGeomInfo> pgi; int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); ImprovementRule * r1; // 2 triangles to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3)); r1->oldels.Append (Element2d (3, 2, 4)); r1->newels.Append (Element2d (1, 2, 4, 3)); r1->deledges.Append (INDEX_2 (2,3)); r1->onp = 4; r1->bonus = 2; rules.Append (r1); // 2 quad to 1 quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (4, 3, 2, 5)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // swap quads r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 6, 3, 4)); r1->newels.Append (Element2d (1, 2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // three quads to 2 r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (3, 6, 7, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->newels.Append (Element2d (4, 5, 6, 7)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 7; r1->bonus = -1; rules.Append (r1); // quad + 2 connected trigs to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->oldels.Append (Element2d (3, 5, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 5)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // quad + 2 non-connected trigs to quad (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 3, 4, 5)); r1->newels.Append (Element2d (1, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 2, 4, 5)); r1->newels.Append (Element2d (4, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // two quad + trig -> one quad + trig r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (4, 3, 6)); r1->newels.Append (Element2d (1, 2, 6, 4)); r1->newels.Append (Element2d (2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 6; r1->bonus = -1; rules.Append (r1); // swap quad + trig (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (2, 5, 3, 4)); r1->newels.Append (Element2d (1, 2, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (1, 2, 5, 3)); r1->newels.Append (Element2d (1, 3, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // 2 quads to quad + 2 trigs r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 5, 6, 4)); r1->newels.Append (Element2d (1, 2, 5)); r1->newels.Append (Element2d (4, 6, 3)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; // rules.Append (r1); ARRAY<int> mapped(rules.Size()); ARRAY<int> used(rules.Size()); used = 0; mapped = 0; for (int ri = 0; ri < rules.Size(); ri++) { ImprovementRule & rule = *rules[ri]; rule.incelsonnode.SetSize (rule.onp); rule.reused.SetSize (rule.onp); for (int j = 1; j <= rule.onp; j++) { rule.incelsonnode.Elem(j) = 0; rule.reused.Elem(j) = 0; } for (int j = 1; j <= rule.oldels.Size(); j++) { const Element2d & el = rule.oldels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) rule.incelsonnode.Elem(el.PNum(k))--; } for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & el = rule.newels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) { rule.incelsonnode.Elem(el.PNum(k))++; rule.reused.Elem(el.PNum(k)) = 1; } } } TABLE<int,PointIndex::BASE> elonnode(np); ARRAY<int,PointIndex::BASE> nelonnode(np); TABLE<SurfaceElementIndex> nbels(ne); nelonnode = -4; for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) elonnode.Add (el[j], sei); } if(!el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) nelonnode[el[j]]++; } } for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) { for (int k = 0; k < elonnode[el[j]].Size(); k++) { int nbel = elonnode[el[j]] [k]; bool inuse = false; for (int l = 0; l < nbels[sei].Size(); l++) if (nbels[sei][l] == nbel) inuse = true; if (!inuse) nbels.Add (sei, nbel); } } } } for (int ri = 0; ri < rules.Size(); ri++) { const ImprovementRule & rule = *rules[ri]; elmap.SetSize (rule.oldels.Size()); elrot.SetSize (rule.oldels.Size()); pmap.SetSize (rule.onp); pgi.SetSize (rule.onp); for (SurfaceElementIndex sei = 0; sei < ne; sei++) { if (multithread.terminate) break; if (mesh[sei].IsDeleted()) continue; elmap[0] = sei; FlatArray<SurfaceElementIndex> neighbours = nbels[sei]; for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++) { const Element2d & el0 = mesh[sei]; const Element2d & rel0 = rule.oldels[0]; if (el0.GetIndex() != faceindex) continue; if (el0.IsDeleted()) continue; if (el0.GetNP() != rel0.GetNP()) continue; pmap = -1; for (int k = 0; k < el0.GetNP(); k++) { pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1); pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1); } ok = 1; for (int i = 1; i < elmap.Size(); i++) { // try to find a mapping for reference-element i const Element2d & rel = rule.oldels[i]; bool possible = 0; for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++) { const Element2d & el = mesh[neighbours[elmap[i]]]; if (el.IsDeleted()) continue; if (el.GetNP() != rel.GetNP()) continue; for (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++) { possible = 1; for (int k = 0; k < rel.GetNP(); k++) if (pmap.Elem(rel[k]) != -1 && pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1)) possible = 0; if (possible) { for (int k = 0; k < el.GetNP(); k++) { pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1); pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1); } break; } } if (possible) break; } if (!possible) { ok = 0; break; } elmap[i] = neighbours[elmap[i]]; } for(int i=0; ok && i<rule.deledges.Size(); i++) { ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()), pmap.Elem(rule.deledges[i].I2())); } if (!ok) continue; mapped[ri]++; olddef = 0; for (int j = 1; j <= pmap.Size(); j++) olddef += sqr (nelonnode[pmap.Get(j)]); olddef += rule.bonus; newdef = 0; for (int j = 1; j <= pmap.Size(); j++) if (rule.reused.Get(j)) newdef += sqr (nelonnode[pmap.Get(j)] + rule.incelsonnode.Get(j)); if (newdef > olddef) continue; // calc metric badness double bad1 = 0, bad2 = 0; Vec<3> n; SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1)); GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n); for (int j = 1; j <= rule.oldels.Size(); j++) bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n); // check new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); for (int k = 1; k <= rnel.GetNP(); k++) nel.PNum(k) = pmap.Get(rnel.PNum(k)); bad2 += nel.CalcJacobianBadness (mesh.Points(), n); } if (bad2 > 1e3) continue; if (newdef == olddef && bad2 > bad1) continue; // generate new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); nel.SetIndex (faceindex); for (int k = 1; k <= rnel.GetNP(); k++) { nel.PNum(k) = pmap.Get(rnel.PNum(k)); nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k)); } mesh.AddSurfaceElement(nel); } for (int j = 0; j < rule.oldels.Size(); j++) mesh.DeleteSurfaceElement ( elmap[j] ); for (int j = 1; j <= pmap.Size(); j++) nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j); used[ri]++; } } } mesh.Compress(); for (int ri = 0; ri < rules.Size(); ri++) { PrintMessage (5, "rule ", ri+1, " ", mapped[ri], "/", used[ri], " mapped/used"); } }