public override void ToSharpLoad(GH_Model model) { ForceVector forceVector = null; switch (model.ModelType) { case SharpFE.ModelType.Truss2D: forceVector = model.Model.ForceFactory.CreateForTruss(Force.X, Force.Z); break; case SharpFE.ModelType.Full3D: forceVector = model.Model.ForceFactory.Create(Force.X, Force.Y, Force.Z, Moment.X, Moment.Y, Moment.Z); break; default: throw new Exception("No such model type implemented: " + model.ModelType); } foreach (GH_Node node in Nodes) { node.ToSharpElement(model); FiniteElementNode FEnode = model.Nodes[node.Index]; model.Model.ApplyForceToNode(forceVector, FEnode); } }
public void CalculateModelOfOneSpringWith2DegreesOfFreedom() { FiniteElementModel model = new FiniteElementModel(ModelType.Truss1D); // we will create and analyze a 1D truss system FiniteElementNode node1 = model.NodeFactory.Create(0); // create a node at the origin model.ConstrainNode(node1, DegreeOfFreedom.X); // constrain this node from moving in the X axis FiniteElementNode node2 = model.NodeFactory.Create(1.0); // create a second node at a distance 1 metre along the X axis model.ElementFactory.CreateLinearConstantSpring(node1, node2, 2000.0); // create a spring between the two nodes of a stiffness of 2000 Newtons per metre ForceVector force = model.ForceFactory.Create(10.0); // Create a force of 10 Newtons in the x direction model.ApplyForceToNode(force, node2); // Apply that force to the second node IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); // Create a new instance of the solver class and pass it the model to solve FiniteElementResults results = solver.Solve(); // ask the solver to solve the model and return results DisplacementVector displacement = results.GetDisplacement(node2); // get the displacement at the second node Assert.AreEqual(0.005, displacement.X); // Check that we have calculated a displacement of 0.005 metres (5 millimetres) along the X axis. ReactionVector reaction = results.GetReaction(node1); //get the reaction at the first node Assert.AreEqual(-10, reaction.X); // Check that we have calculated a reaction of -10 Newtons in the X axis. }
public override void ToSharpLoad(GH_Model model) { ForceVector forceVector = null; switch (model.ModelType) { case ModelType.Truss2D: forceVector = model.Model.ForceFactory.CreateForTruss(Force.X, Force.Z); break; case ModelType.Full3D: forceVector = model.Model.ForceFactory.Create(Force.X, Force.Y, Force.Z, Moment.X, Moment.Y, Moment.Z); break; case ModelType.Membrane3D: forceVector = model.Model.ForceFactory.Create(Force.X, Force.Y, Force.Z, 0, 0, 0); break; default: throw new Exception("No such model type implemented: " + model.ModelType); } foreach (Point3d node in Nodes) { IFiniteElementNode FEnode = model.FindOrCreateNode(node); model.Model.ApplyForceToNode(forceVector, FEnode); } }
public void ReversedCantilever() { FiniteElementModel model = new FiniteElementModel(ModelType.Beam1D); FiniteElementNode node1 = model.NodeFactory.Create(0); model.ConstrainNode(node1, DegreeOfFreedom.Z); model.ConstrainNode(node1, DegreeOfFreedom.YY); FiniteElementNode node2 = model.NodeFactory.Create(3.0); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 0); ICrossSection section = new GenericCrossSection(0.0001, 0.0002); model.ElementFactory.CreateLinear1DBeam(node2, node1, material, section); //connecting the nodes in reverse order to the Cantilever() example ForceVector force = model.ForceFactory.CreateFor1DBeam(-10000, 0); model.ApplyForceToNode(force, node2); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); ReactionVector reaction = results.GetReaction(node1); Assert.AreEqual(10000, reaction.Z, 0.001); Assert.AreEqual(-30000, reaction.YY, 0.001); DisplacementVector displacement = results.GetDisplacement(node2); Assert.AreEqual(-0.00214, displacement.Z, 0.0005); Assert.AreEqual(0.00107, displacement.YY, 0.0001); }
public void Cantilever() { FiniteElementModel model = new FiniteElementModel(ModelType.Beam1D); // we will create and analyze a 1D beam system FiniteElementNode node1 = model.NodeFactory.Create(0); // create a node at the origin model.ConstrainNode(node1, DegreeOfFreedom.Z); // constrain the node from moving in the Z-axis model.ConstrainNode(node1, DegreeOfFreedom.YY); // constrain this node from rotating around the Y-axis FiniteElementNode node2 = model.NodeFactory.Create(3.0); // create a second node at a distance 1 metre along the X axis IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 0); ICrossSection section = new GenericCrossSection(0.0001, 0.0002); model.ElementFactory.CreateLinear1DBeam(node1, node2, material, section); ForceVector force = model.ForceFactory.CreateFor1DBeam(-10000, 0); // Create a force of 10 KiloNewtons in the z direction model.ApplyForceToNode(force, node2); // Apply that force to the second node IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); // Create a new instance of the solver class and pass it the model to solve FiniteElementResults results = solver.Solve(); // ask the solver to solve the model and return results ReactionVector reaction = results.GetReaction(node1); //get the reaction at the first node Assert.AreEqual(10000, reaction.Z, 0.001); // Check that we have calculated a reaction of 10 KiloNewtons in the Z-axis Assert.AreEqual(-30000, reaction.YY, 0.001); // Check that we have calculated a reaction of -30 KiloNewtonMetres around the YY axis. DisplacementVector displacement = results.GetDisplacement(node2); // get the displacement at the second node Assert.AreEqual(-0.00214, displacement.Z, 0.0005); Assert.AreEqual(0.00107, displacement.YY, 0.0001); }
private static Dictionary <IFiniteElementNode, ForceVector> AddWindLoad(PixelStructure structure, FiniteElementModel model) { Dictionary <IFiniteElementNode, ForceVector> map = new Dictionary <IFiniteElementNode, ForceVector>(); if (structure.WindLoad != null) { if (structure.WindLoad.Activated) { double forceX = structure.WindLoad.Direction.X; double forceY = structure.WindLoad.Direction.Y; foreach (var i in structure.WindLoad.NodeIndices) { var node = model.Nodes.ElementAt(i); if (!map.ContainsKey(node)) { map.Add(node, new ForceVector(0, 0, 0)); } map[node] = new ForceVector( map[node].X + forceX, 0, map[node].Z + forceY ); } } } return(map); }
public void SpringAt60DegreesInXYPlane() { FiniteElementModel model = new FiniteElementModel(ModelType.Truss2D); // we will create and analyze a 2D truss system FiniteElementNode node1 = model.NodeFactory.CreateFor2DTruss(0, 0); // create a node at the origin model.ConstrainNode(node1, DegreeOfFreedom.X); // constrain this node from moving in the X axis model.ConstrainNode(node1, DegreeOfFreedom.Z); // also constrain it from moving in the Y axis FiniteElementNode node2 = model.NodeFactory.CreateFor2DTruss(1, 1.73205); // create a second node at a distance 1 metre along the X axis and 1.73 metres along the Y axis (giving an angle of 60 degrees from x-axis). model.ConstrainNode(node2, DegreeOfFreedom.X); LinearConstantSpring spring = model.ElementFactory.CreateLinearConstantSpring(node1, node2, 1000); // create a spring between the first two nodes of a stiffness of 1000 Newtons per metre ForceVector force = model.ForceFactory.CreateForTruss(0, 10); // Create a force of with components of 10 Newtons along the y-axis. model.ApplyForceToNode(force, node2); // Apply that force to the second node IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); // Create a new instance of the solver class and pass it the model to solve FiniteElementResults results = solver.Solve(); // ask the solver to solve the model and return results DisplacementVector displacementAtNode2 = results.GetDisplacement(node2); // get the displacement at the second node Assert.AreEqual(0, displacementAtNode2.X); // Check that there is no displacement in the x-axis Assert.AreEqual(0.013333, displacementAtNode2.Z, 0.001); // and 0.01333 metres (13 millimetres) along the Y axis. ReactionVector reactionAtNode1 = results.GetReaction(node1); //get the reaction at the first node Assert.AreEqual(-5.774, reactionAtNode1.X, 0.001); // Check that we have calculated a reaction of 10/SQRT(3) Newtons in the X axis. Assert.AreEqual(-10, reactionAtNode1.Z, 0.001); // and a reaction of -10 Newtons in the Y axis. }
public void SpringInXAxis() { FiniteElementModel model = new FiniteElementModel(ModelType.Truss2D); // we will create and analyze a 1D spring in the vertical FiniteElementNode node1 = model.NodeFactory.CreateFor2DTruss(0, 0); // create a node at the origin model.ConstrainNode(node1, DegreeOfFreedom.X); // constrain this node from moving in the X axis model.ConstrainNode(node1, DegreeOfFreedom.Z); // also constrain it from moving in the Y axis FiniteElementNode node2 = model.NodeFactory.CreateFor2DTruss(1, 0); // create a second node at a distance 1 metre along the X axis. model.ConstrainNode(node2, DegreeOfFreedom.Z); // fix this node from moving along the Y-axis. It is still free to move along the X-axis however. LinearConstantSpring spring = model.ElementFactory.CreateLinearConstantSpring(node1, node2, 1000); // create a spring between the two nodes of a stiffness of 1000 Newtons per metre ForceVector force = model.ForceFactory.CreateForTruss(10, 0); // Create a force of 10 Newtons along the x-axis. model.ApplyForceToNode(force, node2); // Apply that force to the second node IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); // Create a new instance of the solver class and pass it the model to solve FiniteElementResults results = solver.Solve(); // ask the solver to solve the model and return results DisplacementVector displacementAtNode2 = results.GetDisplacement(node2); // get the displacement at the second node Assert.AreEqual(0.01, displacementAtNode2.X); // check that we calculated 0.010 metres (10 millimetres) along the Y axis. ReactionVector reactionAtNode1 = results.GetReaction(node1); //get the reaction at the first node Assert.AreEqual(-10, reactionAtNode1.X); // Check that we have calculated a reaction of -10 Newtons in the X axis. Assert.AreEqual(0, reactionAtNode1.Z); // and a reaction of 0 Newtons in the Y axis. }
public void OneVerticalQuadFixed3PointsMembrane() { FiniteElementModel model = new FiniteElementModel(ModelType.Membrane3D); FiniteElementNode node1 = model.NodeFactory.Create(0.0, 0.0, 0.0); model.ConstrainNode(node1, DegreeOfFreedom.X); model.ConstrainNode(node1, DegreeOfFreedom.Y); model.ConstrainNode(node1, DegreeOfFreedom.Z); FiniteElementNode node2 = model.NodeFactory.Create(1.0, 0.0, 0.0); model.ConstrainNode(node2, DegreeOfFreedom.X); model.ConstrainNode(node2, DegreeOfFreedom.Y); model.ConstrainNode(node2, DegreeOfFreedom.Z); FiniteElementNode node3 = model.NodeFactory.Create(1.0, 0.0, 1.0); model.ConstrainNode(node3, DegreeOfFreedom.X); model.ConstrainNode(node3, DegreeOfFreedom.Y); model.ConstrainNode(node3, DegreeOfFreedom.Z); FiniteElementNode node4 = model.NodeFactory.Create(0.0, 0.0, 1.0); model.ConstrainNode(node4, DegreeOfFreedom.Y); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0.3, 0); model.ElementFactory.CreateLinearConstantStressQuadrilateral(node1, node2, node3, node4, material, 0.1); ForceVector force = model.ForceFactory.Create(10000, 0, 0, 0, 0, 0); model.ApplyForceToNode(force, node4); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); ReactionVector reaction1 = results.GetReaction(node1); Console.WriteLine("\nReaction1 : \n" + reaction1); ReactionVector reaction2 = results.GetReaction(node2); Console.WriteLine("\nReaction2 : \n" + reaction2); ReactionVector reaction3 = results.GetReaction(node3); Console.WriteLine("\nReaction3 : \n" + reaction3); DisplacementVector displacement4 = results.GetDisplacement(node4); Console.WriteLine("\nDisplacement4 : \n" + displacement4); Assert.AreEqual(2621, reaction1.X, 1); Assert.AreEqual(-3039, reaction1.Z, 1); Assert.AreEqual(-5660, reaction2.X, 1); Assert.AreEqual(1706, reaction2.Z, 1); Assert.AreEqual(-6961, reaction3.X, 1); Assert.AreEqual(1333, reaction3.Z, 1); Assert.AreEqual(0.0000012400, displacement4.X, 0.0000000001); Assert.AreEqual(0.0000004875, displacement4.Z, 0.0000000001); }
public void CalculateGridOf3BeamsAnd24Dof() { FiniteElementModel model = new FiniteElementModel(ModelType.Slab2D); FiniteElementNode node1 = model.NodeFactory.Create(4, 4); FiniteElementNode node2 = model.NodeFactory.Create(4, 0); model.ConstrainNode(node2, DegreeOfFreedom.Z); model.ConstrainNode(node2, DegreeOfFreedom.XX); model.ConstrainNode(node2, DegreeOfFreedom.YY); FiniteElementNode node3 = model.NodeFactory.Create(0, 0); model.ConstrainNode(node3, DegreeOfFreedom.Z); model.ConstrainNode(node3, DegreeOfFreedom.XX); model.ConstrainNode(node3, DegreeOfFreedom.YY); FiniteElementNode node4 = model.NodeFactory.Create(0, 4); model.ConstrainNode(node4, DegreeOfFreedom.Z); model.ConstrainNode(node4, DegreeOfFreedom.XX); model.ConstrainNode(node4, DegreeOfFreedom.YY); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 84000000000); ICrossSection section = new GenericCrossSection(0.02, 0.0002, 0.0002, 0.00005); model.ElementFactory.CreateLinear3DBeam(node1, node2, material, section); model.ElementFactory.CreateLinear3DBeam(node1, node3, material, section); model.ElementFactory.CreateLinear3DBeam(node1, node4, material, section); ForceVector force = model.ForceFactory.Create(0, 0, -20000, 0, 0, 0); model.ApplyForceToNode(force, node1); IFiniteElementSolver solver = new LinearSolverSVD(model); FiniteElementResults results = solver.Solve(); DisplacementVector node1Displacement = results.GetDisplacement(node1); ReactionVector node2Reaction = results.GetReaction(node2); ReactionVector node3Reaction = results.GetReaction(node3); ReactionVector node4Reaction = results.GetReaction(node4); Assert.AreEqual(-0.0033, node1Displacement.Z, 0.0001); Assert.AreEqual(-0.0010, node1Displacement.XX, 0.0001); Assert.AreEqual(0.0010, node1Displacement.YY, 0.0001); Assert.AreEqual(10794, node2Reaction.Z, 1); Assert.AreEqual(31776, node2Reaction.XX, 1); Assert.AreEqual(-1019, node2Reaction.YY, 1); Assert.AreEqual(-1587, node3Reaction.Z, 1); Assert.AreEqual(4030, node3Reaction.XX, 1); Assert.AreEqual(-4030, node3Reaction.YY, 1); Assert.AreEqual(10794, node4Reaction.Z, 1); Assert.AreEqual(1019, node4Reaction.XX, 1); Assert.AreEqual(-31776, node4Reaction.YY, 1); }
public void CanCreateAForce() { ForceVector result = SUT.Create(0); Assert.IsNotNull(result); Assert.AreEqual(0, result.X); Assert.AreEqual(0, result.Y); }
public void TwoTriangleWall() { FiniteElementModel model = new FiniteElementModel(ModelType.Membrane3D); // we will create and analyze a 2D slab system FiniteElementNode node1 = model.NodeFactory.Create(0.0, 0.0, 0.0); // create a node at the origin model.ConstrainNode(node1, DegreeOfFreedom.X); // constrain the node from moving in the x-axis model.ConstrainNode(node1, DegreeOfFreedom.Y); // constrain the node from moving in the y-axis model.ConstrainNode(node1, DegreeOfFreedom.Z); // constrain the node from moving in the z-axis FiniteElementNode node2 = model.NodeFactory.Create(1.0, 0.0, 0.0); // create a second node at a distance 1 metre along the X axis model.ConstrainNode(node2, DegreeOfFreedom.X); // constrain the node from moving in the x-axis model.ConstrainNode(node2, DegreeOfFreedom.Y); // constrain the node from moving in the y-axis model.ConstrainNode(node2, DegreeOfFreedom.Z); // constrain the node from moving in the z-axis FiniteElementNode node3 = model.NodeFactory.Create(0.0, 1.0, 0.0); model.ConstrainNode(node3, DegreeOfFreedom.Z); // constrain the node from moving in the z-axis FiniteElementNode node4 = model.NodeFactory.Create(1.0, 1.0, 0.0); model.ConstrainNode(node4, DegreeOfFreedom.Z); // constrain the node from moving in the z-axis IMaterial material = new GenericElasticMaterial(0, 200000, 0.2, 84000); model.ElementFactory.CreateLinearConstantStrainTriangle(node1, node2, node3, material, 0.1); // create a triangle of thickness of 0.1 metres model.ElementFactory.CreateLinearConstantStrainTriangle(node2, node4, node3, material, 0.1); ForceVector force = model.ForceFactory.Create(0, -10); // Create a force of 10 Newtons in the y direction model.ApplyForceToNode(force, node3); // Apply that force to the third node model.ApplyForceToNode(force, node4); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); ReactionVector reaction1 = results.GetReaction(node1); //get the reaction at the first node Console.WriteLine("\nReaction1 : \n" + reaction1); ReactionVector reaction2 = results.GetReaction(node2); Console.WriteLine("\nReaction2 : \n" + reaction2); Assert.AreEqual(20, reaction1.Y + reaction2.Y, 0.001); DisplacementVector displacement3 = results.GetDisplacement(node3); // get the displacement at the second node Console.WriteLine("\nDisplacement3 : \n" + displacement3); Assert.AreNotEqual(0.0, displacement3.X); // TODO calculate the actual value, rather than just checking we have any value Assert.AreNotEqual(0.0, displacement3.Y); // TODO calculate the actual value, rather than just checking we have any value Assert.AreEqual(0.0, displacement3.Z); // TODO calculate the actual value, rather than just checking we have any value DisplacementVector displacement4 = results.GetDisplacement(node4); // get the displacement at the second node Console.WriteLine("\nDisplacement4 : \n" + displacement4); Assert.AreNotEqual(0.0, displacement4.X); // TODO calculate the actual value, rather than just checking we have any value Assert.AreNotEqual(0.0, displacement4.Y); // TODO calculate the actual value, rather than just checking we have any value Assert.AreEqual(0.0, displacement4.Z); // TODO calculate the actual value, rather than just checking we have any value }
public void Calculate2DPortalFrameOf3BeamsAnd12Dof() { FiniteElementModel model = new FiniteElementModel(ModelType.Full3D); FiniteElementNode node1 = model.NodeFactory.Create(-3, 0, 0); model.ConstrainNode(node1, DegreeOfFreedom.X); model.ConstrainNode(node1, DegreeOfFreedom.Y); model.ConstrainNode(node1, DegreeOfFreedom.Z); model.ConstrainNode(node1, DegreeOfFreedom.XX); model.ConstrainNode(node1, DegreeOfFreedom.YY); FiniteElementNode node2 = model.NodeFactory.Create(-3, 0, 6); FiniteElementNode node3 = model.NodeFactory.Create(3, 0, 6); FiniteElementNode node4 = model.NodeFactory.Create(3, 0, 0); model.ConstrainNode(node4, DegreeOfFreedom.X); model.ConstrainNode(node4, DegreeOfFreedom.Y); model.ConstrainNode(node4, DegreeOfFreedom.Z); model.ConstrainNode(node4, DegreeOfFreedom.XX); model.ConstrainNode(node4, DegreeOfFreedom.YY); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 84000000); ICrossSection section = new GenericCrossSection(0.0002, 0.0002, 0.0002, 0.00005); model.ElementFactory.CreateLinear3DBeam(node1, node2, material, section); model.ElementFactory.CreateLinear3DBeam(node2, node3, material, section); model.ElementFactory.CreateLinear3DBeam(node3, node4, material, section); ForceVector force2 = model.ForceFactory.Create(15000, 0, 0, 0, -10000, 0); model.ApplyForceToNode(force2, node2); IFiniteElementSolver solver = new LinearSolverSVD(model); FiniteElementResults results = solver.Solve(); DisplacementVector node2Displacement = results.GetDisplacement(node2); DisplacementVector node3Displacement = results.GetDisplacement(node3); ReactionVector node1Reaction = results.GetReaction(node1); ReactionVector node4Reaction = results.GetReaction(node4); Assert.AreEqual(0.0052843, node2Displacement.X, 0.0001); Assert.AreEqual(0.0006522, node2Displacement.Z, 0.0001); Assert.AreEqual(0.0005, node2Displacement.YY, 0.0001); Assert.AreEqual(0.0044052, node3Displacement.X, 0.0001); Assert.AreEqual(-0.0006522, node3Displacement.Z, 0.0001); Assert.AreEqual(0.0006, node3Displacement.YY, 0.0001); Assert.AreEqual(-9000, node1Reaction.X, 500); Assert.AreEqual(-5000, node1Reaction.Z, 500); Assert.AreEqual(-30022, node1Reaction.YY, 500); Assert.AreEqual(-6000, node4Reaction.X, 500); Assert.AreEqual(5000, node4Reaction.Z, 500); Assert.AreEqual(-22586, node4Reaction.YY, 500); }
public void ThreeNodeSimplySupportedBeam() //TODO verify results using independent check { FiniteElementModel model = new FiniteElementModel(ModelType.Frame2D); FiniteElementNode node1 = model.NodeFactory.CreateFor2DTruss(0, 0); model.ConstrainNode(node1, DegreeOfFreedom.X); model.ConstrainNode(node1, DegreeOfFreedom.Z); FiniteElementNode node2 = model.NodeFactory.CreateFor2DTruss(1, 0); FiniteElementNode node3 = model.NodeFactory.CreateFor2DTruss(2, 0); model.ConstrainNode(node3, DegreeOfFreedom.Z); IMaterial material = new GenericElasticMaterial(0, 10000000000, 0, 0); ICrossSection section = new GenericCrossSection(0.0001, 0.0002); model.ElementFactory.CreateLinear1DBeam(node1, node2, material, section); model.ElementFactory.CreateLinear1DBeam(node2, node3, material, section); ForceVector force = model.ForceFactory.Create(0, 0, -10000, 0, 0, 0); model.ApplyForceToNode(force, node2); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); Stiffness.GlobalModelStiffnessMatrixBuilder gmsmb = new SharpFE.Stiffness.GlobalModelStiffnessMatrixBuilder(model); Console.WriteLine(gmsmb.BuildKnownForcesUnknownDisplacementStiffnessMatrix()); FiniteElementResults results = solver.Solve(); DisplacementVector node1Displacement = results.GetDisplacement(node1); Console.WriteLine("node1Displacement : " + node1Displacement); DisplacementVector node2Displacement = results.GetDisplacement(node2); Console.WriteLine("node2Displacement : " + node2Displacement); DisplacementVector node3Displacement = results.GetDisplacement(node3); Console.WriteLine("node3Displacement : " + node3Displacement); ReactionVector node1Reaction = results.GetReaction(node1); Console.WriteLine("node1Reaction : " + node1Reaction); ReactionVector node3Reaction = results.GetReaction(node3); Console.WriteLine("node5Reaction : " + node3Reaction); Assert.AreEqual(-0.000833333, node2Displacement.Z, 0.0000001); Assert.AreEqual(5000, node1Reaction.Z, 0.001); Assert.AreEqual(5000, node3Reaction.Z, 0.001); Assert.AreEqual(0, node2Displacement.YY, 0.0001); Assert.AreEqual(0.00125, node1Displacement.YY, 0.0000001); Assert.AreEqual(-0.00125, node3Displacement.YY, 0.0000001); }
public void Setup() { SUT = new ForceRepository(); forceFactory = new ForceFactory(ModelType.Truss1D, SUT); exampleForce1 = forceFactory.Create(1); exampleForce2 = forceFactory.Create(2); nodeFactory = new NodeFactory(ModelType.Truss1D); node = nodeFactory.Create(0); }
public void SetUp() { model = null; node1 = null; node2 = null; spring1 = null; force1 = null; SUT = null; }
public void Calculate2DTrussOf3BarsAnd8Dof() { FiniteElementModel model = new FiniteElementModel(ModelType.Truss2D); FiniteElementNode node1 = model.NodeFactory.CreateFor2DTruss(0, 0); FiniteElementNode node2 = model.NodeFactory.CreateFor2DTruss(0, 10); model.ConstrainNode(node2, DegreeOfFreedom.X); model.ConstrainNode(node2, DegreeOfFreedom.Z); FiniteElementNode node3 = model.NodeFactory.CreateFor2DTruss(10, 10); model.ConstrainNode(node3, DegreeOfFreedom.X); model.ConstrainNode(node3, DegreeOfFreedom.Z); FiniteElementNode node4 = model.NodeFactory.CreateFor2DTruss(10, 0); model.ConstrainNode(node4, DegreeOfFreedom.X); model.ConstrainNode(node4, DegreeOfFreedom.Z); IMaterial material = new GenericElasticMaterial(0, 30000000, 0, 0); ICrossSection section = new SolidRectangle(2, 1); model.ElementFactory.CreateLinearTruss(node1, node2, material, section); model.ElementFactory.CreateLinearTruss(node1, node3, material, section); model.ElementFactory.CreateLinearTruss(node1, node4, material, section); ForceVector externalForce = model.ForceFactory.CreateForTruss(0, -10000); model.ApplyForceToNode(externalForce, node1); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); ReactionVector reactionAtNode2 = results.GetReaction(node2); Assert.AreEqual(0, reactionAtNode2.X, 1); Assert.AreEqual(7929, reactionAtNode2.Z, 1); ReactionVector reactionAtNode3 = results.GetReaction(node3); Assert.AreEqual(2071, reactionAtNode3.X, 1); Assert.AreEqual(2071, reactionAtNode3.Z, 1); ReactionVector reactionAtNode4 = results.GetReaction(node4); Assert.AreEqual(-2071, reactionAtNode4.X, 1); Assert.AreEqual(0, reactionAtNode4.Z, 1); DisplacementVector displacementAtNode1 = results.GetDisplacement(node1); Assert.AreEqual(0.00035, displacementAtNode1.X, 0.00001); ///NOTE this does not match the example in the book, but was instead verified by commercial FE software. It appears as it may be an errata in the book. Assert.AreEqual(-0.00132, displacementAtNode1.Z, 0.00001); ///NOTE this does not match the example in the book, but was instead verified by commercial FE software. It appears as it may be an errata in the book. }
public void Calculate3DFrameOf3BeamsAnd24Dof() { FiniteElementModel model = new FiniteElementModel(ModelType.Full3D); FiniteElementNode node1 = model.NodeFactory.Create(0, 0, 0); FiniteElementNode node2 = model.NodeFactory.Create(3, 0, 0); model.ConstrainNode(node2, DegreeOfFreedom.X); model.ConstrainNode(node2, DegreeOfFreedom.Y); model.ConstrainNode(node2, DegreeOfFreedom.Z); FiniteElementNode node3 = model.NodeFactory.Create(0, 3, 0); model.ConstrainNode(node3, DegreeOfFreedom.X); model.ConstrainNode(node3, DegreeOfFreedom.Y); model.ConstrainNode(node3, DegreeOfFreedom.Z); FiniteElementNode node4 = model.NodeFactory.Create(0, 0, -4); model.ConstrainNode(node4, DegreeOfFreedom.X); model.ConstrainNode(node4, DegreeOfFreedom.Y); model.ConstrainNode(node4, DegreeOfFreedom.Z); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0.3, 84000000000); ICrossSection section = new GenericCrossSection(0.02, 0.0001, 0.0002, 0.00005); model.ElementFactory.CreateLinear3DBeam(node1, node2, material, section); model.ElementFactory.CreateLinear3DBeam(node1, node3, material, section); model.ElementFactory.CreateLinear3DBeam(node1, node4, material, section); ForceVector force = model.ForceFactory.Create(-10000, -15000, 0, 0, 0, 0); model.ApplyForceToNode(force, node1); IFiniteElementSolver solver = new LinearSolverSVD(model); FiniteElementResults results = solver.Solve(); DisplacementVector node1Displacement = results.GetDisplacement(node1); ReactionVector node2Reaction = results.GetReaction(node2); ReactionVector node3Reaction = results.GetReaction(node3); ReactionVector node4Reaction = results.GetReaction(node4); Console.WriteLine("\nNode1 displacement : \n" + node1Displacement); Console.WriteLine("\nNode2 reaction : \n" + node2Reaction); Console.WriteLine("\nNode3 reaction : \n" + node3Reaction); Console.WriteLine("\nNode4 reaction : \n" + node4Reaction); Assert.Inconclusive("The below x, y and zz pass, but z, xx, yy fail"); Assert.AreEqual(-0.000007109, node1Displacement.X, 0.00000001); Assert.AreEqual(-0.000010680, node1Displacement.Y, 0.00000001); Assert.AreEqual(-0.000014704, node1Displacement.Z, 0.00000001); Assert.AreEqual(0.000001147, node1Displacement.XX, 0.00000001); Assert.AreEqual(-0.000001068, node1Displacement.YY, 0.00000001); Assert.AreEqual(0.000000595, node1Displacement.ZZ, 0.000000001); }
public void CanGetZeroCombinedForceOnNodeWithoutForces() { Assert.AreEqual(0, SUT.GetAllForcesAppliedTo(node).Count); ForceVector result = SUT.GetCombinedForceOn(node); Assert.IsNotNull(result); Assert.AreEqual(6, result.Count); // 6 DOF Assert.AreEqual(0, result.X); Assert.AreEqual(0, result.Y); Assert.AreEqual(0, result.Z); }
public void CanGetCombinedForceOnNode() { SUT.ApplyForceToNode(exampleForce1, node); SUT.ApplyForceToNode(exampleForce2, node); ForceVector result = SUT.GetCombinedForceOn(node); Assert.IsNotNull(result); Assert.AreEqual(6, result.Count); // 6 DOF Assert.AreEqual(3, result.X); Assert.AreEqual(0, result.Y); }
/// <summary> /// Creates a new force for a 1D ModelType /// </summary> /// <param name="valueOfXComponent">The component of the force along the global x-axis</param> /// <returns>The force vector which has been created</returns> public ForceVector Create(double valueOfXComponent) { Guard.AgainstInvalidState(() => { return this.modelType != ModelType.Truss1D; }, "Can only use the Create(double valueOfXComponent) method to create a force along the x-axis when a 1D system is in use"); ForceVector newForce = new ForceVector(valueOfXComponent); if (this.repository != null) { this.repository.Add(newForce); } return newForce; }
public void SimplySupportedBeam() { FiniteElementModel model = new FiniteElementModel(ModelType.Full3D); FiniteElementNode node1 = model.NodeFactory.Create(0, 0, 0); model.ConstrainNode(node1, DegreeOfFreedom.X); model.ConstrainNode(node1, DegreeOfFreedom.Y); model.ConstrainNode(node1, DegreeOfFreedom.Z); model.ConstrainNode(node1, DegreeOfFreedom.XX); FiniteElementNode node2 = model.NodeFactory.Create(1.0, 0, 0); model.ConstrainNode(node2, DegreeOfFreedom.X); model.ConstrainNode(node2, DegreeOfFreedom.Y); model.ConstrainNode(node2, DegreeOfFreedom.Z); model.ConstrainNode(node2, DegreeOfFreedom.XX); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 84000000000); ICrossSection section = new GenericCrossSection(0.0001, 0.0002, 0.0002, 0.00005); model.ElementFactory.CreateLinear3DBeam(node1, node2, material, section); ForceVector moment = model.ForceFactory.Create(0, 0, 0, 0, 10000, 0); model.ApplyForceToNode(moment, node1); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); // check the results DisplacementVector displacementAtNode1 = results.GetDisplacement(node1); Assert.AreEqual(0, displacementAtNode1.Z, 0.001); Assert.AreEqual(0.00007936, displacementAtNode1.YY, 0.000001); DisplacementVector displacementAtNode2 = results.GetDisplacement(node2); Assert.AreEqual(0, displacementAtNode2.Z, 0.001); Assert.AreEqual(-0.00003968, displacementAtNode2.YY, 0.000001); ReactionVector reactionAtNode1 = results.GetReaction(node1); Assert.AreEqual(-10000, reactionAtNode1.Z, 0.001); Assert.AreEqual(0, reactionAtNode1.YY, 0.001); ReactionVector reactionAtNode2 = results.GetReaction(node2); Assert.AreEqual(10000, reactionAtNode2.Z, 0.001); Assert.AreEqual(0, reactionAtNode2.YY, 0.001); }
public void SetUp() { model = new FiniteElementModel(ModelType.Truss1D); node1 = model.NodeFactory.Create(0); node2 = model.NodeFactory.Create(1); spring1 = model.ElementFactory.CreateLinearConstantSpring(node1, node2, 4); model.ConstrainNode(node1, DegreeOfFreedom.X); force1 = model.ForceFactory.Create(20); model.ApplyForceToNode(force1, node2); SUT = new LinearSolverSVD(model); }
void OnMouseUp() { if (isPlacingorceVector) { if (!(previewTarget.transform.localPosition.magnitude > maxSpawnDistance)) { Destroy(previewTarget); } else { forceVector = gameObject.AddComponent<ForceVector>(); forceVector.target = previewTarget.transform; GetComponent<ColorStack>().Add(this, activeColor); } previewTarget = null; isPlacingorceVector = false; } }
public void Setup() { SUT = new FiniteElementModel(ModelType.Truss1D); node1 = SUT.NodeFactory.Create(0); node2 = SUT.NodeFactory.Create(1); node3 = SUT.NodeFactory.Create(2); spring1 = SUT.ElementFactory.CreateLinearConstantSpring(node1, node2, 3); spring2 = SUT.ElementFactory.CreateLinearConstantSpring(node2, node3, 2); SUT.ConstrainNode(node1, DegreeOfFreedom.X); SUT.ConstrainNode(node3, DegreeOfFreedom.X); force1 = SUT.ForceFactory.Create(20); SUT.ApplyForceToNode(force1, node2); }
public void OneQuadMembraneLateralLoad() { FiniteElementModel model = new FiniteElementModel(ModelType.Membrane2D); FiniteElementNode node1 = model.NodeFactory.Create(0.0, 0.0); model.ConstrainNode(node1, DegreeOfFreedom.X); model.ConstrainNode(node1, DegreeOfFreedom.Y); FiniteElementNode node2 = model.NodeFactory.Create(1.0, 0.0); model.ConstrainNode(node2, DegreeOfFreedom.Y); FiniteElementNode node3 = model.NodeFactory.Create(1.0, 1.0); FiniteElementNode node4 = model.NodeFactory.Create(0.0, 1.0); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0.3, 0); model.ElementFactory.CreateLinearConstantStressQuadrilateral(node1, node2, node3, node4, material, 0.1); ForceVector force = model.ForceFactory.Create(10000, 0); model.ApplyForceToNode(force, node4); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); ReactionVector reaction1 = results.GetReaction(node1); // Console.WriteLine("\nReaction1 : \n" + reaction1); ReactionVector reaction2 = results.GetReaction(node2); // Console.WriteLine("\nReaction2 : \n" + reaction2); Assert.AreEqual(0, reaction1.Y + reaction2.Y, 1); Assert.AreEqual(-10000, reaction1.X, 1); DisplacementVector displacement3 = results.GetDisplacement(node3); DisplacementVector displacement4 = results.GetDisplacement(node4); Console.WriteLine("\nDisplacement3 : \n" + displacement3); Console.WriteLine("\nDisplacement4 : \n" + displacement4); Assert.AreEqual(0.000002619047, displacement3.X, 0.0000000001); Assert.AreEqual(-0.000001428571, displacement3.Y, 0.0000000001); Assert.AreEqual(0.000004047618, displacement4.X, 0.0000000001); Assert.AreEqual(0.000001428571, displacement4.Y, 0.0000000001); }
private void Create2DSingleSpringModelAroundOrigin(double x, double z) { model = new FiniteElementModel(ModelType.Truss2D); node1 = model.NodeFactory.CreateFor2DTruss(0, 0); node2 = model.NodeFactory.CreateFor2DTruss(x, z); spring1 = model.ElementFactory.CreateLinearConstantSpring(node1, node2, 1000); model.ConstrainNode(node1, DegreeOfFreedom.X); model.ConstrainNode(node1, DegreeOfFreedom.Z); model.ConstrainNode(node2, DegreeOfFreedom.X); force1 = model.ForceFactory.CreateForTruss(0, -10); model.ApplyForceToNode(force1, node2); SUT = new LinearSolverSVD(model); }
public void CalculateModelOfTwoBarsAndOneSpringWithFourDegreesOfFreedom() { FiniteElementModel model = new FiniteElementModel(ModelType.Truss1D); FiniteElementNode node1 = model.NodeFactory.Create(0); model.ConstrainNode(node1, DegreeOfFreedom.X); FiniteElementNode node2 = model.NodeFactory.Create(2.0); FiniteElementNode node3 = model.NodeFactory.Create(4.0); FiniteElementNode node4 = model.NodeFactory.Create(6.0); model.ConstrainNode(node4, DegreeOfFreedom.X); IMaterial material = new GenericElasticMaterial(0, 70000000000, 0, 0); ICrossSection section = new SolidRectangle(0.02, 0.01); model.ElementFactory.CreateLinearTruss(node1, node2, material, section); model.ElementFactory.CreateLinearTruss(node2, node3, material, section); model.ElementFactory.CreateLinearConstantSpring(node3, node4, 2000000); ForceVector externalForce = model.ForceFactory.Create(8000); model.ApplyForceToNode(externalForce, node2); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); DisplacementVector displacementAtNode2 = results.GetDisplacement(node2); Assert.AreEqual(0.000935, displacementAtNode2.X, 0.001); DisplacementVector displacementAtNode3 = results.GetDisplacement(node3); Assert.AreEqual(0.000727, displacementAtNode3.X, 0.001); ReactionVector reactionAtNode1 = results.GetReaction(node1); Assert.AreEqual(-6546, reactionAtNode1.X, 1); ReactionVector reactionAtNode4 = results.GetReaction(node4); Assert.AreEqual(-1455, reactionAtNode4.X, 1); }
void OnMouseDown() { // Destroy existing target if exists. if (forceVector != null) { Destroy(forceVector); forceVector = null; GetComponent<ColorStack>().Remove(this); } // If holding LCTRL, delete everything. if (!Input.GetKey(KeyCode.LeftControl)) { // Spawn new target. isPlacingorceVector = true; previewTarget = (GameObject)Instantiate(prefabToSpawn); previewTarget.transform.position = mousePositionInWorldOnZPlane(); previewTarget.transform.parent = transform; } }
public void CalculateModelOfThreeSpringsWithFourDegreesOfFreedom() { FiniteElementModel model = new FiniteElementModel(ModelType.Truss1D); FiniteElementNode node1 = model.NodeFactory.Create(0); model.ConstrainNode(node1, DegreeOfFreedom.X); FiniteElementNode node2 = model.NodeFactory.Create(1.0); FiniteElementNode node3 = model.NodeFactory.Create(2.0); model.ConstrainNode(node3, DegreeOfFreedom.X); FiniteElementNode node4 = model.NodeFactory.Create(2.00001); ///TODO allow multiple nodes to be added in the same location model.ConstrainNode(node4, DegreeOfFreedom.X); model.ElementFactory.CreateLinearConstantSpring(node1, node2, 1); model.ElementFactory.CreateLinearConstantSpring(node2, node3, 1); model.ElementFactory.CreateLinearConstantSpring(node2, node4, 1); ForceVector externalForce = model.ForceFactory.Create(10); model.ApplyForceToNode(externalForce, node2); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); DisplacementVector displacementAtNode2 = results.GetDisplacement(node2); Assert.AreEqual(3.333, displacementAtNode2.X, 0.001); ReactionVector reactionAtNode1 = results.GetReaction(node1); Assert.AreEqual(-3.333, reactionAtNode1.X, 0.001); ReactionVector reactionAtNode3 = results.GetReaction(node3); Assert.AreEqual(-3.333, reactionAtNode3.X, 0.001); ReactionVector reactionAtNode4 = results.GetReaction(node4); Assert.AreEqual(-3.333, reactionAtNode4.X, 0.001); }
public void SimplySupportedBeam() //TODO verify using independent check { FiniteElementModel model = new FiniteElementModel(ModelType.Beam1D); // we will create and analyze a 1D beam system FiniteElementNode node1 = model.NodeFactory.Create(0); // create a node at the origin model.ConstrainNode(node1, DegreeOfFreedom.Z); // constrain the node from moving in the Z-axis FiniteElementNode node2 = model.NodeFactory.Create(1.0); // create a second node at a distance 1 metre along the X axis model.ConstrainNode(node2, DegreeOfFreedom.Z); // constrain the node from moving in the Z-axis IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 0); ICrossSection section = new GenericCrossSection(0.0001, 0.0002); model.ElementFactory.CreateLinear3DBeam(node1, node2, material, section); // create a spring between the two nodes of a stiffness of 2000 Newtons per metre ForceVector moment = model.ForceFactory.CreateFor1DBeam(0, 10000); // Create a clockwise(?) moment of 10 KiloNewtonmetres around the yy axis model.ApplyForceToNode(moment, node1); // Apply that moment to the first node IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); // Create a new instance of the solver class and pass it the model to solve FiniteElementResults results = solver.Solve(); // ask the solver to solve the model and return results // check the results DisplacementVector displacementAtNode1 = results.GetDisplacement(node1); Assert.AreEqual(0, displacementAtNode1.Z, 0.001); Assert.AreEqual(0.00007936, displacementAtNode1.YY, 0.00000001); DisplacementVector displacementAtNode2 = results.GetDisplacement(node2); Assert.AreEqual(0, displacementAtNode2.Z, 0.001); Assert.AreEqual(-0.00003968, displacementAtNode2.YY, 0.00000001); ReactionVector reactionAtNode1 = results.GetReaction(node1); Assert.AreEqual(-10000, reactionAtNode1.Z, 0.001); Assert.AreEqual(0, reactionAtNode1.YY, 0.001); ReactionVector reactionAtNode2 = results.GetReaction(node2); Assert.AreEqual(10000, reactionAtNode2.Z, 0.001); Assert.AreEqual(0, reactionAtNode2.YY, 0.001); }
public void ThreeNodeCantilever() { FiniteElementModel model = new FiniteElementModel(ModelType.Full3D); FiniteElementNode node1 = model.NodeFactory.Create(0, 0, 0); model.ConstrainNode(node1, DegreeOfFreedom.X); model.ConstrainNode(node1, DegreeOfFreedom.Y); model.ConstrainNode(node1, DegreeOfFreedom.Z); model.ConstrainNode(node1, DegreeOfFreedom.XX); model.ConstrainNode(node1, DegreeOfFreedom.YY); model.ConstrainNode(node1, DegreeOfFreedom.ZZ); FiniteElementNode node2 = model.NodeFactory.Create(1.5, 0, 0); FiniteElementNode node3 = model.NodeFactory.Create(3.0, 0, 0); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 84000000000); ICrossSection section = new GenericCrossSection(0.0001, 0.0002, 0.0002, 0.00005); model.ElementFactory.CreateLinear3DBeam(node1, node2, material, section); model.ElementFactory.CreateLinear3DBeam(node2, node3, material, section); ForceVector force = model.ForceFactory.Create(0, 0, -10000, 0, 0, 0); model.ApplyForceToNode(force, node3); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); ReactionVector reaction = results.GetReaction(node1); Assert.AreEqual(10000, reaction.Z, 0.001); Assert.AreEqual(-30000, reaction.YY, 0.001); DisplacementVector displacement2 = results.GetDisplacement(node2); Assert.AreEqual(-0.000670, displacement2.Z, 0.0005); Assert.AreEqual(0.000804, displacement2.YY, 0.0001); DisplacementVector displacement3 = results.GetDisplacement(node3); Assert.AreEqual(-0.00214, displacement3.Z, 0.0005); Assert.AreEqual(0.00107, displacement3.YY, 0.0001); }
/// <summary> /// /// </summary> /// <param name="valueOfZComponent"></param> /// <param name="valueOfMomentAboutYY"></param> /// <returns></returns> public ForceVector CreateFor1DBeam(double valueOfZComponent, double valueOfMomentAboutYY) { Guard.AgainstInvalidState(() => { return !(this.modelType == ModelType.Beam1D || this.modelType == ModelType.Frame2D); }, "Can only use the CreateFor1DBeam(double valueOfZComponent, double valueOfMomentAboutYY) method when a 1D Beam system is in use"); ForceVector newForce = new ForceVector(0, 0, valueOfZComponent, 0, valueOfMomentAboutYY, 0); if (this.repository != null) { this.repository.Add(newForce); } return newForce; }
/// <summary> /// Creates a new force for a 2D ModelType /// </summary> /// <param name="valueOfXComponent">The component of the force along the global x-axis</param> /// <param name="valueOfYComponent">The component of the force along the global y-axis</param> /// <returns>The force vector which has been created</returns> public ForceVector Create(double valueOfXComponent, double valueOfYComponent) { Guard.AgainstInvalidState(() => { return !this.modelType.IsAllowedDegreeOfFreedomForBoundaryConditions(DegreeOfFreedom.X); }, "Cannot create a boundary condition along the x-axis for this model type."); Guard.AgainstInvalidState(() => { return !this.modelType.IsAllowedDegreeOfFreedomForBoundaryConditions(DegreeOfFreedom.Y); }, "Cannot create a boundary condition along the y-axis for this model type."); ForceVector newForce = new ForceVector(valueOfXComponent, valueOfYComponent); if (this.repository != null) { this.repository.Add(newForce); } return newForce; }
public void UpdateTorque() { // staticTorque will represent engine torque due to imbalanced placement staticTorque.Zero(); // controlTorque is the maximum amount of torque applied by setting a control to 1.0. controlTorque.Zero(); rawTorque.Zero(); staticEngineTorque.Zero(); controlEngineTorque.Zero(); Vector3d pitchControl = Vector3d.zero; Vector3d yawControl = Vector3d.zero; Vector3d rollControl = Vector3d.zero; rcsVectors.Clear(); engineNeutVectors.Clear(); enginePitchVectors.Clear(); engineYawVectors.Clear(); engineRollVectors.Clear(); foreach (ModuleReactionWheel wheel in reactionWheelModules) { if (wheel.isActiveAndEnabled && wheel.State == ModuleReactionWheel.WheelState.Active) { // TODO: Check to see if the component values depend on part orientation, and implement if needed. rawTorque.x += wheel.PitchTorque; rawTorque.z += wheel.YawTorque; rawTorque.y += wheel.RollTorque; } } if (shared.Vessel.ActionGroups[KSPActionGroup.RCS]) { foreach (ModuleRCS rcs in rcsModules) { if (rcs.rcsEnabled && !rcs.part.ShieldedFromAirstream) { for (int i = 0; i < rcs.thrusterTransforms.Count; i++) { Transform thrustdir = rcs.thrusterTransforms[i]; ForceVector force = new ForceVector { Force = thrustdir.up * rcs.thrusterPower, Position = thrustdir.position - centerOfMass, // We need to adjust the relative center of mass because the rigid body // will report the position of the parent part ID = rcs.part.flightID.ToString() + "-" + i.ToString() }; Vector3d torque = force.Torque; rcsVectors.Add(force); // component values of the local torque are calculated using the dot product with the rotation axis. // Only using positive contributions, which is only valid when symmetric placement is assumed rawTorque.x += Math.Max(Vector3d.Dot(torque, vesselStarboard), 0); rawTorque.z += Math.Max(Vector3d.Dot(torque, vesselTop), 0); rawTorque.y += Math.Max(Vector3d.Dot(torque, vesselForward), 0); } } } } for (int i = 0; i < engineModules.Count; i++) { ModuleEngines engine = engineModules[i]; ModuleGimbal gimbal = gimbalModules[i]; if (engine.isActiveAndEnabled && engine.EngineIgnited) { // if the engine is active and ignited, calculate torque float gimbalRange = 0; List<Quaternion> initRots = new List<Quaternion>(); if (gimbal != null && !gimbal.gimbalLock) { gimbalRange = gimbal.gimbalRange * gimbal.gimbalLimiter / 100; // grab the gimbal range // To determine the neutral thrust vector, we reset the gimbal transform to it's "initial" value // from the initRots array and then read the direction from the thrustTransform. We do this for // each gimbal object, and then return them to the previous value after calculating the thrust // transforms, so that we don't inerupt the gimbal logic. for (int gblIdx = 0; gblIdx < gimbal.gimbalTransforms.Count; gblIdx++) { initRots.Add(gimbal.gimbalTransforms[gblIdx].localRotation); // store the current rotation gimbal.gimbalTransforms[gblIdx].localRotation = gimbal.initRots[gblIdx]; // set the rotation to the "initial" value } } for (int xfrmIdx = 0; xfrmIdx < engine.thrustTransforms.Count; xfrmIdx++) { // iterate through each thrust transform. Some engines have multiple transforms for // thrust and/or gimbal, so we need to be able to use as many as the part contains. Transform thrustTransform = engine.thrustTransforms[xfrmIdx]; Vector3d position = thrustTransform.position; if (gimbal != null && !gimbal.gimbalLock) { Transform gimbalTransform = FindParentTransform(thrustTransform, gimbal.gimbalTransformName, engine.part.transform); if (gimbalTransform != null) { // The gimbal position will not move as the gimbal rotates. As of KSP 1.0.5, the Vector engine appears // to be the only engine that moves it's thrust transform location, because the transform itself is located // at the end of the nozzel. Doing so means that our calculated available torque could very well be inaccurate // specifically in the case of roll torque, where it may appear that an axial engine's thrust transform is offset from the // vessel's axial centerline when in fact the axial engine can produce no roll torque. // If there is ever an engine where the thrust transform does not align to the gimbal transform, this assumption // will no longer be valid. position = gimbalTransform.position; // use the gimbal position as the thrust position } } Vector3d neut = -engine.thrustTransforms[xfrmIdx].forward * engine.finalThrust / engine.thrustTransforms.Count; // the neutral control thrust (force is opposite of exhaust direction) Vector3d relCom = position - centerOfMass; string id = string.Format("{0}[{1}]", engine.part.flightID, xfrmIdx); // calculate the neutral gimbal force vector based on the neutral direction and thrust magnitude ForceVector neutralForce = new ForceVector { Force = neut, ID = id, Position = relCom, }; engineNeutVectors.Add(neutralForce); staticEngineTorque += neutralForce.Torque; if (gimbalRange > EPSILON) // only do the gimbal calculation if the range allows it. { Vector3d pitchAxis = Vector3d.Exclude(neut, vesselStarboard); // pitch rotates about the starboard vector Vector3d yawAxis = Vector3d.Exclude(neut, vesselTop); // yaw rotates about the top vector Vector3d rollAxis = Vector3d.Exclude(vesselForward, relCom); // roll rotates about the forward vector ForceVector pitchForce = new ForceVector { Force = Quaternion.AngleAxis(gimbalRange, pitchAxis) * neut, ID = id, Position = relCom }; enginePitchVectors.Add(pitchForce); pitchControl += pitchForce.Torque; ForceVector yawForce = new ForceVector { Force = Quaternion.AngleAxis(gimbalRange, yawAxis) * neut, ID = id, Position = relCom }; engineYawVectors.Add(yawForce); yawControl += yawForce.Torque; ForceVector rollForce; // because of deflection, sometimes an axial engine will look like it can // generate roll torque when it cannot do so reliably. Ignore small offsets. if (rollAxis.sqrMagnitude < 0.02) { rollForce = neutralForce; rollForce = new ForceVector { Force = neutralForce.Force, ID = id, Position = neutralForce.Position }; } else { rollForce = new ForceVector { Force = Quaternion.AngleAxis(gimbalRange, rollAxis) * neut, ID = id, Position = relCom }; } engineRollVectors.Add(rollForce); rollControl += rollForce.Torque; } else { // if there is no gimbal available, or it's too small, just clone the neutral thrust vector enginePitchVectors.Add(new ForceVector { Force = neutralForce.Force, ID = id, Position = neutralForce.Position }); engineYawVectors.Add(new ForceVector { Force = neutralForce.Force, ID = id, Position = neutralForce.Position }); engineRollVectors.Add(new ForceVector { Force = neutralForce.Force, ID = id, Position = neutralForce.Position }); pitchControl += neutralForce.Torque; yawControl += neutralForce.Torque; rollControl += neutralForce.Torque; } } if (gimbal != null && !gimbal.gimbalLock) { // Reset each of the gimbal rotations back to their previous values. This prevents // our calculations from interupting the internal gimbal logic, since some gimbals // do not rotate instantly. for (int gblIdx = 0; gblIdx < gimbal.gimbalTransforms.Count; gblIdx++) { gimbal.gimbalTransforms[gblIdx].localRotation = initRots[gblIdx]; // set the rotation to the previous value } } } else { // if an engine is disabled, hide the associated vectors (do this for all transforms) for (int xfrmIdx = 0; xfrmIdx < engine.thrustTransforms.Count; xfrmIdx++) { string key = string.Format("{0}[{1}]", engine.part.flightID, xfrmIdx); if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "gimbaled"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "torque"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "control"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "position"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } } } } // Because the engines may generate torque about the other 2 axes when trying to rotate about one, // use a dot product to get the component of the torque in the desired direction. Also subtract out // the static engine torque, to account for offset placement. This still does not properly balance // engines that are offset, since the available torque may be drastically different between the // positive and negative limit. If there is a large static torque, it's also possible for the // calculation to show that there is a small amount of available torque, even though the static // torque will actually overpower the control torque. Eventually it would be nice to modify this // calculation to properly handle asymetric gimbal torque, but for now it will need to be a // constraint of ship design. controlEngineTorque.x = Math.Abs(Vector3d.Dot(pitchControl - staticEngineTorque, vesselStarboard)); controlEngineTorque.z = Math.Abs(Vector3d.Dot(yawControl - staticEngineTorque, vesselTop)); controlEngineTorque.y = Math.Abs(Vector3d.Dot(rollControl - staticEngineTorque, vesselForward)); rawTorque.x += controlEngineTorque.x; rawTorque.z += controlEngineTorque.z; rawTorque.y += controlEngineTorque.y; rawTorque.x = (rawTorque.x + PitchTorqueAdjust) * PitchTorqueFactor; rawTorque.z = (rawTorque.z + YawTorqueAdjust) * YawTorqueFactor; rawTorque.y = (rawTorque.y + RollTorqueAdjust) * RollTorqueFactor; controlTorque = rawTorque + adjustTorque; //controlTorque = Vector3d.Scale(rawTorque, adjustTorque); //controlTorque = rawTorque; double minTorque = EPSILON; if (controlTorque.x < minTorque) controlTorque.x = minTorque; if (controlTorque.y < minTorque) controlTorque.y = minTorque; if (controlTorque.z < minTorque) controlTorque.z = minTorque; }
public void UpdateTorque() { // staticTorque will represent engine torque due to imbalanced placement staticTorque.Zero(); // controlTorque is the maximum amount of torque applied by setting a control to 1.0. controlTorque.Zero(); rawTorque.Zero(); staticEngineTorque.Zero(); controlEngineTorque.Zero(); Vector3d pitchControl = Vector3d.zero; Vector3d yawControl = Vector3d.zero; Vector3d rollControl = Vector3d.zero; rcsVectors.Clear(); engineNeutVectors.Clear(); enginePitchVectors.Clear(); engineYawVectors.Clear(); engineRollVectors.Clear(); foreach (ModuleReactionWheel wheel in reactionWheelModules) { if (wheel.isActiveAndEnabled && wheel.State == ModuleReactionWheel.WheelState.Active) { // TODO: Check to see if the component values depend on part orientation, and implement if needed. rawTorque.x += wheel.PitchTorque; rawTorque.z += wheel.YawTorque; rawTorque.y += wheel.RollTorque; } } if (shared.Vessel.ActionGroups[KSPActionGroup.RCS]) { foreach (ModuleRCS rcs in rcsModules) { if (rcs.rcsEnabled && !rcs.part.ShieldedFromAirstream) { for (int i = 0; i < rcs.thrusterTransforms.Count; i++) { Transform thrustdir = rcs.thrusterTransforms[i]; ForceVector force = new ForceVector { Force = thrustdir.up * rcs.thrusterPower, Position = thrustdir.position - centerOfMass, // We need to adjust the relative center of mass because the rigid body // will report the position of the parent part ID = rcs.part.flightID.ToString() + "-" + i.ToString() }; Vector3d torque = force.Torque; rcsVectors.Add(force); // component values of the local torque are calculated using the dot product with the rotation axis. // Only using positive contributions, which is only valid when symmetric placement is assumed rawTorque.x += Math.Max(Vector3d.Dot(torque, vesselStarboard), 0); rawTorque.z += Math.Max(Vector3d.Dot(torque, vesselTop), 0); rawTorque.y += Math.Max(Vector3d.Dot(torque, vesselForward), 0); } } } } for (int i = 0; i < engineModules.Count; i++) { ModuleEngines engine = engineModules[i]; ModuleGimbal gimbal = gimbalModules[i]; Quaternion gimbalRotation = new Quaternion(); float gimbalRange = 0; bool hasGimbal = false; if (engine.isActiveAndEnabled && engine.EngineIgnited) { if (gimbal != null) { hasGimbal = true; if (gimbal.gimbalLock) { foreach (var transform in gimbal.gimbalTransforms) { gimbalRotation = transform.rotation; gimbalRange = 0; } } else { if (gimbal.gimbalTransforms.Count > 1) shared.Logger.LogError("SteeringManager: multiple gimbal transforms found"); Transform transform = gimbal.gimbalTransforms[0]; // init rotations are stored in a local scope. Need to convert back to global scope. var initRotation = transform.localRotation; transform.localRotation = gimbal.initRots[0]; //vEngines[key].Start = transform.localPosition; gimbalRotation = transform.rotation; gimbalRange = gimbal.gimbalRange * gimbal.gimbalLimiter / 100; //gimbalRange = gimbal.gimbalRange; transform.localRotation = initRotation; } } if (engine.thrustTransforms.Count > 1) shared.Logger.LogError("SteeringManager: multiple engine transforms found"); foreach (var transform in engine.thrustTransforms) { if (!hasGimbal) gimbalRotation = transform.rotation; var relCom = transform.position - centerOfMass; Vector3d neut = gimbalRotation * Vector3d.forward; ForceVector neutralForce = new ForceVector { Force = neut * engine.finalThrust, ID = engine.part.flightID.ToString(), Position = relCom, }; engineNeutVectors.Add(neutralForce); staticEngineTorque += neutralForce.Torque; if (gimbalRange > EPSILON) { Vector3d pitchAxis = Vector3d.Exclude(neut, vesselStarboard); Vector3d yawAxis = Vector3d.Exclude(neut, vesselTop); Vector3d rollAxis = Vector3d.Exclude(vesselForward, relCom); ForceVector pitchForce = new ForceVector { Force = Quaternion.AngleAxis(gimbalRange, pitchAxis) * neut, Position = relCom }; enginePitchVectors.Add(pitchForce); pitchControl += pitchForce.Torque; ForceVector yawForce = new ForceVector { Force = Quaternion.AngleAxis(gimbalRange, yawAxis) * neut, Position = relCom }; engineYawVectors.Add(yawForce); yawControl += yawForce.Torque; ForceVector rollForce; if (rollAxis.sqrMagnitude < 0.02) { rollForce = neutralForce; } else { rollForce = new ForceVector { Force = Quaternion.AngleAxis(gimbalRange, rollAxis) * neut, Position = relCom }; } engineRollVectors.Add(rollForce); rollControl += rollForce.Torque; } else { enginePitchVectors.Add(neutralForce); engineYawVectors.Add(neutralForce); engineRollVectors.Add(neutralForce); pitchControl += neutralForce.Torque; yawControl += neutralForce.Torque; rollControl += neutralForce.Torque; } } } else { string key = engine.part.flightID.ToString(); if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "gimbaled"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "torque"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "control"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } key = engine.part.flightID.ToString() + "position"; if (vEngines.Keys.Contains(key)) { vEngines[key].SetShow(false); vEngines.Remove(key); } } } controlEngineTorque.x = pitchControl.magnitude; controlEngineTorque.z = yawControl.magnitude; controlEngineTorque.y = rollControl.magnitude; rawTorque.x += controlEngineTorque.x; rawTorque.z += controlEngineTorque.z; rawTorque.y += controlEngineTorque.y; rawTorque.x = (rawTorque.x + PitchTorqueAdjust) * PitchTorqueFactor; rawTorque.z = (rawTorque.z + YawTorqueAdjust) * YawTorqueFactor; rawTorque.y = (rawTorque.y + RollTorqueAdjust) * RollTorqueFactor; controlTorque = rawTorque + adjustTorque; //controlTorque = Vector3d.Scale(rawTorque, adjustTorque); //controlTorque = rawTorque; double minTorque = EPSILON; if (controlTorque.x < minTorque) controlTorque.x = minTorque; if (controlTorque.y < minTorque) controlTorque.y = minTorque; if (controlTorque.z < minTorque) controlTorque.z = minTorque; }
public void Calculate3DTrussOf4BarsAnd15Dof() { FiniteElementModel model = new FiniteElementModel(ModelType.Truss3D); FiniteElementNode node1 = model.NodeFactory.Create(4, 4, 3); FiniteElementNode node2 = model.NodeFactory.Create(0, 4, 0); model.ConstrainNode(node2, DegreeOfFreedom.X); model.ConstrainNode(node2, DegreeOfFreedom.Y); model.ConstrainNode(node2, DegreeOfFreedom.Z); FiniteElementNode node3 = model.NodeFactory.Create(0, 4, 6); model.ConstrainNode(node3, DegreeOfFreedom.X); model.ConstrainNode(node3, DegreeOfFreedom.Y); model.ConstrainNode(node3, DegreeOfFreedom.Z); FiniteElementNode node4 = model.NodeFactory.Create(4, 0, 3); model.ConstrainNode(node4, DegreeOfFreedom.X); model.ConstrainNode(node4, DegreeOfFreedom.Y); model.ConstrainNode(node4, DegreeOfFreedom.Z); FiniteElementNode node5 = model.NodeFactory.Create(8, -1, 1); model.ConstrainNode(node5, DegreeOfFreedom.X); model.ConstrainNode(node5, DegreeOfFreedom.Y); model.ConstrainNode(node5, DegreeOfFreedom.Z); IMaterial material = new GenericElasticMaterial(0, 210000000000, 0, 0); ICrossSection section = new SolidRectangle(0.01, 0.01); model.ElementFactory.CreateLinearTruss(node1, node2, material, section); model.ElementFactory.CreateLinearTruss(node1, node3, material, section); model.ElementFactory.CreateLinearTruss(node1, node4, material, section); model.ElementFactory.CreateLinearTruss(node1, node5, material, section); ForceVector externalForce = model.ForceFactory.Create(0, -10000, 0, 0, 0, 0); model.ApplyForceToNode(externalForce, node1); IFiniteElementSolver solver = new MatrixInversionLinearSolver(model); FiniteElementResults results = solver.Solve(); ReactionVector reactionAtNode2 = results.GetReaction(node2); Assert.AreEqual(270.9, reactionAtNode2.X, 1); Assert.AreEqual(0, reactionAtNode2.Y, 1); Assert.AreEqual(203.2, reactionAtNode2.Z, 1); ReactionVector reactionAtNode3 = results.GetReaction(node3); Assert.AreEqual(1354.6, reactionAtNode3.X, 1); Assert.AreEqual(0, reactionAtNode3.Y, 1); Assert.AreEqual(-1016, reactionAtNode3.Z, 1); ReactionVector reactionAtNode4 = results.GetReaction(node4); Assert.AreEqual(0, reactionAtNode4.X, 1); Assert.AreEqual(7968.1, reactionAtNode4.Y, 1); Assert.AreEqual(0, reactionAtNode4.Z, 1); ReactionVector reactionAtNode5 = results.GetReaction(node5); Assert.AreEqual(-1625.5, reactionAtNode5.X, 1); Assert.AreEqual(2031.9, reactionAtNode5.Y, 1); Assert.AreEqual(812.8, reactionAtNode5.Z, 1); DisplacementVector displacementAtNode1 = results.GetDisplacement(node1); Assert.AreEqual(-0.0003024, displacementAtNode1.X, 0.0001); //NOTE the results given in the book are 1E03 Assert.AreEqual(-0.0015177, displacementAtNode1.Y, 0.0001); Assert.AreEqual(0.0002688, displacementAtNode1.Z, 0.0001); }
public void Setup() { forceFactory = new ForceFactory(ModelType.Truss1D); SUT = forceFactory.Create(12); }
/// <summary> /// Creates a new force for a 2D ModelType /// </summary> /// <param name="valueOfXComponent">The component of the force along the global x-axis</param> /// <param name="valueOfYComponent">The component of the force along the global y-axis</param> /// <param name="valueOfZComponent">The component of the force along the global z-axis</param> /// <returns>The force vector which has been created</returns> public ForceVector Create(double valueOfXComponent, double valueOfYComponent, double valueOfZComponent, double valueOfXXComponent, double valueOfYYComponent, double valueOfZZComponent) { ////TODO ForceVector newForce = new ForceVector(valueOfXComponent, valueOfYComponent, valueOfZComponent, valueOfXXComponent, valueOfYYComponent, valueOfZZComponent); if (this.repository != null) { this.repository.Add(newForce); } return newForce; }