private IList <Vector> FEAnalysisCantilever2LoadCases(Matrix x)
        {
            int numLoadCases = 2;
            int numAllDofs   = 2 * (nelx + 1) * (nely + 1);
            var K            = DokSymmetric.CreateEmpty(numAllDofs);
            var F            = new Vector[] { Vector.CreateZero(numAllDofs), Vector.CreateZero(numAllDofs) };
            var U            = new Vector[] { Vector.CreateZero(numAllDofs), Vector.CreateZero(numAllDofs) };

            Matrix Ke             = ElementStiffness();
            int    numElementDofs = Ke.NumRows;

            int[] elementDofsLocal = Enumerable.Range(0, numElementDofs).ToArray();

            // Global stiffness matrix assembly
            for (int ely = 1; ely <= nely; ++ely)
            {
                for (int elx = 1; elx <= nelx; ++elx)
                {
                    int[]  elementDofsGlobal = GetElementDofs(elx, ely);
                    double density           = Math.Pow(x[ely - 1, elx - 1], penal);
                    K.AddSubmatrixSymmetric(density * Ke, elementDofsLocal, elementDofsGlobal);
                }
            }

            // Define supports for cantilever beam
            IEnumerable <int> fixedDofs = Enumerable.Range(0, 2 * (nely + 1));

            int[] freeDofs = Enumerable.Range(0, numAllDofs).Except(fixedDofs).ToArray();

            // Load case 1: unit load towards -y at bottom right corner
            F[0][2 * (nelx + 1) * (nely + 1) - 1] = -1.0;

            // Load case 2: unit load towards +y at top right corner
            F[1][2 * (nelx) * (nely + 1) + 1] = 1.0;

            // Solve linear system
            CholeskyCSparseNet factorizedKf = CholeskyCSparseNet.Factorize(
                K.GetSubmatrix(freeDofs).BuildSymmetricCscMatrix(true)); // only factorize the matrix once

            for (int c = 0; c < numLoadCases; ++c)
            {
                Vector Ff = F[c].GetSubvector(freeDofs);
                Vector Uf = factorizedKf.SolveLinearSystem(Ff);
                for (int i = 0; i < freeDofs.Length; ++i)
                {
                    U[c][freeDofs[i]] = Uf[i];
                }
                //U[c].CopyNonContiguouslyFrom(freeDofs, Uf, Enumerable.Range(0, freeDofs.Length).ToArray()); // alternative way, but probably slower.
                //foreach (int i in fixedDofs) U[c][i] = 0.0; // They are 0 by default
            }
            return(U);
        }
Example #2
0
        private static void TestSystemSolution()
        {
            int order   = SparsePosDef10by10.Order;
            var skyline = SkylineMatrix.CreateFromArrays(order, SparsePosDef10by10.SkylineValues,
                                                         SparsePosDef10by10.SkylineDiagOffsets, true, true);
            var dok       = DokSymmetric.CreateFromSparseMatrix(skyline);
            var b         = Vector.CreateFromArray(SparsePosDef10by10.Rhs);
            var xExpected = Vector.CreateFromArray(SparsePosDef10by10.Lhs);

            (double[] cscValues, int[] cscRowIndices, int[] cscColOffsets) = dok.BuildSymmetricCscArrays(true);
            var    factor    = CholeskyCSparseNet.Factorize(order, cscValues.Length, cscValues, cscRowIndices, cscColOffsets);
            Vector xComputed = factor.SolveLinearSystem(b);

            comparer.AssertEqual(xExpected, xComputed);
        }
        private IList <Vector> FEAnalysisHalfMbbBeam(Matrix x)
        {
            int numAllDofs = 2 * (nelx + 1) * (nely + 1);
            var K          = DokSymmetric.CreateEmpty(numAllDofs);
            var F          = Vector.CreateZero(numAllDofs);
            var U          = Vector.CreateZero(numAllDofs);

            Matrix Ke             = ElementStiffness();
            int    numElementDofs = Ke.NumRows;

            int[] elementDofsLocal = Enumerable.Range(0, numElementDofs).ToArray();

            // Global stiffness matrix assembly
            for (int ely = 1; ely <= nely; ++ely)
            {
                for (int elx = 1; elx <= nelx; ++elx)
                {
                    int[]  elementDofsGlobal = GetElementDofs(elx, ely);
                    double density           = Math.Pow(x[ely - 1, elx - 1], penal);
                    K.AddSubmatrixSymmetric(density * Ke, elementDofsLocal, elementDofsGlobal);
                }
            }

            // Define loads and supports for half MBB beam
            F[1] = -1.0;
            var fixedDofs = new HashSet <int>(); //TODO: Use LINQ to simplify this

            for (int i = 0; i < 2 * (nely + 1); i += 2)
            {
                fixedDofs.Add(i);
            }
            fixedDofs.Add(numAllDofs - 1);
            int[] freeDofs = Enumerable.Range(0, numAllDofs).Except(fixedDofs).ToArray();

            // Solve linear system
            DokSymmetric Kf = K.GetSubmatrix(freeDofs);
            Vector       Ff = F.GetSubvector(freeDofs);
            Vector       Uf = CholeskyCSparseNet.Factorize(Kf.BuildSymmetricCscMatrix(true)).SolveLinearSystem(Ff);

            for (int i = 0; i < freeDofs.Length; ++i)
            {
                U[freeDofs[i]] = Uf[i];
            }
            //U.CopyNonContiguouslyFrom(freeDofs, Uf, Enumerable.Range(0, freeDofs.Length).ToArray()); // alternative way, but probably slower.
            //foreach (int i in fixedDofs) U[i] = 0.0; // They are 0 by default

            return(new Vector[] { U });
        }
        public void UpdateModelAndAnalyze(IVectorView youngModuli)
        {
            this.youngModuli = youngModuli;

            // Global stiffness matrix assembly
            int numAllDofs = 2 * (numElementsX + 1) * (numElementsY + 1);
            var K          = DokSymmetric.CreateEmpty(numAllDofs);

            for (int e = 0; e < NumElements; ++e)
            {
                int[] elementDofsGlobal = GetElementDofs(e);
                K.AddSubmatrixSymmetric(unitStiffness.Scale(youngModuli[e]), elementDofsLocal, elementDofsGlobal);
            }

            // Apply boundary conditions
            (int[] freeDofs, Vector[] Fs) = ApplyBoundaryConditions();
            int numLoadCases = Fs.Length;

            globalDisplacements = new Vector[numLoadCases];

            // Solve linear system
            DokSymmetric Kf     = K.GetSubmatrix(freeDofs);
            var          factor = CholeskyCSparseNet.Factorize(Kf.BuildSymmetricCscMatrix(true));

            for (int c = 0; c < numLoadCases; ++c)
            {
                Vector Ff = Fs[c].GetSubvector(freeDofs);
                Vector Uf = factor.SolveLinearSystem(Ff);
                var    U  = Vector.CreateZero(numAllDofs);
                for (int i = 0; i < freeDofs.Length; ++i)
                {
                    U[freeDofs[i]] = Uf[i];
                }
                globalDisplacements[c] = U;
                //U.CopyNonContiguouslyFrom(freeDofs, Uf, Enumerable.Range(0, freeDofs.Length).ToArray()); // alternative way, but probably slower.
            }
        }