/// <summary> /// Returns the crack path after repeatedly executing: XFEM analysis, SIF calculation, crack propagation /// </summary> /// <returns></returns> public void Analyze() { int analysisStep; for (analysisStep = 0; analysisStep < maxIterations; ++analysisStep) { Debug.WriteLine($"Crack propagation step {analysisStep}"); Console.WriteLine($"Crack propagation step {analysisStep}"); // Apply the updated enrichements. crack.UpdateEnrichments(); // Update the mesh partitioning and identify unmodified subdomains to avoid fully processing them again. UpdateSubdomains(); // Order and count dofs solver.OrderDofs(false); foreach (ILinearSystem linearSystem in linearSystems.Values) { if (linearSystem.Subdomain.ConnectivityModified) { linearSystem.Reset(); // Necessary to define the linear system's size linearSystem.Subdomain.Forces = Vector.CreateZero(linearSystem.Size); } } // Create the stiffness matrix and then the forces vector //problem.ClearMatrices(); BuildMatrices(); model.AssignLoads(solver.DistributeNodalLoads); foreach (ILinearSystem linearSystem in linearSystems.Values) { linearSystem.RhsVector = linearSystem.Subdomain.Forces; } AddEquivalentNodalLoadsToRhs(); // Plot domain decomposition data, if necessary if (DDLogger != null) { DDLogger.PlotSubdomains(model); } // Solve the linear system solver.Solve(); //// Output field data //if (fieldOutput != null) //{ // fieldOutput.WriteOutputData(solver.DofOrderer, freeDisplacements, constrainedDisplacements, iteration); //} // Let the crack propagate //Vector constrainedDisplacements = model.CalculateConstrainedDisplacements(solver.DofOrderer); var freeDisplacements = new Dictionary <int, Vector>(); foreach (int s in linearSystems.Keys) { freeDisplacements[s] = (Vector)(linearSystems[s].Solution); //TODO: avoid this cast. } crack.Propagate(freeDisplacements); // Check convergence //TODO: Perhaps this should be done by the crack geometry or the Propagator itself and handled via exceptions foreach (var tipPropagator in crack.CrackTipPropagators) { double sifEffective = CalculateEquivalentSIF(tipPropagator.Value.Logger.SIFsMode1[analysisStep], tipPropagator.Value.Logger.SIFsMode2[analysisStep]); //Console.WriteLine("Keff = " + sifEffective); if (sifEffective >= fractureToughness) { Termination = CrackPropagationTermination.FractureToughnessIsExceeded; return; } if (!model.Boundary.IsInside(tipPropagator.Key)) { Termination = CrackPropagationTermination.CrackExitsDomainBoundary; return; } } } Termination = CrackPropagationTermination.RequiredIterationsWereCompleted; }