/// <summary> /// Gets the total displacement vector for whole structure for specified <see cref="cse"/> /// </summary> /// <param name="cse">The cse.</param> /// <param name="map">The map.</param> /// <remarks> /// This is not used for finding unknown displacements (like displacement of free DoFs). /// Just is used for known displacements (like settlements and only for settlement). /// </remarks> /// <returns></returns> private double[] GetTotalDispVector(LoadCase cse, DofMappingManager map) { //displacement vector. free part can be assume zero however didn't touch that var n = parent.Nodes.Count; var buf = new double[6 * n]; if (parent.SettlementLoadCase != cse) { return(buf); } var nodes = parent.Nodes; for (var i = 0; i < n; i++) { var disp = nodes[i].Settlements; buf[6 * i + 0] = disp.DX; buf[6 * i + 1] = disp.DY; buf[6 * i + 2] = disp.DZ; buf[6 * i + 3] = disp.RX; buf[6 * i + 4] = disp.RY; buf[6 * i + 5] = disp.RZ; } return(buf); }
/// <summary> /// Gets the total elements equivalent nodal force vector. /// </summary> /// <param name="cse">The load case.</param> /// <param name="map">The map.</param> /// <returns></returns> private double[] GetTotalElementsForceVector(LoadCase cse, DofMappingManager map) { //force vector for both free and fixed dof var n = parent.Nodes.Count; var loads = new Force[n]; //loads from connected element to node is stored in this array instead of Node.ElementLoads. for (int i = 0; i < n; i++) //re indexing { parent.Nodes[i].Index = i; } #region adding element loads foreach (var elm in parent.Elements) { var nc = elm.Nodes.Length; foreach (var ld in elm.Loads) { if (ld.Case != cse) { continue; } var frcs = ld.GetGlobalEquivalentNodalLoads(elm); for (var i = 0; i < nc; i++) { var nde = elm.Nodes[i]; loads[nde.Index] += frcs[i]; } } } #endregion var buf = new double[6 * n]; for (int i = 0; i < n; i++) { var force = loads[i]; buf[6 * i + 0] = force.Fx; buf[6 * i + 1] = force.Fy; buf[6 * i + 2] = force.Fz; buf[6 * i + 3] = force.Mx; buf[6 * i + 4] = force.My; buf[6 * i + 5] = force.Mz; } return(buf); }
private double[] GetFixedPartOfReducedVector(double[] vr, DofMappingManager map) { var buf = new double[map.RMap3.Length]; for (var i = 0; i < buf.Length; i++) { buf[i] = vr[map.RMap3[i]]; } return(buf); }
public double[] GetFreePartOfReducedVector(double[] vr, DofMappingManager map) { var buf = new double[map.RMap2.Length]; for (var i = 0; i < buf.Length; i++) { buf[i] = vr[map.RMap2[i]]; } return(buf); }
public static CCS GetReducedFreeFreeStiffnessMatrix(this Model model, LoadCase lc) { var fullst = MatrixAssemblerUtil.AssembleFullStiffnessMatrix(model); var mgr = DofMappingManager.Create(model, lc); var dvd = CalcUtil.GetReducedZoneDividedMatrix(fullst, mgr); return(dvd.ReleasedReleasedPart); }
public static CCS GetForcePermute(Model model, DofMappingManager mgr) { var buf = new PermutationGenerator(); buf._target = model; buf.DofMap = mgr; buf._m = mgr.M; buf._n = mgr.N; return(buf.GetForcePermutation()); }
/// <summary> /// Analyses the stiffness matrix for warnings. /// </summary> /// <param name="mtx">The MTX.</param> /// <param name="map">The map.</param> /// <param name="currentCase">The current load case which error is with it.</param> /// <remarks> /// Only searches for zero elements on matrix diagonal /// </remarks> private void AnalyseStiffnessMatrixForWarnings(ZoneDevidedMatrix mtx, DofMappingManager map, LoadCase currentCase) { var cs = mtx.ReleasedReleasedPart; var n = cs.ColumnCount; var t = new bool[n]; //true if i'th diagonal member nonzero, false if diagonal member zero! for (var i = 0; i < n; i++) { var st = cs.ColumnPointers[i]; var en = cs.ColumnPointers[i + 1]; var col = i; for (var j = st; j < en; j++) { var row = cs.RowIndices[j]; //var val = cs.Values[j]; if (row == col) { t[row] = true; } } } for (var i = 0; i < n; i++) { if (t[i]) { continue; } var globalDofNum = map.RMap1[map.RMap2[i]]; var nodeNum = globalDofNum / 6; var dof = (DoF)(globalDofNum % 6); var rec = TraceRecords.GetRecord(30000, parent.Nodes[nodeNum].Label); rec.TargetIdentifier = string.Format( "{0} DoF on node #{1} for load case with [name = '{2}'] and [nature = {3}]", dof, nodeNum, currentCase.CaseName, currentCase.LoadType); parent.Trace.Write(rec); } }
/// <summary> /// Gets the total concentrated forces on loads vector. /// </summary> /// <param name="cse">The load case.</param> /// <param name="map">The map.</param> /// <returns></returns> private double[] GetTotalConcentratedForceVector(LoadCase cse, DofMappingManager map) { //force vector for both free and fixed dof var n = parent.Nodes.Count; var loads = new Force[n]; //loads from connected element to node is stored in this array instead of Node.ElementLoads. for (int i = 0; i < n; i++) //re indexing { parent.Nodes[i].Index = i; } #region adding concentrated nodal loads for (int i = 0; i < n; i++) { foreach (var load in parent.Nodes[i].Loads) { if (load.Case != cse) { continue; } loads[parent.Nodes[i].Index] += load.Force; } } #endregion var buf = new double[6 * n]; for (int i = 0; i < n; i++) { var force = loads[i]; buf[6 * i + 0] = force.Fx; buf[6 * i + 1] = force.Fy; buf[6 * i + 2] = force.Fz; buf[6 * i + 3] = force.Mx; buf[6 * i + 4] = force.My; buf[6 * i + 5] = force.Mz; } return(buf); }
/// <summary> /// Divides the zones of reduced <see cref="matrix"/>. /// </summary> /// <param name="model">The model.</param> /// <param name="matrix">The reduced matrix.</param> /// <param name="dofMap">The DoF map.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public static ZoneDevidedMatrix DivideZones(Model model, CCS matrix, DofMappingManager dofMap) { //see Calcutil.GetReducedZoneDividedMatrix throw new NotImplementedException(); }
/// <summary> /// Adds the analysis result. /// </summary> /// <param name="loadCase">The load case.</param> /// <remarks>if model is analyzed against specific load case, then displacements are available through <see cref="Displacements"/> property. /// If system is not analyses against a specific load case, then this method will analyses structure against <see cref="LoadCase"/>. /// While this method is using pre computed Cholesky Decomposition , its have a high performance in solving the system. /// </remarks> public void AddAnalysisResult(LoadCase loadCase) { ISolver solver; var map = DofMappingManager.Create(parent, loadCase); var n = parent.Nodes.Count; //node count var m = map.M; //master node count var pu = PermutationGenerator.GetDisplacementPermute(parent, map); //permutation of U var pf = PermutationGenerator.GetForcePermute(parent, map); //permutation of F var fe = elementForces[loadCase] = GetTotalElementsForceVector(loadCase); var fc = concentratedForces[loadCase] = GetTotalConcentratedForceVector(loadCase); var ft = fe.Plus(fc); var fr = pf.Multiply(ft); var ffr = GetFreePartOfReducedVector(fr, map); var fsr = GetFixedPartOfReducedVector(fr, map); var kt = MatrixAssemblerUtil.AssembleFullStiffnessMatrix(parent); var kr = (CCS)((CCS)pf.Multiply(kt)).Multiply(pu); #region U_s,r var usr = new double[map.RMap3.Length]; { //should fill usr var ut_temp = GetTotalDispVector(loadCase, map); for (int i = 0; i < usr.Length; i++) { var t1 = map.RMap3[i]; var t2 = map.RMap1[t1]; usr[i] = ut_temp[t2]; } } #endregion var krd = CalcUtil.GetReducedZoneDividedMatrix(kr, map); AnalyseStiffnessMatrixForWarnings(krd, map, loadCase); {//TODO: remove var minAbsDiag = double.MaxValue; foreach (var tpl in krd.ReleasedReleasedPart.EnumerateIndexed2()) { if (tpl.Item1 == tpl.Item2) { minAbsDiag = Math.Min(minAbsDiag, Math.Abs(tpl.Item3)); } } if (krd.ReleasedReleasedPart.RowCount != 0) { //var kk = krd.ReleasedReleasedPart.ToDenseMatrix(); } } #region solver if (Solvers.ContainsKey(map.MasterMap)) { solver = Solvers[map.MasterMap]; } else { solver = //SolverGenerator(krd.ReleasedReleasedPart); SolverFactory.CreateSolver(krd.ReleasedReleasedPart); Solvers[map.MasterMap] = solver; } if (!solver.IsInitialized) { solver.Initialize(); } #endregion double[] ufr = new double[map.RMap2.Length]; string message; var input = ffr.Minus(krd.ReleasedFixedPart.Multiply(usr)); solver.Solve(input, ufr); //if (res2 != SolverResult.Success) // throw new BriefFiniteElementNetException(message); var fpsr = krd.FixedReleasedPart.Multiply(ufr).Plus(krd.FixedFixedPart.Multiply(usr)); var fsrt = fpsr.Minus(fsr);// no needed var fx = supportReactions[loadCase] = new double[6 * n]; #region forming ft for (var i = 0; i < map.Fixity.Length; i++) { if (map.Fixity[i] == DofConstraint.Fixed) { ft[i] = 0; } } for (var i = 0; i < fpsr.Length; i++) { var totDofNum = map.RMap1[map.RMap3[i]]; ft[totDofNum] = fx[totDofNum] = fpsr[i]; } #endregion #region forming ur var ur = new double[map.M * 6]; for (var i = 0; i < usr.Length; i++) { ur[map.RMap3[i]] = usr[i]; } for (var i = 0; i < ufr.Length; i++) { ur[map.RMap2[i]] = ufr[i]; } #endregion var ut = pu.Multiply(ur); _forces[loadCase] = ft; _displacements[loadCase] = ut; }
private void AddAnalysisResult2(LoadCase loadCase) { ISolver solver; var map = DofMappingManager.Create(parent, loadCase); var n = parent.Nodes.Count; //node count var m = map.M; //master node count var dispPermute = PermutationGenerator.GetDisplacementPermute(parent, map); var forcePermute = PermutationGenerator.GetForcePermute(parent, map); var ft = GetTotalForceVector(loadCase, map); var ut = GetTotalDispVector(loadCase, map); var kt = MatrixAssemblerUtil.AssembleFullStiffnessMatrix(parent); for (var i = 0; i < map.Fixity.Length; i++) { if (map.Fixity[i] == DofConstraint.Fixed) { ft[i] = 0; } else { ut[i] = 0; } } var kr = (CCS)((CCS)forcePermute.Multiply(kt)).Multiply(dispPermute); var fr = forcePermute.Multiply(ft); var ur = new double[fr.Length]; for (var i = 0; i < 6 * m; i++) { ur[i] = ut[map.RMap1[i]]; } var krd = CalcUtil.GetReducedZoneDividedMatrix(kr, map); AnalyseStiffnessMatrixForWarnings(krd, map, loadCase); var ff_r = GetFreePartOfReducedVector(fr, map); var us_r = GetFixedPartOfReducedVector(ur, map); if (Solvers.ContainsKey(map.MasterMap)) { solver = Solvers[map.MasterMap]; } else { solver = //SolverGenerator(krd.ReleasedReleasedPart); SolverFactory.CreateSolver(krd.ReleasedReleasedPart); Solvers[map.MasterMap] = solver; } if (!solver.IsInitialized) { solver.Initialize(); } #region ff - kfs * us //درسته، تغییرش نده گوس... var ff_r_negative = ff_r.Clone(); for (var i = 0; i < ff_r.Length; i++) { ff_r[i] = -ff_r[i]; } krd.ReleasedFixedPart.Multiply(us_r, ff_r); for (var i = 0; i < ff_r.Length; i++) { ff_r[i] = -ff_r[i]; } #endregion var urf = new double[map.RMap2.Length]; //string msg; //var res = solver.Solve(ff_r, urf); //if (res != SolverResult.Success) // throw new BriefFiniteElementNetException(msg); var frs = CalcUtil.Add(krd.FixedReleasedPart.Multiply(urf), krd.FixedFixedPart.Multiply(us_r)); for (var i = 0; i < urf.Length; i++) { ur[map.RMap2[i]] = urf[i]; } for (var i = 0; i < frs.Length; i++) { fr[map.RMap3[i]] = frs[i]; } for (var i = 0; i < map.RMap3.Length; i++) { var ind = i; var gi = map.RMap1[map.RMap3[ind]]; ft[gi] = frs[ind]; } var ut2 = dispPermute.Multiply(ur); for (int i = 0; i < 6 * n; i++) { if (map.Fixity[i] == DofConstraint.Fixed) { ut2[i] = ut[i]; } } _forces[loadCase] = ft; _displacements[loadCase] = ut2; }
public static DofMappingManager Create(Model model, LoadCase cse) { var n = model.Nodes.Count; var m = 0; for (var i = 0; i < n; i++) { model.Nodes[i].Index = i; } var masters = CalcUtil.GetMasterMapping(model, cse); for (var i = 0; i < n; i++) { if (masters[i] == i) { m++; } } var cnt = 0; var fixity = new DofConstraint[6 * n]; #region Map4 and rMap4 var map4 = new int[n]; var rMap4 = new int[m]; map4.FillNegative(); rMap4.FillNegative(); for (var i = 0; i < n; i++) { if (masters[i] == i) { map4[i] = cnt; rMap4[cnt] = i; cnt++; } } #endregion #region Map1 and rMap1 var map1 = new int[6 * n]; var rMap1 = new int[6 * m]; map1.FillNegative(); rMap1.FillNegative(); cnt = 0; for (var i = 0; i < m; i++) { var ir = i; var it = rMap4[i]; for (var j = 0; j < 6; j++) { map1[it * 6 + j] = ir * 6 + j; rMap1[ir * 6 + j] = it * 6 + j; } } #endregion #region map2,map3,rmap2,rmap3 var mf = 0;//fixes var mr = 0; for (var i = 0; i < n; i++) { if (masters[i] != i) { continue; } var ctx = model.Nodes[i].Constraints; var s = ctx.Sum(); mf += s; } mr = 6 * m - mf; var rMap2 = new int[mr]; var rMap3 = new int[mf]; var map2 = new int[6 * m]; var map3 = new int[6 * m]; rMap2.FillNegative(); rMap3.FillNegative(); map2.FillNegative(); map3.FillNegative(); var rcnt = 0; var fcnt = 0; for (var i = 0; i < m; i++) { var arr = model.Nodes[rMap4[i]].Constraints.ToArray(); for (var j = 0; j < 6; j++) { if (arr[j] == DofConstraint.Released) { map2[6 * i + j] = rcnt; rMap2[rcnt] = 6 * i + j; rcnt++; } else { map3[6 * i + j] = fcnt; rMap3[fcnt] = 6 * i + j; fcnt++; } } } for (var i = 0; i < n; i++) { var ctx = model.Nodes[i].Constraints.ToArray(); for (var j = 0; j < 6; j++) { fixity[6 * i + j] = ctx[j]; } } #endregion #region RMaster var rMaster = new int[n]; rMaster.FillNegative(); cnt = 0; for (var i = 0; i < masters.Length; i++) { if (masters[i] == i) { rMaster[i] = cnt++; } } #endregion var buf = new DofMappingManager(); buf.Map1 = map1; buf.RMap1 = rMap1; buf.Map2 = map2; buf.RMap2 = rMap2; buf.Map3 = map3; buf.RMap3 = rMap3; buf.Map4 = map4; buf.RMap4 = rMap4; buf.Fixity = fixity; buf.M = m; buf.N = n; buf.MasterMap = masters; buf.RMasterMap = rMaster; return(buf); }
/// <summary> /// Gets the reduced zone divided matrix. /// </summary> /// <param name="reducedMatrix">The reduced matrix.</param> /// <param name="map">The map.</param> /// <returns></returns> public static ZoneDevidedMatrix GetReducedZoneDividedMatrix(CCS reducedMatrix, DofMappingManager map) { var m = map.M; var n = map.N; var r = reducedMatrix; if (r.ColumnCount != r.RowCount || r.RowCount != 6 * m) { throw new InvalidOperationException(); } var ff = new Coord(map.RMap2.Length, map.RMap2.Length); var fs = new Coord(map.RMap2.Length, map.RMap3.Length); var sf = new Coord(map.RMap3.Length, map.RMap2.Length); var ss = new Coord(map.RMap3.Length, map.RMap3.Length); for (var i = 0; i < 6 * m; i++) { var st = r.ColumnPointers[i]; var en = r.ColumnPointers[i + 1]; var col = i; for (var j = st; j < en; j++) { var row = r.RowIndices[j]; var val = r.Values[j]; if (map.Fixity[map.RMap1[row]] == DofConstraint.Released && map.Fixity[map.RMap1[col]] == DofConstraint.Released) { ff.At(map.Map2[row], map.Map2[col], val); } if (map.Fixity[map.RMap1[row]] == DofConstraint.Released && map.Fixity[map.RMap1[col]] != DofConstraint.Released) { fs.At(map.Map2[row], map.Map3[col], val); } if (map.Fixity[map.RMap1[row]] != DofConstraint.Released && map.Fixity[map.RMap1[col]] == DofConstraint.Released) { sf.At(map.Map3[row], map.Map2[col], val); } if (map.Fixity[map.RMap1[row]] != DofConstraint.Released && map.Fixity[map.RMap1[col]] != DofConstraint.Released) { ss.At(map.Map3[row], map.Map3[col], val); } } } var buf = new ZoneDevidedMatrix(); buf.ReleasedReleasedPart = ff.ToCCs(); buf.ReleasedFixedPart = fs.ToCCs(); buf.FixedReleasedPart = sf.ToCCs(); buf.FixedFixedPart = ss.ToCCs(); return(buf); }