private static void RunTest()
        {
            IReadOnlyList <Dictionary <int, double> > expectedDisplacements = GetExpectedDisplacements();
            IncrementalDisplacementsLog computedDisplacements = SolveModel();

            Assert.True(AreDisplacementsSame(expectedDisplacements, computedDisplacements, 1e-9));
        }
        private static void WriteDisplacementsToFile(IncrementalDisplacementsLog log1, Dictionary <int, int[]> watchDof, double load)
        {
            // Output
            string pathName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

            string FileName     = "ForcesDisplacementsData.txt";
            string Extension    = Path.GetExtension(FileName);
            string fileNameOnly = Path.Combine(pathName, Path.GetFileNameWithoutExtension(FileName));
            string File         = string.Format("{0}{1}", fileNameOnly, Extension);

            var append = false;

            using (var writer = new StreamWriter(File, append))
            {
                writer.WriteLine(" IncrementalLoad     IncrementalDisplacement");
                writer.WriteLine(" ");
            }
            append = true;
            for (int i = 0; i < log1.dofDisplacementsPerIter.Count; i++)
            {
                using (var writer = new StreamWriter(File, append)) // append mode to continue from previous increment
                {
                    writer.WriteLine($"       {load * (i + 1) / log1.dofDisplacementsPerIter.Count}             {log1.dofDisplacementsPerIter[i][0][watchDof[0][0]]}");
                }
            }
        }
        private static void SolveModel()
        {
            var model = new Model();

            model.SubdomainsDictionary.Add(subdomainID, new Subdomain(subdomainID));

            var load = 850;

            BuildCantileverModel(model, load);

            // Solver
            var     solverBuilder = new SkylineSolver.Builder();
            ISolver solver        = solverBuilder.BuildSolver(model);

            // Problem type
            var provider = new ProblemStructural(model, solver);

            // Analyzers
            int increments           = 10;
            var childAnalyzerBuilder = new LoadControlAnalyzer.Builder(model, solver, provider, increments);

            childAnalyzerBuilder.ResidualTolerance             = 1E-5;
            childAnalyzerBuilder.MaxIterationsPerIncrement     = 100;
            childAnalyzerBuilder.NumIterationsForMatrixRebuild = 1;
            //childAnalyzerBuilder.SubdomainUpdaters = new[] { new NonLinearSubdomainUpdater(model.SubdomainsDictionary[subdomainID]) }; // This is the default
            LoadControlAnalyzer childAnalyzer = childAnalyzerBuilder.Build();
            var parentAnalyzer = new StaticAnalyzer(model, solver, provider, childAnalyzer);

            // Setup displacements log
            var watchDof = new Dictionary <int, int[]>();

            //watchDof.Add(subdomainID, new int[1] { 46 });
            watchDof.Add(subdomainID, new int[1] {
                94
            });
            var log1 = new IncrementalDisplacementsLog(watchDof);

            childAnalyzer.IncrementalDisplacementsLog = log1;

            // Run the analysis
            parentAnalyzer.Initialize();
            parentAnalyzer.Solve();

            // Write log data to file
            WriteDisplacementsToFile(log1, watchDof, load);
        }
        private static IncrementalDisplacementsLog SolveModel()
        {
            //VectorExtensions.AssignTotalAffinityCount();
            Model model = new Model();

            model.SubdomainsDictionary.Add(subdomainID, new Subdomain(subdomainID));

            BuildCantileverModel(model, 850);

            // Solver
            var     solverBuilder = new SkylineSolver.Builder();
            ISolver solver        = solverBuilder.BuildSolver(model);

            // Problem type
            var provider = new ProblemStructural(model, solver);

            // Analyzers
            int increments           = 2;
            var childAnalyzerBuilder = new LoadControlAnalyzer.Builder(model, solver, provider, increments);

            childAnalyzerBuilder.ResidualTolerance             = 1E-8;
            childAnalyzerBuilder.MaxIterationsPerIncrement     = 100;
            childAnalyzerBuilder.NumIterationsForMatrixRebuild = 1;
            //childAnalyzerBuilder.SubdomainUpdaters = new[] { new NonLinearSubdomainUpdater(model.SubdomainsDictionary[subdomainID]) }; // This is the default
            LoadControlAnalyzer childAnalyzer = childAnalyzerBuilder.Build();
            var parentAnalyzer = new StaticAnalyzer(model, solver, provider, childAnalyzer);

            // Output
            var watchDofs = new Dictionary <int, int[]>();

            watchDofs.Add(subdomainID, new int[5] {
                0, 11, 23, 35, 47
            });
            var log1 = new IncrementalDisplacementsLog(watchDofs);

            childAnalyzer.IncrementalDisplacementsLog = log1;

            // Run the anlaysis
            parentAnalyzer.Initialize();
            parentAnalyzer.Solve();



            return(log1);
        }
        private static bool AreDisplacementsSame(IReadOnlyList <Dictionary <int, double> > expectedDisplacements, IncrementalDisplacementsLog computedDisplacements, double tolerance)
        {
            var comparer = new ValueComparer(tolerance);

            for (int iter = 0; iter < expectedDisplacements.Count; ++iter)
            {
                foreach (int dof in expectedDisplacements[iter].Keys)
                {
                    if (!comparer.AreEqual(expectedDisplacements[iter][dof], computedDisplacements.GetTotalDisplacement(iter, subdomainID, dof)))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }