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); }
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. } }