/// <summary> /// Assembles the stiffness matrix of defined model and return it back. /// </summary> /// <returns>Assembled stiffness matrix</returns> public static CCS AssembleFullStiffnessMatrix(Model model) { model.ReIndexNodes(); var elements = model.Elements; var maxNodePerElement = model.Elements.Any() ? model.Elements.Select(i => i.Nodes.Length).Max() : 1; var rElmMap = new int[maxNodePerElement * 6]; var c = model.Nodes.Count * 6; var kt = new CoordinateStorage <double>(c, c, c); foreach (var elm in elements) { var c2 = elm.Nodes.Length; for (var i = 0; i < c2; i++) { rElmMap[6 * i + 0] = elm.Nodes[i].Index * 6 + 0; rElmMap[6 * i + 1] = elm.Nodes[i].Index * 6 + 1; rElmMap[6 * i + 2] = elm.Nodes[i].Index * 6 + 2; rElmMap[6 * i + 3] = elm.Nodes[i].Index * 6 + 3; rElmMap[6 * i + 4] = elm.Nodes[i].Index * 6 + 4; rElmMap[6 * i + 5] = elm.Nodes[i].Index * 6 + 5; } var mtx = elm.GetGlobalStifnessMatrix(); var d = c2 * 6; for (var i = 0; i < d; i++) { for (var j = 0; j < d; j++) { kt.At(rElmMap[i], rElmMap[j], mtx[i, j]); } } mtx.ReturnToPool(); } var stiffness = (CCS)Converter.ToCompressedColumnStorage(kt, true); return(stiffness); }
/// <summary> /// Generates the permutation for delta for specified model in specified loadCase. /// Note that delta permutation = P_delta in reduction process /// </summary> /// <param name="target">The target.</param> /// <param name="loadCase">The load case.</param> /// <returns>delta permutation</returns> public static CCS GenerateP_Delta(Model target, LoadCase loadCase) { throw new NotImplementedException(); target.ReIndexNodes(); var buf = new CoordinateStorage <double>(target.Nodes.Count * 6, target.Nodes.Count * 6, 1); #region rigid elements foreach (var elm in target.RigidElements) { var centralNode = elm.Nodes[0]; var masterIdx = centralNode.Index; for (var i = 1; i < elm.Nodes.Count; i++) { var slaveIdx = elm.Nodes[i].Index; var d = centralNode.Location - elm.Nodes[i].Location; //buf[0, 4] = -(buf[1, 3] = d.Z); //buf[2, 3] = -(buf[0, 5] = d.Y); //buf[1, 5] = -(buf[2, 4] = d.X); buf.At(6 * slaveIdx + 0, 6 * masterIdx + 0, 1); buf.At(6 * slaveIdx + 1, 6 * masterIdx + 1, 1); buf.At(6 * slaveIdx + 2, 6 * masterIdx + 2, 1); buf.At(6 * slaveIdx + 1, 6 * masterIdx + 3, d.Z); buf.At(6 * slaveIdx + 0, 6 * masterIdx + 4, -d.Z); buf.At(6 * slaveIdx + 0, 6 * masterIdx + 5, d.Y); buf.At(6 * slaveIdx + 2, 6 * masterIdx + 3, -d.Y); // buf.At(6 * slaveIdx + 2, 6 * masterIdx + 4, d.X); // buf.At(6 * slaveIdx + 1, 6 * masterIdx + 5, -d.X); } //add to buf } #endregion throw new NotImplementedException(); return(buf.ToCCs()); }
public static CCS GenerateP_Delta_Mpc(Model target, LoadCase loadCase, IRrefFinder rrefFinder) { target.ReIndexNodes(); var n = target.Nodes.Count; var boundaryConditions = GetModelBoundaryConditions(target, loadCase); var lastRow = 0; #region step 1 //step 1: combine all eqs to one system //var filledCols = new bool[6 * n]; var extraEqCount = 0; foreach (var mpcElm in target.MpcElements) { if (mpcElm.AppliesForLoadCase(loadCase)) { extraEqCount += mpcElm.GetExtraEquationsCount(); } } extraEqCount += boundaryConditions.RowCount; var allEqsCrd = new CoordinateStorage <double>(extraEqCount, n * 6 + 1, 1);//rows: extra eqs, cols: 6*n+1 (+1 is for right hand side) foreach (var mpcElm in target.MpcElements) { if (mpcElm.AppliesForLoadCase(loadCase)) { var extras = mpcElm.GetExtraEquations(); extras.EnumerateMembers((row, col, val) => { allEqsCrd.At(row + lastRow, col, val); }); lastRow += extras.RowCount; } } { boundaryConditions.EnumerateMembers((row, col, val) => { allEqsCrd.At(row + lastRow, col, val); }); lastRow += boundaryConditions.RowCount; } var allEqs = allEqsCrd.ToCCs(); #endregion #region comment /* #region step 2 * //step 2: create adjacency matrix of variables * * //step 2-1: find nonzero pattern * var allEqsNonzeroPattern = allEqs.Clone(); * * for (var i = 0; i < allEqsNonzeroPattern.Values.Length; i++) * allEqsNonzeroPattern.Values[i] = 1; * * //https://math.stackexchange.com/questions/2340450/extract-independent-sub-systems-from-a-bigger-linear-eq-system * var tmp = allEqsNonzeroPattern.Transpose(); * * var variableAdj = tmp.Multiply(allEqsNonzeroPattern); #endregion * #region step 3 * //extract parts * var parts = EnumerateGraphParts(variableAdj); * #endregion * #region step 4 * { * * allEqs.EnumerateColumns((colNum, vals) => * { * if (vals.Count == 0) * Console.WriteLine("Col {0} have {1} nonzeros", colNum, vals.Count); * }); * * var order = ColumnOrdering.MinimumDegreeAtPlusA; * * // Partial pivoting tolerance (0.0 to 1.0) * double tolerance = 1.0; * * var lu = CSparse.Double.Factorization.SparseLU.Create(allEqs, order, tolerance); * * } * #endregion */ #endregion rrefFinder.CalculateRref(allEqs); var q = AMD.Generate(allEqs, ColumnOrdering.MinimumDegreeAtA); var s = new SymbolicFactorization() { q = q }; var qr = CSparse.Double.Factorization.SparseQR.Create(allEqs, ColumnOrdering.MinimumDegreeAtA); var r = ((CCS)ReflectionUtils.GetFactorR(qr, "R")); //var q = ((CCS)ReflectionUtils.GetFactorR(qr, "Q")); //var s = ((SymbolicFactorization)ReflectionUtils.GetFactorR(qr, "S")); var idependents = new bool[allEqs.RowCount]; var rd = allEqs.ToDenseMatrix(); r.EnumerateMembers((row, col, val) => { if (row == col) { if (Math.Abs(val) < 1e-6) { return; } } idependents[row] = true; } ); //var t=qr. throw new NotImplementedException(); //return buf.ToCCs(); }