public double ComputeStress(List <double> elemDisplacements) { LinearAlgebra.Vector <double> elemDispVector = LinearAlgebra.Vector <double> .Build.Dense(elemDisplacements.ToArray()); double N = StiffnessModulus * Area / ElemLength * LinearAlgebra.Vector <double> .Build.Dense(new double[] { -1, 1 }).DotProduct(G.Multiply(elemDispVector)); return(N / Area); }
public LinearAlgebra.Vector <double> solveEquations(LinearAlgebra.Matrix <double> stiffnessMatrix, LinearAlgebra.Vector <double> forceVector, List <int> boundaryDofs, List <double> boundaryConstraints) { int nDof = forceVector.Count; // Find all dofs where force is known List <int> allDofs = Enumerable.Range(0, nDof).ToList(); List <int> unknownDofs = allDofs.Except(boundaryDofs).ToList(); // Add the know displacements to the result LinearAlgebra.Vector <double> displacementVector = LinearAlgebra.Vector <double> .Build.Dense(nDof); for (int i = 0; i < boundaryDofs.Count; i++) { displacementVector[boundaryDofs[i]] = boundaryConstraints[i]; } // Pick out part of matrix corresponding to known forces int nrUnknownDofs = unknownDofs.Count; LinearAlgebra.Matrix <double> unknownK = LinearAlgebra.Matrix <double> .Build.Dense(nrUnknownDofs, nrUnknownDofs); LinearAlgebra.Vector <double> knownForces = LinearAlgebra.Vector <double> .Build.Dense(unknownDofs.Count); for (int i = 0; i < unknownDofs.Count; i++) { for (int j = 0; j < unknownDofs.Count; j++) { unknownK[i, j] = stiffnessMatrix[unknownDofs[i], unknownDofs[j]]; } knownForces[i] = forceVector[unknownDofs[i]]; } LinearAlgebra.Matrix <double> unkownKnownK = LinearAlgebra.Matrix <double> .Build.Dense(nrUnknownDofs, boundaryDofs.Count); for (int i = 0; i < unknownDofs.Count; i++) { for (int j = 0; j < boundaryDofs.Count; j++) { unkownKnownK[i, j] = stiffnessMatrix[unknownDofs[i], boundaryDofs[j]]; } knownForces[i] = forceVector[unknownDofs[i]]; } // Solve for the unknown displacements LinearAlgebra.Vector <double> unknownDisplacements = unknownK.Inverse().Multiply(knownForces.Subtract(unkownKnownK.Multiply(LinearAlgebra.Vector <double> .Build.Dense(boundaryConstraints.ToArray())))); // Insert the calculated displacements for (int i = 0; i < unknownDofs.Count; i++) { displacementVector[unknownDofs[i]] = unknownDisplacements[i]; } return(displacementVector); }
/// <summary> /// 回傳數列中最明顯的 Change Point。 /// </summary> /// <param name="d">The numeric array which use to run change point procedure. Missing value (1.23456E+30) element is not allow in the array.</param> /// <param name="conf">The confidence level used to test whether it is a significant change point</param> /// <param name="N">Number of boostrap</param> /// <returns></returns> public static ChangePointInfo ChangePointOnSingleCase(double[] d, double conf = 0.9, int N = 1000) { if (d.Length < 7) { return new ChangePointInfo() { Index = -1 } } ; if (d.Any(x => x >= MtbTools.MISSINGVALUE)) { throw new ArgumentException("數列中包含遺失值"); } LinearAlgebra.Vector <double> xs = LinearAlgebra.Vector <double> .Build.DenseOfArray(d); double xbar = xs.Average(); xs = xs - xbar; //Xi-Xbar LinearAlgebra.Vector <double> si = LinearAlgebra.Vector <double> .Build.DenseOfArray(MathTool.PartialSum(xs.ToArray())); int changepointindex = si.AbsoluteMaximumIndex(); double sdiff = si.Maximum() - si.Minimum(); double[] Sdiff_boostrap = new double[N]; for (int i = 0; i < N; i++) { double[] si_boostrap = MathTool.PartialSum(MathTool.RandomSample(xs.ToArray()).Cast <double>().ToArray()); Sdiff_boostrap[i] = si_boostrap.Max() - si_boostrap.Min(); } double confLv = (double)Sdiff_boostrap.Where(x => x < sdiff).Count() / N; if (confLv < conf) { return new ChangePointInfo() { Index = -1 } } ; //Not significant return(new ChangePointInfo() { Index = changepointindex, Sdiff = sdiff, ConfidenceLevel = confLv }); }
/// <summary> /// 計算數列各元素的累積和 /// </summary> /// <param name="x">要處理的陣列,合法的輸入是 double[]</param> /// <returns></returns> public static double[] PartialSum(double[] x) { LinearAlgebra.Vector <double> vx = LinearAlgebra.Double.DenseVector.OfArray(x); int row = vx.Count; int col = row; LinearAlgebra.Matrix <double> lmat = LinearAlgebra.Matrix <double> .Build.Dense(row, col, 1); lmat = lmat.LowerTriangle(); LinearAlgebra.Vector <double> result = lmat.Multiply(vx); return(result.ToArray()); }
protected override void SolveInstance(IGH_DataAccess DA) { // Retrive data from component List <double> A = new List <double>(); List <double> E = new List <double>(); List <Line> lines = new List <Line>(); List <ContstraintNode> rNodes = new List <ContstraintNode>(); List <LoadNode> loadNodes = new List <LoadNode>(); double scaleFactor = 1.0; DA.GetDataList("Line", lines); DA.GetDataList("Area", A); DA.GetDataList("Youngs Modulus", E); DA.GetDataList("Restraint Nodes", rNodes); DA.GetDataList("Load Nodes", loadNodes); DA.GetData("Scale Factor", ref scaleFactor); // The length of A and E must be the same as lines if ((A.Count != E.Count) | (E.Count != lines.Count)) { throw new ArgumentException("Length of A and E must equal length of Line"); } // Create one list to store the nodes and one list to store the bars List <Node> trussNodes = new List <Node>(); List <Bar> trussBars = new List <Bar>(); // Topology matrix to keep track of element dofs List <List <int> > eDof = new List <List <int> >(); // Loop trough each line and create nodes at end points for (int i = 0; i < lines.Count; i++) { Node node1 = new Node(lines[i].From); Node node2 = new Node(lines[i].To); // To keep track if the node is unique bool unique1 = true; bool unique2 = true; // Check if node is unique, if so give it an ID and degress of freedom foreach (Node existingNode in trussNodes) { // If not unique use an already identified node if (node1 == existingNode) { node1 = existingNode; unique1 = false; } if (node2 == existingNode) { node2 = existingNode; unique2 = false; } } // If unique give it an ID if (unique1) { int id_node_1 = trussNodes.Count; node1.ID = id_node_1; node1.Dofs = System.Linq.Enumerable.Range(id_node_1 * 3, 3).ToList(); // Check if any boundary node or load node exist at current node foreach (ContstraintNode rNode in rNodes) { if (rNode == node1) { // Add restraint data node1.ConstraintX = rNode.ConstraintX; node1.ConstraintY = rNode.ConstraintY; node1.ConstraintZ = rNode.ConstraintZ; } } foreach (LoadNode loadNode in loadNodes) { if (loadNode == node1) { // Add force data node1.ForceX = loadNode.ForceX; node1.ForceY = loadNode.ForceY; node1.ForceZ = loadNode.ForceZ; } } // Finally add the node trussNodes.Add(node1); } if (unique2) { int id_node_2 = trussNodes.Count; node2.ID = id_node_2; node2.Dofs = System.Linq.Enumerable.Range(id_node_2 * 3, 3).ToList(); // Check if any boundary node or load node exist at current node foreach (ContstraintNode rNode in rNodes) { if (rNode == node2) { // Add constraint data node2.ConstraintX = rNode.ConstraintX; node2.ConstraintY = rNode.ConstraintY; node2.ConstraintZ = rNode.ConstraintZ; } } foreach (LoadNode loadNode in loadNodes) { if (loadNode == node2) { // Add force data node2.ForceX = loadNode.ForceX; node2.ForceY = loadNode.ForceY; node2.ForceZ = loadNode.ForceZ; } } // Finally add the node trussNodes.Add(node2); } // Create a bar object between the nodes Bar bar = new Bar(node1, node2, A[i], E[i]); trussBars.Add(bar); // Topology matrix List <int> dofs1 = bar.Nodes[0].Dofs; List <int> dofs2 = bar.Nodes[1].Dofs; List <int> eDofRow = new List <int>(); eDofRow.AddRange(dofs1); eDofRow.AddRange(dofs2); eDof.Add(eDofRow); } int nDof = trussNodes.Count * 3; int nElem = eDof.Count; // Loop trough each node and construct a load vector and boundary vector LinearAlgebra.Vector <double> forceVector = LinearAlgebra.Vector <double> .Build.Dense(nDof); List <int> boundaryDofs = new List <int>(); List <double?> boundaryConstraints = new List <double?>(); for (int i = 0; i < trussNodes.Count; i++) { // Load vector forceVector[i * 3] = trussNodes[i].ForceX; forceVector[i * 3 + 1] = trussNodes[i].ForceY; forceVector[i * 3 + 2] = trussNodes[i].ForceZ; // Boundary vector for (int j = 0; j < 3; j++) { if (j == 0 && trussNodes[i].ConstraintX != null) { boundaryDofs.Add(trussNodes[i].Dofs[j]); boundaryConstraints.Add(trussNodes[i].ConstraintX); } else if (j == 1 && trussNodes[i].ConstraintY != null) { boundaryDofs.Add(trussNodes[i].Dofs[j]); boundaryConstraints.Add(trussNodes[i].ConstraintY); } else if (j == 2 && trussNodes[i].ConstraintZ != null) { boundaryDofs.Add(trussNodes[i].Dofs[j]); boundaryConstraints.Add(trussNodes[i].ConstraintZ); } } } // Loop trough each element, compute local stiffness matrix and assemble into global stiffness matrix LinearAlgebra.Matrix <double> K = LinearAlgebra.Matrix <double> .Build.Dense(nDof, nDof); for (int i = 0; i < trussBars.Count; i++) { LinearAlgebra.Matrix <double> KElem = trussBars[i].ComputeStiffnessMatrix(); // Assemble for (int k = 0; k < 6; k++) { for (int l = 0; l < 6; l++) { K[eDof[i][k], eDof[i][l]] = K[eDof[i][k], eDof[i][l]] + KElem[k, l]; } } } // Calculate the displacements Solver solver = new Solver(); LinearAlgebra.Vector <double> displacements = solver.solveEquations(K, forceVector, boundaryDofs, boundaryConstraints.Cast <double>().ToList()); // Save the displacement for each node and calculate the stress in each bar List <double> elemStress = new List <double> { }; for (int i = 0; i < nElem; i++) { double disp1 = displacements[eDof[i][0]]; double disp2 = displacements[eDof[i][1]]; double disp3 = displacements[eDof[i][2]]; double disp4 = displacements[eDof[i][3]]; double disp5 = displacements[eDof[i][4]]; double disp6 = displacements[eDof[i][5]]; Point3d newPoint1 = new Point3d(disp1 * scaleFactor, disp2 * scaleFactor, disp3 * scaleFactor); Point3d newPoint2 = new Point3d(disp4 * scaleFactor, disp5 * scaleFactor, disp6 * scaleFactor); // Translate original points trussBars[i].Nodes[0].Point = trussBars[i].Nodes[0].Point + newPoint1; trussBars[i].Nodes[1].Point = trussBars[i].Nodes[1].Point + newPoint2; // Calculate element stress elemStress.Add(trussBars[i].ComputeStress(new List <double> { disp1, disp2, disp3, disp4, disp5, disp6 })); } // Return the deformed lines List <Line> deformedLines = new List <Line>(); foreach (Bar bar in trussBars) { deformedLines.Add(new Line(bar.Nodes[0].Point, bar.Nodes[1].Point)); } DA.SetDataList("Deformed Truss", deformedLines); DA.SetDataList("Element Stress", elemStress); }