public void InitializeGeometry(CartesianPoint crackMouth, CartesianPoint crackTip) { this.crackMouth = crackMouth; crackPath.Add(crackMouth); var segment = new DirectedSegment2D(crackMouth, crackTip); double tangentX = crackTip.X - crackMouth.X; double tangentY = crackTip.Y - crackMouth.Y; double length = Math.Sqrt(tangentX * tangentX + tangentY * tangentY); double tangentSlope = Math.Atan2(tangentY, tangentX); this.crackTip = crackTip; crackPath.Add(crackTip); tipSystem = new TipCoordinateSystem(crackTip, tangentSlope); CrackTipEnrichments.TipSystem = tipSystem; tangentX /= length; tangentY /= length; foreach (XNode node in Mesh.Nodes) { levelSetsBody[node] = segment.SignedDistanceOf(node); levelSetsTip[node] = (node.X - crackTip.X) * tangentX + (node.Y - crackTip.Y) * tangentY; } if (LevelSetLogger != null) { LevelSetLogger.InitialLog(); //TODO: handle this with a NullLogger. } }
public void UpdateGeometry(double localGrowthAngle, double growthLength) { double globalGrowthAngle = MathUtilities.WrapAngle(localGrowthAngle + tipSystem.RotationAngle); double dx = growthLength * Math.Cos(globalGrowthAngle); double dy = growthLength * Math.Sin(globalGrowthAngle); double unitDx = dx / growthLength; double unitDy = dy / growthLength; var oldTip = crackTip; var newTip = new CartesianPoint(oldTip.X + dx, oldTip.Y + dy); crackTip = newTip; tipSystem = new TipCoordinateSystem(newTip, globalGrowthAngle); var newSegment = new DirectedSegment2D(oldTip, newTip); foreach (XNode node in Mesh.Nodes) { // Rotate the ALL tip level sets towards the new tip and then advance them double rotatedTipLevelSet = (node.X - crackTip.X) * unitDx + (node.Y - crackTip.Y) * unitDy; levelSetsTip[node] = rotatedTipLevelSet - newSegment.Length; if (rotatedTipLevelSet > 0.0) // Only some body level sets are updated (See Stolarska 2001) { levelSetsBody[node] = newSegment.SignedDistanceOf(node); } } }
public HashSet <XNode> Update(CartesianPoint oldTip, double localGrowthAngle, double growthLength, double dx, double dy, IReadOnlyList <XNode> allNodes, ISet <XNode> crackBodyNodesAll, Dictionary <XNode, double> levelSetsBody, Dictionary <XNode, double> levelSetsTip) { double unitDx = dx / growthLength; double unitDy = dy / growthLength; var newTip = new CartesianPoint(oldTip.X + dx, oldTip.Y + dy); var newSegment = new DirectedSegment2D(oldTip, newTip); var crackBodyNodesModified = new HashSet <XNode>(); foreach (XNode node in allNodes) { // Rotate the ALL tip level sets towards the new tip and then advance them double rotatedTipLevelSet = (node.X - oldTip.X) * unitDx + (node.Y - oldTip.Y) * unitDy; levelSetsTip[node] = rotatedTipLevelSet - growthLength; // Only some body level sets are updated (See Stolarska 2001) // WARNING: this is quite dangerous. If the crack turns/kinks sufficiently over its whole history, then nodes far // alway from the tip that should remain unchanged, will get different level sets. A new formula is needed to // avoid messing them up. In a narrow band approach, it may be possible to limit the level set update in nodes // near to the old tip the new tip or the inbetween segment. if (rotatedTipLevelSet > 0.0) { levelSetsBody[node] = newSegment.SignedDistanceOf(node); if (crackBodyNodesAll.Contains(node)) { crackBodyNodesModified.Add(node); } } } if (crackBodyNodesModified.Count != 0) { Console.WriteLine("There are nodes that were previously enriched with Heaviside, but now their level set" + " changes. For 1st order LSM, this usually indicates that the crack has turned sufficiently towards" + " its original geometry. In that case, the body level set of these nodes is computed from the crack" + " extension far away from their position and is thus incorrect. These nodes are: "); foreach (var node in crackBodyNodesModified) { Console.WriteLine(node); } Console.WriteLine(); } return(crackBodyNodesModified); }
public void InitializeGeometry(CartesianPoint crackMouth, CartesianPoint crackTip) { CrackMouth = crackMouth; var segment = new DirectedSegment2D(crackMouth, crackTip); double tangentX = crackTip.X - crackMouth.X; double tangentY = crackTip.Y - crackMouth.Y; double length = Math.Sqrt(tangentX * tangentX + tangentY * tangentY); double tangentSlope = Math.Atan2(tangentY, tangentX); this.crackTip = crackTip; tipSystem = new TipCoordinateSystem(crackTip, tangentSlope); tangentX /= length; tangentY /= length; foreach (XNode node in Mesh.Nodes) { levelSetsBody[node] = segment.SignedDistanceOf(node); levelSetsTip[node] = (node.X - crackTip.X) * tangentX + (node.Y - crackTip.Y) * tangentY; } }