/// <summary> /// /// </summary> /// <param name="mesh"></param> /// <param name="crack"></param> /// <param name="magnificationOfJintegralRadius">The outer countour of the J-integral domain is defined as: /// radius = magnification * sqrt(areaOfElementContainingTip). This parameter is the magnification. /// It should be at least 1.5 (see "Modeling quasi-static crack growth with the extended finite element /// method Part II: Numerical applications, Huang et al, 2003" page 7546). Usually values 2-3 are selected /// (see Ahmed thesis, 2009).</param> /// <param name="auxiliaryStatesStrategy"></param> /// <param name="sifCalculationStrategy"></param> public Propagator(IMesh2D <XNode, XContinuumElement2D> mesh, double magnificationOfJintegralRadius, IAuxiliaryStates auxiliaryStatesStrategy, ISIFCalculator sifCalculationStrategy, ICrackGrowthDirectionLaw2D growthDirectionLaw, ICrackGrowthLengthLaw2D growthLengthLaw) { this.mesh = mesh; this.magnificationOfJintegralRadius = magnificationOfJintegralRadius; this.auxiliaryStatesStrategy = auxiliaryStatesStrategy; this.sifCalculationStrategy = sifCalculationStrategy; this.growthDirectionLaw = growthDirectionLaw; this.growthLengthLaw = growthLengthLaw; this.Logger = new PropagationLogger(); }
/// <summary> /// Given a set of Heaviside enriched nodes, find which of them must not be enriched, in order to avoid the global /// stiffness matrix being singular. /// </summary> /// <param name="mesh"></param> /// <param name="heavisideNodes">They will not be altered.</param> /// <returns></returns> public ISet <XNode> FindHeavisideNodesToRemove(ISingleCrack crack, IMesh2D <XNode, XContinuumElement2D> mesh, ISet <XNode> heavisideNodes) { var processedElements = new Dictionary <XContinuumElement2D, Tuple <double, double> >(); var nodesToRemove = new HashSet <XNode>(); foreach (var node in heavisideNodes) { double nodePositiveArea = 0.0; double nodeNegativeArea = 0.0; foreach (var element in mesh.FindElementsWithNode(node)) { bool alreadyProcessed = processedElements.TryGetValue(element, out Tuple <double, double> elementPosNegAreas); if (!alreadyProcessed) { (double elementPosArea, double elementNegArea) = FindSignedAreasOfElement(crack, element); elementPosNegAreas = new Tuple <double, double>(elementPosArea, elementNegArea); processedElements[element] = elementPosNegAreas; } nodePositiveArea += elementPosNegAreas.Item1; nodeNegativeArea += elementPosNegAreas.Item2; } if (crack.SignedDistanceOf(node) >= 0.0) { double negativeAreaRatio = nodeNegativeArea / (nodePositiveArea + nodeNegativeArea); if (negativeAreaRatio < relativeAreaTolerance) { nodesToRemove.Add(node); } } else { double positiveAreaRatio = nodePositiveArea / (nodePositiveArea + nodeNegativeArea); if (positiveAreaRatio < relativeAreaTolerance) { nodesToRemove.Add(node); } } } return(nodesToRemove); }
public GuidedPartioner2D(IMesh2D <TNode, TElement> mesh, Dictionary <int, IRegion2D> regions) { this.mesh = mesh; this.regions = regions; }