Ejemplo n.º 1
0
        private static void SolverLinearStatics()
        {
            SolverFunctions Fun = new SolverFunctions();
            Stopwatch       sw  = new Stopwatch(); sw.Start();

            // Others
            int    inc       = 1;
            string separator = "  ========================================================== ";

            // Initialize time 0 and time 1
            foreach (Node N in DB.NodeLib.Values)
            {
                N.Initialize_StepZero();
                N.Initialize_NewDisp(inc);
            }
            foreach (Element E in DB.ElemLib.Values)
            {
                E.Initialize_StepZero(DB.FELib);
                E.Initialize_Increment(inc);
            }

            // Console paragraph
            Console.WriteLine("\n" + separator);
            Console.WriteLine("        LINEAR STATIC ANALYSIS ");
            Console.WriteLine(separator);

            // *****************************************************************************
            // ========================= MAIN FINITE ELEMENT CODE ==========================
            // *****************************************************************************

            //  ============================ Essential boundary conditions ======================================

            // DoF list with kinematic BC
            List <int> Fix_DOF = new List <int>();

            foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "SPC"))
            {
                foreach (int NID in BC.NodalValues.Keys)
                {
                    if (BC.NodalValues[NID].Get(0, 0) == 1)
                    {
                        Fix_DOF.Add(DB.NodeLib[NID].DOF[0]);
                    }
                    if (BC.NodalValues[NID].Get(1, 0) == 1)
                    {
                        Fix_DOF.Add(DB.NodeLib[NID].DOF[1]);
                    }
                    if (BC.NodalValues[NID].Get(2, 0) == 1)
                    {
                        Fix_DOF.Add(DB.NodeLib[NID].DOF[2]);
                    }
                }
            }

            // Sort and remove duplicates of kinematic BC
            Fix_DOF = Fix_DOF.Distinct().ToList();
            Fix_DOF.Sort();

            // Define Row index reduction - rows and columns related to Dirichlet BC are removed from K matrix and F vector
            int[] nDOF_reduction = new int[DB.nDOF];
            for (int i = 0; i < Fix_DOF.Count; i++)
            {
                nDOF_reduction[Fix_DOF[i]] = -1;
            }

            int reduc = 0;

            for (int i = 0; i < DB.nDOF; i++)
            {
                if (nDOF_reduction[i] == -1)
                {
                    reduc++;
                }
                else
                {
                    nDOF_reduction[i] = reduc;
                }
            }

            //  ============================ F (Right hand side) Vector =========================================

            double[] F = new double[DB.nDOF - Fix_DOF.Count];

            foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "PointLoad"))
            {
                foreach (int NID in BC.NodalValues.Keys)
                {
                    for (int dir = 0; dir < 3; dir++)
                    {
                        if (nDOF_reduction[DB.NodeLib[NID].DOF[dir]] != -1)
                        {
                            if (inc == 1)
                            {
                                F[DB.NodeLib[NID].DOF[dir] - nDOF_reduction[DB.NodeLib[NID].DOF[dir]]] +=
                                    BC.NodalValues[NID].Get(dir, 0);
                            }
                        }
                    }
                }
            }

            // ============================== GLOBAL STIFFNESS MATRIX ===================================

            alglib.sparsematrix K = Fun.ParallelAssembly_K(DB, nDOF_reduction, inc, "Initial");

            // ============================== SOLVING LINEAR SYSTEM ===================================

            double[] U = new double[DB.nDOF - Fix_DOF.Count];

            if (DB.AnalysisLib.GetLinSolver() == "CG")
            {
                U = Fun.LinearSolver_CG(K, F, DB.AnalysisLib);
            }
            if (DB.AnalysisLib.GetLinSolver() == "Cholesky")
            {
                U = Fun.LinearSolver_Cholesky(K, F);
            }
            if (DB.AnalysisLib.GetLinSolver() == "LU")
            {
                U = Fun.LinearSolver_LU(K, F);
            }

            // ================== U (Left hand side) vector reconstruction =====================================

            double[] U_Full = Fun.Include_BC_DOF(U, nDOF_reduction);

            // Assign displacements to nodes (replace dU vector and update dU Buffer)
            foreach (Node n in DB.NodeLib.Values)
            {
                n.dU_buffer[0] = U_Full[n.DOF[0]];
                n.dU_buffer[1] = U_Full[n.DOF[1]];
                n.dU_buffer[2] = U_Full[n.DOF[2]];

                //Console.Write("Node " + n.ID + " disp: "); Fun.Print_Vector(n.dU_buffer, 3);
            }

            // Internal Forces vector
            double[] R = new double[DB.nDOF];

            Console.Write("   Stress recovery: ");
            Parallel.ForEach(DB.ElemLib.Values, Elem =>
            {
                Elem.Recovery_Stress(DB);
                Elem.Compute_NodalForces(DB);

                // Assembly Nodal Forces vector
                for (int i = 0; i < Elem.NList.Count; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        R[DB.NodeLib[Elem.NList[i]].DOF[j]] += Elem.NodalForces.GetFast(3 * i + j, 0);
                    }
                }
            });

            R = Fun.Exclude_BC_DOF(R, nDOF_reduction);
            Console.WriteLine("            Done");

            // Update nodal displacement, element stress and strain
            foreach (Node n in DB.NodeLib.Values)
            {
                n.Update_Displacement(inc);
            }
            foreach (Element E in DB.ElemLib.Values)
            {
                E.Update_StrainStress(inc);
            }

            // Print CPU time summary
            sw.Stop();
            Console.WriteLine("\n" + separator);
            Console.WriteLine("  Total CPU time: " + sw.Elapsed.TotalSeconds.ToString("F2", CultureInfo.InvariantCulture) + " s");
            Console.WriteLine(separator);
        }
