private List <List <int> > GetDistinctRigidElements(Model model, LoadCase loadCase) { for (int i = 0; i < model.Nodes.Count; i++) { model.Nodes[i].Index = i; } var n = model.Nodes.Count; var crd = new CoordinateStorage <double>(n, n, 1); foreach (var elm in model.RigidElements) { if (IsAppliableRigidElement(elm, loadCase)) { for (var i = 0; i < elm.Nodes.Count; i++) { crd.At(elm.Nodes[i].Index, elm.Nodes[i].Index, 1.0); } for (var i = 0; i < elm.Nodes.Count - 1; i++) { crd.At(elm.Nodes[i].Index, elm.Nodes[i + 1].Index, 1.0); crd.At(elm.Nodes[i + 1].Index, elm.Nodes[i].Index, 1.0); } } } var graph = Converter.ToCompressedColumnStorage(crd); var buf = CalcUtil.EnumerateGraphParts(graph); 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 double[] GetAngleWithAxises(Vector vec) { var buf = new List <double>(); buf.Add(CalcUtil.RadToDeg(Math.Acos(vec.X / vec.Length))); buf.Add(CalcUtil.RadToDeg(Math.Acos(vec.Y / vec.Length))); buf.Add(CalcUtil.RadToDeg(Math.Acos(vec.Z / vec.Length))); return(buf.ToArray()); }
/// <summary> /// Solves the instance with specified <see cref="solverType" /> and assuming linear behavior (both geometric and material) and for default load case. /// </summary> /// <param name="solverType">The solver type.</param> public void Solve(BuiltInSolverType solverType) { var gen = new Func <CompressedColumnStorage, ISolver>(i => { var sl = CalcUtil.CreateBuiltInSolver(solverType); sl.A = i; return(sl); }); Solve(gen); }
public void Solve_MPC(params LoadCase[] cases) { var fact = CalcUtil.CreateBuiltInSolverFactory(BuiltInSolverType.CholeskyDecomposition); var cfg = new SolverConfiguration(); cfg.SolverFactory = fact; cfg.LoadCases.AddRange(cases); Solve_MPC(cfg); }
/// <summary> /// Solves the instance assuming linear behavior (both geometric and material) for specified cases. /// </summary> /// <param name="cases">The cases.</param> public void Solve(params LoadCase[] cases) { var cfg = new SolverConfiguration(); cfg.SolverGenerator = i => { var sl = CalcUtil.CreateBuiltInSolver(BuiltInSolverType.CholeskyDecomposition); sl.A = i; return(sl); }; cfg.LoadCases = new List <LoadCase>(cases); Solve(cfg); }
public void Solve_MPC() { var fact = CalcUtil.CreateBuiltInSolverFactory(BuiltInSolverType.CholeskyDecomposition); var cfg = new SolverConfiguration(); cfg.SolverFactory = fact; cfg.LoadCases = new List <LoadCase>() { LoadCase.DefaultLoadCase }; Solve_MPC(cfg); }
public Force[] GetGlobalEquivalentNodalLoads(Element element) { if (element is FrameElement2Node) { var frElm = element as FrameElement2Node; var l = (frElm.EndNode.Location - frElm.StartNode.Location).Length; var w = GetLocalDistributedLoad(element as Element1D); var localEndForces = new Force[2]; localEndForces[0] = new Force(w.X * l / 2, w.Y * l / 2, w.Z * l / 2, 0, -w.Z * l * l / 12.0, w.Y * l * l / 12.0); localEndForces[1] = new Force(w.X * l / 2, w.Y * l / 2, w.Z * l / 2, 0, w.Z * l * l / 12.0, -w.Y * l * l / 12.0); localEndForces = CalcUtil.ApplyReleaseMatrixToEndForces(frElm, localEndForces);//applying release matrix to end forces for (var i = 0; i < element.Nodes.Length; i++) { var frc = localEndForces[i]; localEndForces[i] = new Force( frElm.TransformLocalToGlobal(frc.Forces), frElm.TransformLocalToGlobal(frc.Moments)); } return(localEndForces); } return(element.GetGlobalEquivalentNodalLoads(this)); }
private static List <List <int> > GetDistinctRigidElements(Model model, LoadCase loadCase) { for (int i = 0; i < model.Nodes.Count; i++) { model.Nodes[i].Index = i; } var n = model.Nodes.Count; var ecrd = new CoordinateStorage <double>(n, n, 1); //for storing existence of rigid elements var crd = new CoordinateStorage <double>(n, n, 1); //for storing hinged connection of rigid elements for (int ii = 0; ii < model.RigidElements.Count; ii++) { var elm = model.RigidElements[ii]; if (IsAppliableRigidElement(elm, loadCase)) { for (var i = 0; i < elm.Nodes.Count; i++) { ecrd.At(elm.Nodes[i].Index, elm.Nodes[i].Index, 1.0); } for (var i = 0; i < elm.Nodes.Count - 1; i++) { ecrd.At(elm.Nodes[i].Index, elm.Nodes[i + 1].Index, 1.0); ecrd.At(elm.Nodes[i + 1].Index, elm.Nodes[i].Index, 1.0); } } } var graph = Converter.ToCompressedColumnStorage(ecrd); var buf = CalcUtil.EnumerateGraphParts(graph); return(buf); }
/// <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_MPC(LoadCase loadCase) { var n = parent.Nodes.Count * 6; var dt = new double[n];//total delta ISolver solver; var perm = CalcUtil.GenerateP_Delta_Mpc(parent, loadCase, new Mathh.GaussRrefFinder()); var np = perm.Item1.ColumnCount;//master count var rd = perm.Item2; var pd = perm.Item1; var kt = MatrixAssemblerUtil.AssembleFullStiffnessMatrix(parent); var ft = new double[n]; { var fe = elementForces[loadCase] = GetTotalElementsForceVector(loadCase); var fc = concentratedForces[loadCase] = GetTotalConcentratedForceVector(loadCase); ft.AddToSelf(fe); ft.AddToSelf(fc); } if (perm.Item1.RowCount > 0 && perm.Item1.RowCount > 0) { var pf = pd.Transpose(); var kr = pf.Multiply(kt).Multiply(pd); var a1 = new double[n]; //a1.AddToSelf(rd); kt.Multiply(rd, a1); a1.AddToSelf(ft); var a2 = new double[np]; pf.Multiply(a1, a2); var a3 = new double[np]; #region load/generate solver if (Solvers_New.ContainsKey(pd)) { solver = Solvers_New[pd]; } else { solver = SolverFactory.CreateSolver((CCS)kr); Solvers_New[pd] = solver; } if (!solver.IsInitialized) { solver.Initialize(); } #endregion solver.Solve(a2, a3); pd.Multiply(a3, dt); } dt.AddToSelf(rd, -1); kt.Multiply(dt, ft); _forces[loadCase] = ft; _displacements[loadCase] = dt; }
/// <summary> /// Solves the instance with specified <see cref="solverType" /> and assuming linear behavior (both geometric and material) and for default load case. /// </summary> /// <param name="solverType">The solver type.</param> public void Solve(BuiltInSolverType solverType) { Solve(CalcUtil.CreateBuiltInSolverFactory(solverType)); }
/// <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_MPC(LoadCase loadCase) { var n = parent.Nodes.Count * 6; var dt = new double[n];//total delta ISolver solver; var perm = CalcUtil.GenerateP_Delta_Mpc(parent, loadCase, new Mathh.GaussRrefFinder()); var np = perm.Item1.ColumnCount;//master count var rd = perm.Item2; var pd = perm.Item1; var kt = MatrixAssemblerUtil.AssembleFullStiffnessMatrix(parent); var ft = new double[n]; //{ var fe = elementForces[loadCase] = GetTotalElementsForceVector(loadCase); var fc = concentratedForces[loadCase] = GetTotalConcentratedForceVector(loadCase); ft.AddToSelf(fe); ft.AddToSelf(fc); //} if (perm.Item1.RowCount > 0 && perm.Item1.RowCount > 0) { var pf = pd.Transpose(); var kr = pf.Multiply(kt).Multiply(pd); var a1 = new double[n]; //a1.AddToSelf(rd); kt.Multiply(rd, a1); a1.AddToSelf(ft); var a2 = new double[np]; pf.Multiply(a1, a2); var a3 = new double[np]; #region load/generate solver if (Solvers_New.ContainsKey(pd)) { solver = Solvers_New[pd]; } else { solver = SolverFactory.CreateSolver((CCS)kr); Solvers_New[pd] = solver; } if (!solver.IsInitialized) { solver.Initialize(); } #endregion solver.Solve(a2, a3); pd.Multiply(a3, dt); } dt.AddToSelf(rd, -1); ft.FillWith(0); kt.Multiply(dt, ft); var fx = supportReactions[loadCase] = (double[])ft.Clone(); ft.AddToSelf(fe, -1); ft.AddToSelf(fc, -1); _forces[loadCase] = ft; _displacements[loadCase] = dt; //var forcesRegenerated= for (var i = 0; i < parent.Nodes.Count; i++) { #region constraint var virtConsts = new List <Constraint>(); var origConst = parent.Nodes[i].Constraints; virtConsts.Add(origConst); foreach (var element in parent.MpcElements) { if (!(element is VirtualConstraint)) { continue; } if (!element.AppliesForLoadCase(loadCase)) { continue; } if (!element.Nodes.Contains(parent.Nodes[i])) { continue; } virtConsts.Add((element as VirtualConstraint).Constraint); } var finalConst = new Constraint(); foreach (var cns in virtConsts) { if (cns.DX == DofConstraint.Fixed) { finalConst.DX = DofConstraint.Fixed; } if (cns.DY == DofConstraint.Fixed) { finalConst.DY = DofConstraint.Fixed; } if (cns.DZ == DofConstraint.Fixed) { finalConst.DZ = DofConstraint.Fixed; } if (cns.RX == DofConstraint.Fixed) { finalConst.RX = DofConstraint.Fixed; } if (cns.RY == DofConstraint.Fixed) { finalConst.RY = DofConstraint.Fixed; } if (cns.RZ == DofConstraint.Fixed) { finalConst.RZ = DofConstraint.Fixed; } } #endregion if (finalConst.DX == DofConstraint.Released) { fx[6 * i + 0] = 0; } if (finalConst.DY == DofConstraint.Released) { fx[6 * i + 1] = 0; } if (finalConst.DY == DofConstraint.Released) { fx[6 * i + 2] = 0; } if (finalConst.RX == DofConstraint.Released) { fx[6 * i + 3] = 0; } if (finalConst.RY == DofConstraint.Released) { fx[6 * i + 4] = 0; } if (finalConst.RZ == DofConstraint.Released) { fx[6 * i + 5] = 0; } } }
/// <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 override Force[] GetGlobalEquivalentNodalLoads(Element element) { if (element is FrameElement2Node) { var e = element as FrameElement2Node; var localForce = this.force; if (this.coordinationSystem == CoordinationSystem.Global) { var tmp = e.TransformGlobalToLocal(localForce.Forces, localForce.Moments); localForce.Forces = tmp[0]; localForce.Moments = tmp[1]; } var buf = new Force[2]; buf[0] = new Force(); var l = (e.EndNode.Location - e.StartNode.Location).Length; var a = distanseFromStartNode; var b = l - a; var mymy1 = localForce.My * b / (l * l) * (b - 2 * a); var mymy2 = localForce.My * a / (l * l) * (a - 2 * b); var myfz1 = 6 * localForce.My * a * b / (l * l * l); var myfz2 = -myfz1; var mzmz1 = localForce.Mz * b / (l * l) * (b - 2 * a); var mzmz2 = localForce.Mz * a / (l * l) * (a - 2 * b); var mzfy1 = -6 * localForce.Mz * a * b / (l * l * l); var mzfy2 = -mzfy1; var fzmy1 = -localForce.Fz * a * b * b / (l * l); var fzmy2 = localForce.Fz * a * a * b / (l * l); var fzfz1 = localForce.Fz * b * b / (l * l * l) * (3 * a + b); var fzfz2 = localForce.Fz * a * a / (l * l * l) * (3 * b + a); var fymz1 = localForce.Fy * a * b * b / (l * l); var fymz2 = -localForce.Fy * a * a * b / (l * l); var fyfy1 = localForce.Fy * b * b / (l * l * l) * (3 * a + b); var fyfy2 = localForce.Fy * a * a / (l * l * l) * (3 * b + a); var fxfx1 = localForce.Fx * b / l; var fxfx2 = localForce.Fx * a / l; var mxmx1 = localForce.Mx * b / l; var mxmx2 = localForce.Mx * a / l; var f1 = new Force( fxfx1, mzfy1 + fyfy1, fzfz1 + myfz1, mxmx1, mymy1 + fzmy1, mzmz1 + fymz1 ); var f2 = new Force( fxfx2, mzfy2 + fyfy2, fzfz2 + myfz2, mxmx2, mymy2 + fzmy2, mzmz2 + fymz2 ); var localEndForces = new Force[2]; localEndForces[0] = f1; localEndForces[1] = f2; localEndForces = CalcUtil.ApplyReleaseMatrixToEndForces(e, localEndForces);//applying release matrix to end forces var vecs = new Vector[] { localEndForces[0].Forces, localEndForces[0].Moments, localEndForces[1].Forces, localEndForces[1].Moments }; var tvecs = e.TransformLocalToGlobal(vecs); buf[0] = new Force(tvecs[0], tvecs[1]); buf[1] = new Force(tvecs[2], tvecs[3]); return(buf); } throw new NotImplementedException(); }
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> /// 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_MPC(LoadCase loadCase) { var n = parent.Nodes.Count * 6; var dt = new double[n];//total delta ISolver solver; var sp = Stopwatch.StartNew(); var permCalculator = new CsparsenetQrDisplacementPermutationCalculator(); var perm = CalcUtil.GenerateP_Delta_Mpc(parent, loadCase, permCalculator); parent.Trace.Write(Common.TraceLevel.Info, "Calculating Displacement Permutation Matrix took {0} ms", sp.ElapsedMilliseconds); var np = perm.Item1.ColumnCount;//master count var rd = perm.Item2; var pd = perm.Item1; //var todo = pd.ToDenseMatrix(); sp.Restart(); var kt = MatrixAssemblerUtil.AssembleFullStiffnessMatrix(parent);//total stiffness matrix, same for all load cases parent.Trace.Write(Common.TraceLevel.Info, "Assemble Full Stiffness Matrix took {0} ms", sp.ElapsedMilliseconds); var ft = new double[n]; //{ var fe = elementForces[loadCase] = GetTotalElementsForceVector(loadCase); var fc = concentratedForces[loadCase] = GetTotalConcentratedForceVector(loadCase); ft.AddToSelf(fe); ft.AddToSelf(fc); //} if (perm.Item1.RowCount > 0 && perm.Item1.RowCount > 0) { var pf = pd.Transpose(); sp.Restart(); var kr = pf.Multiply(kt).Multiply(pd); var a1 = new double[n]; kt.Multiply(rd, a1); a1.AddToSelf(ft); var a2 = new double[np]; pf.Multiply(a1, a2); parent.Trace.Write(Common.TraceLevel.Info, "Applying boundary conditions took {0} ms", sp.ElapsedMilliseconds); var a3 = new double[np]; #region load/generate solver if (Solvers_New.ContainsKey(pd)) { solver = Solvers_New[pd]; } else { //var tt = kr.ToDenseMatrix(); solver = SolverFactory.CreateSolver((CCS)kr); Solvers_New[pd] = solver; } sp.Restart(); if (!solver.IsInitialized) { solver.Initialize(); } #endregion solver.Solve(a2, a3); parent.Trace.Write(Common.TraceLevel.Info, "Solving EQ system took {0} ms", sp.ElapsedMilliseconds); pd.Multiply(a3, dt); } dt.AddToSelf(rd, -1); ft.FillWith(0); kt.Multiply(dt, ft); var fx = supportReactions[loadCase] = (double[])ft.Clone(); ft.AddToSelf(fe, -1); ft.AddToSelf(fc, -1); _forces[loadCase] = ft; _displacements[loadCase] = dt; for (var i = 0; i < parent.Nodes.Count; i++) { #region constraint var virtConsts = new List <Constraint>(); var origConst = parent.Nodes[i].Constraints; virtConsts.Add(origConst); foreach (var element in parent.MpcElements) { if (!(element is VirtualConstraint)) { continue; } if (!element.AppliesForLoadCase(loadCase)) { continue; } if (!element.Nodes.Contains(parent.Nodes[i])) { continue; } virtConsts.Add((element as VirtualConstraint).Constraint); } var finalConst = new Constraint(); foreach (var cns in virtConsts) { if (cns.DX == DofConstraint.Fixed) { finalConst.DX = DofConstraint.Fixed; } if (cns.DY == DofConstraint.Fixed) { finalConst.DY = DofConstraint.Fixed; } if (cns.DZ == DofConstraint.Fixed) { finalConst.DZ = DofConstraint.Fixed; } if (cns.RX == DofConstraint.Fixed) { finalConst.RX = DofConstraint.Fixed; } if (cns.RY == DofConstraint.Fixed) { finalConst.RY = DofConstraint.Fixed; } if (cns.RZ == DofConstraint.Fixed) { finalConst.RZ = DofConstraint.Fixed; } } #endregion if (finalConst.DX == DofConstraint.Released) { fx[6 * i + 0] = 0; } if (finalConst.DY == DofConstraint.Released) { fx[6 * i + 1] = 0; } if (finalConst.DY == DofConstraint.Released) { fx[6 * i + 2] = 0; } if (finalConst.RX == DofConstraint.Released) { fx[6 * i + 3] = 0; } if (finalConst.RY == DofConstraint.Released) { fx[6 * i + 4] = 0; } if (finalConst.RZ == DofConstraint.Released) { fx[6 * i + 5] = 0; } } }