/***************************************************/ // Convert Guanaco mesh to Rhino mesh. public static Rhino.Geometry.Mesh GetRhinoMesh(Mesh mesh, out List <LineCurve> barElements) { barElements = new List <LineCurve>(); Rhino.Geometry.Mesh rhinoMesh = new Rhino.Geometry.Mesh(); foreach (Node node in mesh.Nodes) { rhinoMesh.Vertices.Add(node.Location); } foreach (Element element in mesh.Elements) { if (element is Element2D) { Element2D e = element as Element2D; int[] nodeIds = e.Nodes.Take(e.PrimaryNodeCount).Select(n => n.Id.AsInteger).ToArray(); if (nodeIds.Length == 4) { rhinoMesh.Faces.AddFace(nodeIds[0], nodeIds[1], nodeIds[2], nodeIds[3]); } else if (nodeIds.Length == 3) { rhinoMesh.Faces.AddFace(nodeIds[0], nodeIds[1], nodeIds[2]); } } else if (element is Element1D) { Element1D e = element as Element1D; barElements.Add(new LineCurve(rhinoMesh.Vertices[e.Nodes.First().Id.AsInteger], rhinoMesh.Vertices[e.Nodes.Last().Id.AsInteger])); } } return(rhinoMesh); }
/***************************************************/ // Apply pressure load to the elements laying within tolerance from the pressure area. private void ApplyLoad(PressureLoad load) { foreach (Element e in this._mesh.Elements) { // Check if the element is 2D. Element2D el = e as Element2D; if (el == null) { continue; } // Check if the element is adjoining to the pressure area (if all its vertices lie within tolerance) - if yes then apply the load. Point3d elC = el.GetCentroid(); foreach (Brep s in load.Surfaces) { bool broken = false; foreach (Point3d v in el.GetVertices()) { if (v.DistanceTo(s.ClosestPoint(v)) > this._tolerance) { broken = true; break; } } if (!broken) { el.AddPressure(load.LoadValue * 1); } } } }
/***************************************************/ // Apply infill load to the adjoining elements. private void ApplyLoad(InfillLoad load) { foreach (Element e in this._mesh.Elements) { // Check if the element is 2D. Element2D el = e as Element2D; if (el == null) { continue; } Point3d elC = el.GetCentroid(); Vector3d elN = el.GetNormal(); foreach (Infill i in load.Infills) { // Check if the element is adjoining to the infill (if all its vertices lie within tolerance). bool broken = false; foreach (Point3d v in el.GetVertices()) { if (v.DistanceTo(i.Volume.ClosestPoint(v)) > this._tolerance) { broken = true; break; } } // If the element is adjoining to the infill, apply the load based on location of the element and load function of the infill. if (!broken) { // Flip normal of the element if it points outside the infill. Point3d cpt = Point3d.Add(elC, elN * this._tolerance); if (!i.Volume.IsPointInside(cpt, Rhino.RhinoMath.SqrtEpsilon, true)) { el.FlipNormal(); } // Check if the element is not surrounded by the infill from both sides - if it is then do nothing (no hydrostatic pressure). else { cpt = Point3d.Add(elC, -elN * this._tolerance); if (i.Volume.IsPointInside(cpt, Rhino.RhinoMath.SqrtEpsilon, true)) { continue; } } // Apply the load based on location of the element and load function of the infill. string g = load.InfillDensity.ToString(GuanacoUtil.Invariant); string x = (i.MaxZ - elC.Z).ToString(GuanacoUtil.Invariant); string z = (i.MaxZ - i.MinZ).ToString(GuanacoUtil.Invariant); string f = load.LoadFunction.Replace("g", g).Replace("x", x).Replace("z", z); double p = GuanacoUtil.Evaluate(f); el.AddPressure(-p); } } } }
/***************************************************/ // Assign elements to the component after meshing. public override void AssignElements(List <Element> elements) { this._elements = elements; foreach (Element element in elements) { Element2D e = element as Element2D; e.FEType = this._feType; } }
// Clone to a target mesh. public override GuanacoObject Clone(Mesh targetMesh, bool newID = false) { Element2D e = this.Clone(newID) as Element2D; if (targetMesh != null) { targetMesh.AddElement(e, this._id.AsInteger); e._nodes = this._nodes.Select(n => targetMesh.Nodes[n.Id.AsInteger]).ToList(); } return(e); }
/***************************************************/ // Populate the element with points - used for preview purposes to show pressure loads. public static List <Point3d> PopulateWithPoints(this Element2D element) { List <Point3d> corners = element.Nodes.Take(element.PrimaryNodeCount).Select(n => n.Location).ToList(); Surface srf; if (corners.Count == 3) { srf = NurbsSurface.CreateFromCorners(corners[0], corners[1], corners[2]); } else { srf = NurbsSurface.CreateFromCorners(corners[0], corners[1], corners[2], corners[3]); } corners.Add(corners[0]); Polyline perim = new Polyline(corners); double minDist = perim.Length * 0.01; List <Point3d> srfPts = new List <Point3d>(); Interval uDomain = srf.Domain(0); Interval vDomain = srf.Domain(1); double uMin = uDomain.Min; double uMax = uDomain.Max; double vMin = vDomain.Min; double vMax = vDomain.Max; double uStep = (uMax - uMin) / 3; double vStep = (vMax - vMin) / 3; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { srfPts.Add(srf.PointAt(uMin + i * uStep, vMin + j * vStep)); } } Brep srfBrep = srf.ToBrep(); List <Point3d> pts = new List <Point3d>(); foreach (Point3d pt in srfPts) { if (srfBrep.ClosestPoint(pt).DistanceTo(pt) <= minDist && perim.ClosestPoint(pt).DistanceTo(pt) > minDist) { pts.Add(pt); } } return(pts); }
/***************************************************/ //Clone. public override GuanacoObject Clone(bool newID = false) { Element2D e = this.ShallowClone(newID) as Element2D; e._nodes = this._nodes.Select(n => n.Clone(newID) as Node).ToList(); e._orientation = new Vector3d[] { new Vector3d(this._orientation[0]), new Vector3d(this._orientation[1]) }; e._results = new Dictionary <string, double[]>(this._results); foreach (string r in this._results.Keys) { e._results[r] = this._results[r].ToArray(); } e._parentCollection = null; e._id = null; return(e); }
/***************************************************/ // Read results for 2D elements from the output file. public static void Read2DElementResults(Model model, ResultGroup resultType, int step = 0, double totalTime = 1.0) { if (model.Panels.Count == 0) { return; } // Find Ids of 2D elements. List <int> nonComposite2DIds = new List <int>(); foreach (Element e in model.Mesh.Elements) { if (e is Element2D && !(e as Element2D).Composite) { nonComposite2DIds.Add(e.Id.AsInteger); } } if (nonComposite2DIds.Count == 0) { return; } // Read result lines. string[] resLines = File.ReadAllLines(model.GetModelFilePath(GuanacoUtil.FileType.frd)); string line; // Find ids of vertices of each element. List <int[]> vertIds = new List <int[]>(); int elCount = 0; bool elInfo = false; for (int i = 0; i < resLines.Length; i++) { line = resLines[i].TrimStart(' '); if (!elInfo && line.StartsWith("3C")) { elInfo = true; continue; } else if (elInfo && line.StartsWith("-1")) { int elId = int.Parse(line.Split(GuanacoUtil.Space, StringSplitOptions.RemoveEmptyEntries)[1]) - 1; if (elId == nonComposite2DIds[elCount]) { Element2D e = model.Mesh.Elements[elId] as Element2D; i++; line = resLines[i].TrimStart(' '); int[] splt = line.Split(GuanacoUtil.Space, StringSplitOptions.RemoveEmptyEntries).Skip(1).Select(s => int.Parse(s)).ToArray(); vertIds.Add(splt.Take(e.PrimaryNodeCount * 2).ToArray()); elCount++; if (elCount == nonComposite2DIds.Count) { break; } } } else if (elInfo && line.StartsWith("-3")) { break; } } // Read the results per each vertex. Dictionary <int, double[]> nodeValues = new Dictionary <int, double[]>(); int resid = GetFirstResultLine(resLines, resultType, GuanacoUtil.FileType.frd, step, totalTime); line = resLines[resid]; string start = "-1"; while (start == "-1") { int nodeId = int.Parse(line.Substring(4, 9)); double[] nodeValue = new double[6]; int i = 13; for (int j = 0; j < 6; j++) { string resultString = line.Substring(i, 12); double resultValue = double.NaN; if (double.TryParse(resultString, GuanacoUtil.FloatNum, GuanacoUtil.Invariant, out resultValue)) { nodeValue[j] = resultValue; } else if (resultString.Substring(9) == "INF") { nodeValue[j] = resultString[8] == '-' ? double.NegativeInfinity : double.PositiveInfinity; } else { throw new Exception("The result format is incorrect, please inspect the result .frd file."); } i += 12; } nodeValues.Add(nodeId, nodeValue); resid++; line = resLines[resid]; start = line.Substring(1, 2); } // Assign the values to the elements. for (int i = 0; i < nonComposite2DIds.Count; i++) { Element2D e = model.Mesh.Elements[nonComposite2DIds[i]] as Element2D; int vertCount = vertIds[i].Length; Type type = null; switch (resultType) { case ResultGroup.Stress: type = typeof(Stress2D); break; case ResultGroup.Strain: type = typeof(Strain2D); break; } string[] names = Enum.GetNames(type).Skip(1).ToArray(); foreach (string name in names) { if (!e.Results.ContainsKey(name)) { e.AddResult(name, new double[vertCount]); } } for (int j = 0; j < vertCount; j++) { double[] vertValues = nodeValues[vertIds[i][j]]; for (int k = 0; k < names.Length; k++) { e.Results[names[k]][j] = vertValues[k]; } } } }
/***************************************************/ // Apply support to the nodes laying within tolerance from the support geometry. private void ApplySupport(Support support) { foreach (GeometryBase g in support.Geometry) { if (g is Point) { Point p = g as Point; Point3d pt = p.Location; foreach (Node node in this._mesh.Nodes) { if (node.Primary && node.Location.DistanceTo(pt) <= this._tolerance) { support.Nodes.Add(node); } } } else if (g is Curve) { Curve c = g as Curve; double t; foreach (Node node in this._mesh.Nodes) { if (node.Primary) { c.ClosestPoint(node.Location, out t); if (c.PointAt(t).DistanceTo(node.Location) <= this._tolerance) { support.Nodes.Add(node); } } } } else if (g is Brep) { Brep b = g as Brep; foreach (Node node in this._mesh.Nodes) { if (node.Primary) { Point3d bpt = b.ClosestPoint(node.Location); if (node.Location.DistanceTo(bpt) <= this._tolerance) { support.Nodes.Add(node); } } } } else { throw new Exception("Unknown support geometry type! " + support.Name); } } // If the physical fixing of the support is chosen, then instead of fixing rotational stiffness within chosen nodes, fix translation in all nodes of the supported elements. if (support.SupportType.Physical) { List <Node> baseNodes = support.Nodes.ToList(); foreach (Element e in this._mesh.Elements) { Element2D el = e as Element2D; if (e == null) { continue; } HashSet <Node> elNodes = new HashSet <Node>(el.Nodes.Take(el.PrimaryNodeCount)); foreach (Node node in baseNodes) { if (elNodes.Any(n => n == node)) { support.Nodes.UnionWith(elNodes); break; } } } } }
/***************************************************/ // Build CalculiX input file. public virtual void BuildCCXFile(bool nonLinear) { List <string> outputLines = new List <string>(); // Write mesh topology information. outputLines.AddRange(this._mesh.ToCCX()); // Write support information. foreach (Support s in this._supports) { outputLines.AddRange(s.ToCCX()); } // Write material information. foreach (Material m in this._materials.Items) { outputLines.AddRange((m as dynamic).ToCCX()); } // Write bar information. foreach (Bar bar in this._bars) { outputLines.AddRange(bar.ToCCX()); } // Write panel information. foreach (Panel panel in this._panels) { outputLines.AddRange(panel.ToCCX()); } // Write information about the analysis mode. outputLines.Add(nonLinear ? "*STEP,NLGEOM" : "*STEP"); outputLines.Add("*STATIC"); // Set pressure and gravity loads (element loads). outputLines.Add("*DLOAD"); foreach (Element element in this._mesh.Elements) { if (element is Element2D) { Element2D e = element as Element2D; if (e.Pressure != 0) { outputLines.Add(e.PressureToCCX()); } } } if (this._gravity.Length > 0) { outputLines.Add(String.Format("Eall, GRAV,{0},{1},{2},{3}", Gravity.Length, Gravity.X / Gravity.Length, Gravity.Y / Gravity.Length, Gravity.Z / Gravity.Length)); } // Set nodal loads. outputLines.Add("*CLOAD"); foreach (Node n in this._mesh.Nodes) { outputLines.AddRange(n.LoadToCCX()); } // Set sections in which the bar results are to be calculated. foreach (Element e in this._mesh.Elements) { if (e is Element1D) { outputLines.AddRange((e as Element1D).CCXSectionResults()); } } // Set output format. outputLines.AddRange(new List <string> { "*EL FILE,GLOBAL=NO", "S, E", "*NODE PRINT,NSET=Nall,GLOBAL=YES", "U", "*END STEP" }); // Write the information to file. TextWriter tw = new System.IO.StreamWriter(this.GetModelFilePath(GuanacoUtil.FileType.inp)); foreach (String s in outputLines) { tw.WriteLine(s); } tw.Close(); // Set the info about building the file. this._CCXFileBuilt = true; }
/***************************************************/ // Calculate the display factors dependent on the size of the model and its elements. public static double[] sizeFactors(this Model model) { BoundingBox bBox = new BoundingBox(model.Mesh.Nodes.Select(x => x.Location)); double forceFactor = 0; double elementFactor = bBox.Diagonal.Length; foreach (Panel panel in model.Panels) { foreach (Element element in panel.Elements) { Element2D e = element as Element2D; List <Point3d> eVertices = e.GetVertices().ToList(); if (e.PrimaryNodeCount == 3) { for (int i = 0; i < 3; i++) { double edgeL = eVertices[i].DistanceTo(eVertices[(i + 1) % 3]); if (edgeL <= elementFactor) { elementFactor = edgeL; } } } else { for (int i = 0; i < 2; i++) { double diagL = eVertices[i].DistanceTo(eVertices[i + 2]); if (diagL <= elementFactor) { elementFactor = diagL; } } } if (e.Pressure != 0 && Math.Abs(e.Pressure) >= forceFactor) { forceFactor = Math.Abs(e.Pressure); } } } foreach (Bar bar in model.Bars) { foreach (Element element in bar.Elements) { Element1D e = element as Element1D; Point3d[] eVertices = e.GetVertices().ToArray(); double l = eVertices[0].DistanceTo(eVertices[1]); if (l <= elementFactor) { elementFactor = l; } } } foreach (Node n in model.Mesh.Nodes) { if (n.ForceLoad.Length != 0 && Math.Abs(n.ForceLoad.Length) >= forceFactor) { forceFactor = Math.Abs(n.ForceLoad.Length); } } elementFactor *= 0.3; return(new double[] { elementFactor, forceFactor }); }
/***************************************************/ // Create the preview of panels. public static void AddPanelPreview(this Rhino.Display.CustomDisplay display, Model model, IEnumerable <int> ids, out HashSet <int> nodeIds, double graphicFactor, double elementFactor, double textFactor, double forceFactor, bool showComponentNumbers, bool showElementNumbers, bool showLCS, bool showLoads, bool showLoadValues, bool showEdges, bool showThk = false, Grasshopper.GUI.Gradient.GH_Gradient gradient = null, string panelResultType = "None", bool showResultValues = false) { nodeIds = new HashSet <int>(); if (model.Panels.Count == 0) { return; } // Take all results out first to determine min & max, otherwise could be done inside the loop. Dictionary <int, double> panelTopResults = new Dictionary <int, double>(); Dictionary <int, double> panelBottomResults = new Dictionary <int, double>(); double panelMax = 0; double panelMin = 0; if (panelResultType != "None") { Dictionary <int, double[]> panelResults = model.Mesh.GetElementResults(panelResultType); foreach (KeyValuePair <int, double[]> elResult in panelResults) { int id = elResult.Key; double[] results = elResult.Value; int halfResultCount = results.Length / 2; panelTopResults.Add(id, results.Skip(halfResultCount).Average()); panelBottomResults.Add(id, results.Take(halfResultCount).Average()); } panelMax = Math.Max(panelTopResults.Values.Max(), panelBottomResults.Values.Max()); panelMin = Math.Min(panelTopResults.Values.Min(), panelBottomResults.Values.Min()); } ids = ids.Count() == 0 ? Enumerable.Range(0, model.Panels.Count) : ids.Select(i => i - 1); foreach (int i in ids) { Panel panel = model.Panels[i]; if (showComponentNumbers) { Vector3d fOffset = panel.LCS.ZAxis * 0.002; if (showThk) { fOffset += panel.LCS.ZAxis * 0.5 * panel.Thickness; } Plane fp = new Plane(panel.LCS.Origin + fOffset, panel.LCS.ZAxis); Plane bp = new Plane(panel.LCS.Origin - fOffset, -panel.LCS.ZAxis); Rhino.Display.Text3d ft = new Rhino.Display.Text3d("Panel " + panel.CCXId(), fp, elementFactor * 0.6 * textFactor); Rhino.Display.Text3d bt = new Rhino.Display.Text3d("Panel " + panel.CCXId(), bp, elementFactor * 0.6 * textFactor); ft.Bold = true; bt.Bold = true; display.AddText(ft, Color.DarkRed); display.AddText(bt, Color.DarkRed); } foreach (Element element in panel.Elements) { Element2D e = element as Element2D; int eId = e.Id.AsInteger; foreach (Node n in e.Nodes.Take(e.PrimaryNodeCount)) { nodeIds.Add(n.Id.AsInteger); } Color bottomColor; Color topColor; if (panelResultType == "None") { bottomColor = topColor = Color.Aqua; } else { bottomColor = gradient.ColourAt((panelBottomResults[eId] - panelMin) / (panelMax - panelMin)); topColor = gradient.ColourAt((panelTopResults[eId] - panelMin) / (panelMax - panelMin)); } Point3d centroid = e.GetCentroid(); Vector3d normal = e.GetNormal(); Vector3d minOffset = normal * 0.001; Vector3d offset = showThk ? normal * 0.5 * panel.Thickness : minOffset; List <Point3d> front = new List <Point3d>(); List <Point3d> back = new List <Point3d>(); foreach (Point3d v in e.GetVertices()) { front.Add(v + offset); back.Add(v - offset); } display.AddPolygon(front, topColor, Color.Black, true, showEdges); display.AddPolygon(back, bottomColor, Color.Black, true, showEdges); if (showThk) { front.Add(front[0]); back.Add(back[0]); for (int j = 0; j < front.Count - 1; j++) { List <Point3d> fv = front.GetRange(j, 2); List <Point3d> bv = back.GetRange(j, 2); bv.Reverse(); fv.AddRange(bv); display.AddPolygon(fv, Color.Aqua, Color.Black, true, true); } } Plane tp = new Plane(panel.LCS); tp.Origin = centroid + offset + minOffset; tp.XAxis *= -1; tp.ZAxis *= -1; Plane bp = new Plane(panel.LCS); bp.Origin = centroid - offset - minOffset; if (showResultValues && panelTopResults.Count != 0) { Rhino.Display.Text3d t1 = new Rhino.Display.Text3d(panelTopResults[eId].ToString("G2"), tp, elementFactor * 0.4 * textFactor); t1.Bold = true; display.AddText(t1, Color.Black); Rhino.Display.Text3d t2 = new Rhino.Display.Text3d(panelBottomResults[eId].ToString("G2"), bp, elementFactor * 0.4 * textFactor); t2.Bold = true; display.AddText(t2, Color.Black); } if (showLCS) { display.AddVector(centroid, e.Orientation[0] * elementFactor * graphicFactor, Color.Red); display.AddVector(centroid, e.Orientation[1] * elementFactor * graphicFactor, Color.Green); display.AddVector(centroid, normal * elementFactor * graphicFactor, Color.Blue); } if (showLoads && e.Pressure != 0) { Vector3d pv = normal * e.Pressure / forceFactor * elementFactor * 5 * graphicFactor; List <Point3d> pressurePoints = new List <Point3d>(); foreach (Point3d pt in e.PopulateWithPoints()) { if (e.Pressure > 0) { display.AddVector(pt - pv - offset, pv); } else { display.AddVector(pt - pv + offset, pv); } } if (showLoadValues) { Plane p; if (e.Pressure > 0) { p = new Plane(e.GetCentroid() - pv * 1.1 - offset, Vector3d.XAxis, Vector3d.ZAxis); } else { p = new Plane(e.GetCentroid() - pv * 1.1 + offset, Vector3d.XAxis, Vector3d.ZAxis); } Rhino.Display.Text3d t = new Rhino.Display.Text3d(e.Pressure.ToString("G2"), p, elementFactor * 0.4 * textFactor); t.Bold = true; display.AddText(t, Color.Magenta); } } if (showElementNumbers) { Rhino.Display.Text3d tt = new Rhino.Display.Text3d(e.CCXId(), tp, elementFactor * 0.4 * textFactor); Rhino.Display.Text3d bt = new Rhino.Display.Text3d(e.CCXId(), bp, elementFactor * 0.4 * textFactor); tt.Bold = true; bt.Bold = true; display.AddText(tt, Color.Black); display.AddText(bt, Color.Black); } } } }
/***************************************************/ // Read mesh file and convert it to Guanaco mesh format. public static void ReadMesh(Model model, bool reducedIntegration) { // Create empty mesh, initiate local variables. int barCounter = 0; int panelCounter = 0; bool nodeLines, elementLines, componentLines; nodeLines = elementLines = componentLines = false; string[] itemSep = new string[] { "," }; // Read the mesh file. string line; int elementOrder = -1; int elementDimension = -1; List <int> elementList = new List <int>(); Dictionary <int, int> elementPairs = new Dictionary <int, int>(); System.IO.StreamReader file = new System.IO.StreamReader(model.GetModelFilePath() + "_Mesh.inp"); while ((line = file.ReadLine()) != null) { if (line.StartsWith("*NODE") && !line.StartsWith("*NODE ")) { nodeLines = true; continue; } else if (nodeLines && line.StartsWith("*")) { nodeLines = false; } // Create Guanaco node based on the given line of input file. else if (nodeLines) { string[] nodeInfo = line.Replace("\n", "").Split(itemSep, StringSplitOptions.None); double x = Double.Parse(nodeInfo[1], GuanacoUtil.FloatNum); double y = Double.Parse(nodeInfo[2], GuanacoUtil.FloatNum); double z = Double.Parse(nodeInfo[3], GuanacoUtil.FloatNum); model.Mesh.AddNode(new Node(x, y, z)); } if (line.StartsWith("*ELEMENT, type=")) { elementLines = true; string elementShape = line.Replace(" ", "").Substring(14).Split(',')[0]; switch (elementShape) { case "T3D2": elementOrder = 1; elementDimension = 1; break; case "T3D3": elementOrder = 2; elementDimension = 1; break; case "CPS3": case "CPS4": elementOrder = 1; elementDimension = 2; break; case "CPS6": case "CPS8": elementOrder = 2; elementDimension = 2; break; default: throw new Exception("Incorrect element type! Check if all elements in the .inp file are supported by Guanaco."); } } else if (elementLines && line.StartsWith("*")) { elementLines = false; } // Create Guanaco element based on the given line of input file. else if (elementLines) { string[] elInfo = line.Replace("\n", "").Split(itemSep, StringSplitOptions.None); List <Node> elementNodes = new List <Node>(); for (int i = 1; i < elInfo.Length; i++) { int id = int.Parse(elInfo[i]) - 1; elementNodes.Add(model.Mesh.Nodes[id]); } Element el; if (elementDimension == 1) { // Add element. el = new Element1D(elementNodes, elementOrder, reducedIntegration); model.Mesh.AddElement(el as Element1D); // Set primary nodes of an element. elementNodes[0].Primary = true; elementNodes.Last().Primary = true; } else if (elementDimension == 2) { // Add element. el = new Element2D(elementNodes, elementOrder, reducedIntegration); model.Mesh.AddElement(el as Element2D); // Set primary nodes of an element. for (int i = 0; i < (el as Element2D).PrimaryNodeCount; i++) { elementNodes[i].Primary = true; } } else { throw new Exception("Unsupported element found!"); } elementPairs.Add(int.Parse(elInfo[0]), el.Id.AsInteger); } if (componentLines && !Char.IsDigit(line[0])) { if (elementDimension == 1) { model.Bars[barCounter].AssignElements(elementList.Select(e => model.Mesh.Elements[e]).ToList()); barCounter++; } else if (elementDimension == 2) { model.Panels[panelCounter].AssignElements(elementList.Select(e => model.Mesh.Elements[e]).ToList()); panelCounter++; } elementList = new List <int>(); } if (line.StartsWith("*ELSET,")) { componentLines = true; if (line.Contains("PhysicalLine")) { elementDimension = 1; } else if (line.Contains("PhysicalSurface")) { elementDimension = 2; } else { throw new Exception("Gmsh physical entity type not known."); } } else if (componentLines && line.StartsWith("*")) { componentLines = false; } // Assign the mesh elements to relevant components. else if (componentLines) { string[] sa = line.Replace("\n", "").Split(itemSep, StringSplitOptions.RemoveEmptyEntries); foreach (string s in sa) { int id; if (Int32.TryParse(s, out id)) { elementList.Add(elementPairs[id]); } } } } if (elementList.Count > 0) { if (elementDimension == 1) { model.Bars[barCounter].AssignElements(elementList.Select(e => model.Mesh.Elements[e]).ToList()); } else if (elementDimension == 2) { model.Panels[panelCounter].AssignElements(elementList.Select(e => model.Mesh.Elements[e]).ToList()); } } file.Close(); }