Ejemplo n.º 2
0
        private static void SolverNonlinearStatics()
        {
            SolverFunctions Fun = new SolverFunctions();
            Stopwatch       sw  = new Stopwatch(); sw.Start();

            // Analysis settings
            double tolerance = 0.001;

            // Others
            string separator = "  ========================================================== ";


            // Initialize time 0 and time 1
            foreach (Node N in DB.NodeLib.Values)
            {
                N.Initialize_StepZero();
            }
            foreach (Element E in DB.ElemLib.Values)
            {
                E.Initialize_StepZero(DB.FELib);
            }

            // Console paragraph
            Console.WriteLine("\n" + separator);
            if (DB.AnalysisLib.GetAnalysisType().StartsWith("Linear"))
            {
                Console.WriteLine("        LINEAR STATIC ANALYSIS ");
            }
            if (DB.AnalysisLib.GetAnalysisType().StartsWith("Nonlinear"))
            {
                Console.WriteLine("        NONLINEAR STATIC ANALYSIS ");
            }
            Console.WriteLine(separator);

            // *****************************************************************************
            // ========================= MAIN FINITE ELEMENT CODE ==========================
            // *****************************************************************************


            //  ============================ Essential boundary conditions ======================================

            // DoF list with kinematic BC
            List <int> Fix_DOF = new List <int>();

            foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "SPC"))
            {
                foreach (int NID in BC.NodalValues.Keys)
                {
                    if (BC.NodalValues[NID].Get(0, 0) == 1)
                    {
                        Fix_DOF.Add(DB.NodeLib[NID].DOF[0]);
                    }
                    if (BC.NodalValues[NID].Get(1, 0) == 1)
                    {
                        Fix_DOF.Add(DB.NodeLib[NID].DOF[1]);
                    }
                    if (BC.NodalValues[NID].Get(2, 0) == 1)
                    {
                        Fix_DOF.Add(DB.NodeLib[NID].DOF[2]);
                    }
                }
            }

            // Sort and remove duplicates of kinematic BC
            Fix_DOF = Fix_DOF.Distinct().ToList();
            Fix_DOF.Sort();

            // Define Row index reduction - rows and columns related to Dirichlet BC are removed from K matrix and F vector
            int[] nDOF_reduction = new int[DB.nDOF];
            for (int i = 0; i < Fix_DOF.Count; i++)
            {
                nDOF_reduction[Fix_DOF[i]] = -1;
            }

            int reduc = 0;

            for (int i = 0; i < DB.nDOF; i++)
            {
                if (nDOF_reduction[i] == -1)
                {
                    reduc++;
                }
                else
                {
                    nDOF_reduction[i] = reduc;
                }
            }


            //  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  INCREMENTAL ANALYSIS   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

            for (int inc = 1; inc <= DB.AnalysisLib.GetIncNumb(); inc++)
            {
                Console.WriteLine("\n" + separator);
                Console.WriteLine("      INCREMENT " + inc);
                Console.WriteLine(separator);

                // Initialize Nodal displacements for new increment
                foreach (Node n in DB.NodeLib.Values)
                {
                    n.Initialize_NewDisp(inc);
                }

                // Initialize Element Strain and Stress for new increment
                foreach (Element Elem in DB.ElemLib.Values)
                {
                    Elem.Initialize_Increment(inc);
                }

                //  ============================ F (Right hand side) Vector =========================================

                double[] F = new double[DB.nDOF - Fix_DOF.Count];

                foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "PointLoad"))
                {
                    foreach (int NID in BC.NodalValues.Keys)
                    {
                        for (int dir = 0; dir < 3; dir++)
                        {
                            if (nDOF_reduction[DB.NodeLib[NID].DOF[dir]] != -1)
                            {
                                if (inc == 1)
                                {
                                    F[DB.NodeLib[NID].DOF[dir] - nDOF_reduction[DB.NodeLib[NID].DOF[dir]]] +=
                                        BC.NodalValues[NID].Get(dir, 0) * inc / DB.AnalysisLib.GetIncNumb();
                                }
                            }
                        }
                    }
                }

                // ================================    NEWTON-RAPHSON ITERATION   =====================================
                int    iter    = 0;
                double NormF   = Fun.Vector_Norm(F);
                double NormRes = 1;

                // Iteration zero:
                Console.WriteLine("  ITERATION 0: ");
                alglib.sparsematrix K = Fun.ParallelAssembly_K(DB, nDOF_reduction, inc, "Initial");


                // Newton loop
                while (NormRes > tolerance)
                //while (iter<1)
                {
                    if (iter > 0)
                    {
                        Console.WriteLine("  ITERATION " + iter + ": ");
                        K = Fun.ParallelAssembly_K(DB, nDOF_reduction, inc, "Tangent");
                        Fun.Print_Matrix(K, 6, 8);
                    }

                    // ============================== SOLVING LINEAR SYSTEM ===================================

                    double[]            U  = new double[DB.nDOF - Fix_DOF.Count];
                    alglib.sparsematrix K1 = (alglib.sparsematrix)K.make_copy();

                    if (DB.AnalysisLib.GetLinSolver() == "CG")
                    {
                        U = Fun.LinearSolver_CG(K1, F, DB.AnalysisLib);
                    }

                    if (DB.AnalysisLib.GetLinSolver() == "Cholesky")
                    {
                        U = Fun.LinearSolver_Cholesky(K1, F);
                    }

                    if (DB.AnalysisLib.GetLinSolver() == "LU")
                    {
                        U = Fun.LinearSolver_LU(K1, F);
                    }

                    // ================== U (Left hand side) vector reconstruction =====================================

                    double[] U_Full = Fun.Include_BC_DOF(U, nDOF_reduction);

                    // Assign displacements to nodes (replace dU vector and update dU Buffer)
                    foreach (Node n in DB.NodeLib.Values)
                    {
                        n.dU[0] = U_Full[n.DOF[0]];   n.dU_buffer[0] += U_Full[n.DOF[0]];
                        n.dU[1] = U_Full[n.DOF[1]];   n.dU_buffer[1] += U_Full[n.DOF[1]];
                        n.dU[2] = U_Full[n.DOF[2]];   n.dU_buffer[2] += U_Full[n.DOF[2]];

                        //Console.Write("Node " + n.ID + " disp: ");  Fun.Print_Vector(n.dU_buffer, 3);
                    }

                    // Internal Forces vector
                    double[] R = new double[DB.nDOF];

                    Console.Write("   Stress recovery: ");
                    Parallel.ForEach(DB.ElemLib.Values, Elem =>
                    {
                        Elem.Recovery_Stress(DB);
                        Elem.Compute_NodalForces(DB);

                        // Assembly Nodal Forces vector
                        for (int i = 0; i < Elem.NList.Count; i++)
                        {
                            for (int j = 0; j < 3; j++)
                            {
                                R[DB.NodeLib[Elem.NList[i]].DOF[j]] += Elem.NodalForces.GetFast(3 * i + j, 0);
                            }
                        }
                    });
                    R = Fun.Exclude_BC_DOF(R, nDOF_reduction);
                    Console.WriteLine("            Done");

                    Fun.Print_MatrixST(DB.ElemLib[1].dS[0].Transpose(), 1, 6);
                    Fun.Print_MatrixST(DB.ElemLib[1].dS[1].Transpose(), 1, 6);
                    Fun.Print_MatrixST(DB.ElemLib[1].dS[2].Transpose(), 1, 6);
                    Fun.Print_MatrixST(DB.ElemLib[1].dS[3].Transpose(), 1, 6);
                    Fun.Print_MatrixST(DB.ElemLib[1].dS[4].Transpose(), 1, 6);
                    Fun.Print_MatrixST(DB.ElemLib[1].dS[5].Transpose(), 1, 6);
                    Fun.Print_MatrixST(DB.ElemLib[1].dS[6].Transpose(), 1, 6);
                    Fun.Print_MatrixST(DB.ElemLib[1].dS[7].Transpose(), 1, 6);
                    Console.WriteLine("\n Nodal forces:");
                    Fun.Print_Vector(R, R.Length);
                    Console.WriteLine("\n");

                    // Calculate Residual Forces
                    double[] Residual = new double[DB.nDOF - Fix_DOF.Count];

                    for (int i = 0; i < F.Length; i++)
                    {
                        Residual[i] = F[i] - R[i];
                    }

                    // Calculate Residual Forces norm and extreme value
                    NormRes = Fun.Vector_Norm(Residual) / NormF;
                    double ExtremeResidual = Math.Max(Residual.Max(), Math.Abs(Residual.Min()));

                    Console.WriteLine("   Residual norm: " + NormRes.ToString("F4"));
                    Console.WriteLine("   Max residual force: " + ExtremeResidual.ToString("#0.0e+0") + "\n");
                    //Console.WriteLine("\nOut of balance forces:\n" + string.Join("\n", F.Where(x => x != 0)) + "\n");

                    // Next iteration
                    F = Residual;
                    iter++;
                }
                Console.WriteLine("  INCREMENT CONVERGED in " + iter + " iterations\n");

                // Update nodal displacement, element stress and strain
                foreach (Node N in DB.NodeLib.Values)
                {
                    N.Update_Displacement(inc);
                }
                foreach (Element E in DB.ElemLib.Values)
                {
                    E.Update_StrainStress(inc);
                }
            }

            sw.Stop();

            Console.WriteLine("\n" + separator);
            Console.WriteLine("  Total CPU time: " + sw.Elapsed.TotalSeconds.ToString("F2", CultureInfo.InvariantCulture) + " s");
            Console.WriteLine(separator);
        }