public void ReinitializeVerticeArrays() { for (int i = 0; i < 3; i++) { vrts[i] = e0.vrts[ExtendedElement.TetraIdxOfFaceVertex(fidx0, i)]; vrts[i + 3] = e1.vrts[ExtendedElement.TetraIdxOfFaceVertex(fidx1, (i + relativeOrientationIndex) % 3)]; } Node temp = vrts[5]; vrts[5] = vrts[4]; vrts[4] = temp; }
// convert normal geometry to extended public static void Extend(this Mesh mg) { // replace Nodes, Faces and Elements with Extended for (int i = 0; i < mg.nodes.Count; i++) { mg.nodes[i] = new ExtendedNode(mg.nodes[i]); } for (int i = 0; i < mg.faces.Count; i++) { Face fc = mg.faces[i]; ExtendedFace exfc = new ExtendedFace(); for (int j = 0; j < 3; j++) { exfc.vrts[j] = mg.nodes[fc.vrts[j].id]; } exfc.granule = fc.granule; exfc.tag = fc.tag; mg.faces[i] = exfc; } for (int i = 0; i < mg.elems.Count; i++) { Element elem = mg.elems[i]; ExtendedElement exelem = new ExtendedElement(); exelem.id = i; exelem.granule = elem.granule; for (int j = 0; j < 4; j++) { exelem.vrts[j] = mg.nodes[elem.vrts[j].id]; } mg.elems[i] = exelem; } foreach (GranuleEdge ge in mg.edges) { ge.vrts[0] = mg.nodes[ge.vrts[0].id]; ge.vrts[1] = mg.nodes[ge.vrts[1].id]; } Trace.Assert(mg.czs.Count == 0, "mg.czs already initialized"); }
int relativeOrientationIndex = -1; // used when creating CZ from Face public ExtendedCZ(Face f, ExtendedElement e0, ExtendedElement e1) { // create a CZ from a face that connects 2 elements this.e0 = e0; this.e1 = e1; Trace.Assert(e0 != e1, "CZ connects two identicla elements"); Trace.Assert(e0.granule != e1.granule, $"CZ connects same granule, g0: {e0.granule} g1: {e1.granule}"); fidx0 = e0.WhichFace(f); fidx1 = e1.WhichFace(f); Node firstNd = e0.vrts[ExtendedElement.TetraIdxOfFaceVertex(fidx0, 0)]; relativeOrientationIndex = -1; for (int i = 0; i < 3; i++) { Node testNd = e1.vrts[ExtendedElement.TetraIdxOfFaceVertex(fidx1, i)]; if (testNd == firstNd) { relativeOrientationIndex = i; break; } } Trace.Assert(relativeOrientationIndex != -1); }
public static void InsertCohesiveElements(this Mesh mg) { Trace.Assert(mg.czs.Count == 0, "CZs can be inserted only once"); mg.Extend(); mg.IdentifyParentsOfTriangles(); // connectivity information for nodes foreach (ExtendedNode nd in mg.nodes) { nd.elementsOfNode.Clear(); } foreach (Element e in mg.elems) { foreach (ExtendedNode n in e.vrts) { n.elementsOfNode.Add(e); if (!n.granules.Contains(e.granule)) { n.granules.Add(e.granule); } } } // preserve the exposed faces List <ExtendedFace> surface = new List <ExtendedFace>(); List <ExtendedFace> innerTris = new List <ExtendedFace>(); foreach (ExtendedFace f in mg.faces) { if (f.elementsOfFace.Count == 1) { surface.Add(f); } else if (f.elementsOfFace.Count == 2) { innerTris.Add(f); } } foreach (Face f in surface) { foreach (Node nd in f.vrts) { nd.isSurface = true; } } List <Tuple <ExtendedElement, int> > surfaceFaces = new List <Tuple <ExtendedElement, int> >(); // (element, faceIdx) format foreach (ExtendedFace f in mg.faces) { foreach (ExtendedElement e in f.elementsOfFace) { Trace.Assert(e.ContainsFace(f), "error in .elementsOfFace"); int which = e.WhichFace(f); // exposed faces are preserved in surfaceFaces if (f.elementsOfFace.Count == 1) { surfaceFaces.Add(new Tuple <ExtendedElement, int>(e, which)); } e.faces.Add(which); } } // store all edges within extended elements foreach (GranuleEdge ge in mg.edges) { ExtendedNode nd = (ExtendedNode)ge.vrts[0]; foreach (ExtendedElement elem in nd.elementsOfNode) { elem.AddEdgeIfContains(ge); } } // convert inner triangles into cohesive elements foreach (ExtendedFace f in innerTris) { ExtendedElement e0 = (ExtendedElement)f.elementsOfFace[0]; ExtendedElement e1 = (ExtendedElement)f.elementsOfFace[1]; ExtendedCZ ecz = new ExtendedCZ(f, e0, e1); mg.czs.Add(ecz); } // list the nodes, which are connected to CZs foreach (Face t in innerTris) { foreach (ExtendedNode n in t.vrts) { n._belongs_to_cz = true; } } List <ExtendedNode> nczs = new List <ExtendedNode>(); foreach (ExtendedNode nd in mg.nodes) { if (nd._belongs_to_cz) { nczs.Add(nd); } } // create linked list LinkedList <Node> ll = new LinkedList <Node>(mg.nodes); LinkedListNode <Node> lln = ll.First; do { ((ExtendedNode)lln.Value).ll_node = lln; lln = lln.Next; } while (lln != null); // split the nodes, which belong to cohesive elements foreach (ExtendedNode nd in nczs) { nd.SplitNode(ll); } // linked list becomes the new list of nodes; resequence mg.nodes = new List <Node>(ll); for (int i = 0; i < mg.nodes.Count; i++) { mg.nodes[i].id = i; } // infer cz.vrts[] from fidx foreach (ExtendedCZ cz in mg.czs) { cz.ReinitializeVerticeArrays(); } // restore the list of faces and the list of edges mg.edges.Clear(); mg.faces.Clear(); foreach (ExtendedElement e in mg.elems) { foreach (int i in e.edges) { mg.edges.Add(e.GetEdge(i)); } } foreach (GranuleEdge ge in mg.edges) { ge.exposed = true; } // first, create exposed faces from surfaceFaces array foreach (Tuple <ExtendedElement, int> tuple in surfaceFaces) { ExtendedElement elem = tuple.Item1; int which = tuple.Item2; Face fc = elem.GetFace(which); fc.exposed = true; fc.id = mg.faces.Count; mg.faces.Add(fc); } // create non-exposed faces from CZs, record their references into cz.faces foreach (ExtendedCZ cz in mg.czs) { Face fc = cz.e0.GetFace(cz.fidx0); fc.elem = cz.e0; cz.faces[0] = fc; fc.granule = cz.e0.granule; fc.exposed = false; fc.id = mg.faces.Count; mg.faces.Add(fc); fc = cz.e1.GetFace(cz.fidx1); fc.elem = cz.e1; cz.faces[1] = fc; fc.exposed = false; fc.id = mg.faces.Count; fc.granule = cz.e1.granule; mg.faces.Add(fc); } // convert extended nodes back to regular mg.ConvertBack(); mg.DetectSurfacesAfterLoadingMSH(); for (int i = 0; i < mg.czs.Count; i++) { mg.czs[i].immutableID = i; } }