/// <summary> /// Debug Code: Beam with simple supports at left and right ends that has two equal concentrated loads symmetrically placed. /// Calculate results from User entered values and send output to Debug. /// </summary> /// <param name="loadConcentratedValuesLeft">Left concentrated load values.</param> /// <param name="loadConcentratedValuesRight">Right concentrated load values.</param> public static void CheckResultsSampleBeam02(LoadConcentratedValues loadConcentratedValuesLeft, LoadConcentratedValues loadConcentratedValuesRight) { Debug.WriteLine("\nBeam with simple supports at left and right ends that has two equal concentrated loads symmetrically placed:"); double E = CommonItems.doubleYoungsModulus; double I = CommonItems.doubleInertia; double l = CommonItems.doubleBeamLength; double Pl = loadConcentratedValuesLeft.DoubleLoadConcentratedForce; double a = loadConcentratedValuesLeft.DoubleLoadConcentratedPosition; double Pr = loadConcentratedValuesRight.DoubleLoadConcentratedForce; double b = l - loadConcentratedValuesRight.DoubleLoadConcentratedPosition; Debug.WriteLine($"Inputs: E={E}, I={I}, l={l}, Pl={Pl}, a={a}, Pr={Pr}, b={b}"); if (Pl == Pr && a == b) //Check input. { // Reverse signs, upward forces are positive, downward forces are negative. double Rleft = -(Pl); double Rright = Rleft; double Mmax = -(Pl * a); // Mmax occurs between loads. double Dmax = Pl * a * (3d * l * l - 4d * a * a) / (24 * E * I); double Da = Pl * a * (3d * l * a - 3d * a * a - a * a) / (6d * E * I); Debug.WriteLine($"Reaction left={Rleft}, Reaction right={Rright}"); Debug.WriteLine($"Shear left={-Rleft}, Shear right={Rright}"); Debug.WriteLine($"Maximum moment occurs between loads is {Mmax}"); Debug.WriteLine($"Deflection @ a={a} is {Da}"); Debug.WriteLine($"Max deflection @ midpoint={l / 2d} is {Dmax}"); } else { Debug.WriteLine($"Skipped results since entered load values not equal or not placed symmetrically."); } }
/// <summary> /// Debug Code: Beam with simple supports at left and right ends that has single concentrated load at any point. /// Calculate results from User entered values and send output to Debug. /// </summary> /// <param name="loadConcentratedValues">Concentrated load values.</param> public static void CheckResultsSampleBeam01(LoadConcentratedValues loadConcentratedValues) { Debug.WriteLine("\nBeam with simple supports at left and right ends that has single concentrated load at any point:"); double E = CommonItems.doubleYoungsModulus; double I = CommonItems.doubleInertia; double l = CommonItems.doubleBeamLength; double P = loadConcentratedValues.DoubleLoadConcentratedForce; double a = loadConcentratedValues.DoubleLoadConcentratedPosition; double b = l - a; Debug.WriteLine($"Inputs: E={E}, I={I}, l={l}, P={P}, a={a}"); // Reverse signs, upward forces are positive, downward forces are negative. double Rleft = -(P * b / l); double Rright = -(P * a / l); double Mmax = -(P * a * b / l); // Mmax occurs at point of load, 'a'. double Da = P * a * a * b * b / (3d * E * I * l); // Deflection at 'a' Debug.WriteLine($"Reaction left={Rleft}, Reaction right={Rright}"); Debug.WriteLine($"Shear left={-Rleft}, Shear right={Rright}"); Debug.WriteLine($"a={a}, Maximum moment is {Mmax}"); Debug.WriteLine($"a={a}, Maximum deflection is {Da}"); if (a > b) // Next values calculated and shown only if a > b. { double XDmax = Sqrt(a * (a + 2d * b) / 3d); double Dmax = P * a * b * (a + 2d * b) * Sqrt(3d * a * (a + 2d * b)) / (27d * E * I * l); Debug.WriteLine($"Max deflection occurs @ XDmax={XDmax}, Deflection @ XDmax={Dmax}"); } }
/// <summary> /// Debug Code: Beam with simple support at left end and fixed support at right end that has single concentrated load at any point. /// Calculate results from User entered values and send output to Debug. /// </summary> /// <param name="loadConcentratedValues">Concentrated load values.</param> public static void CheckResultsSampleBeam03(LoadConcentratedValues loadConcentratedValues) { Debug.WriteLine("\nBeam with simple support at left end and fixed support at right end that has single concentrated load at any point:"); double E = CommonItems.doubleYoungsModulus; double I = CommonItems.doubleInertia; double l = CommonItems.doubleBeamLength; double P = loadConcentratedValues.DoubleLoadConcentratedForce; double a = loadConcentratedValues.DoubleLoadConcentratedPosition; double b = l - a; Debug.WriteLine($"Inputs: E={E}, I={I}, l={l}, P={P}, a={a}"); // Reverse signs, upward forces are positive, downward forces are negative. double Rleft = -(P * b * b * (a + 2d * l) / (2d * l * l * l)); double Rright = -(P * a * (3d * l * l - a * a) / (2d * l * l * l)); double Ma = -(Rleft * a); // Moment at 'a'. double Da = (P * a * a * b * b * b) * (3d * l + a) / (12d * E * I * l * l * l); // Deflection at 'a' double Ml = P * a * b * (a + l) / (2d * l * l); // Moment at left (fixed) end of beam. // Not checking all available formula results since formulas are quite complex. Debug.WriteLine($"Reaction left={Rleft}, Reaction right={Rright}"); Debug.WriteLine($"Shear left={-Rleft}, Shear right={Rright}"); Debug.WriteLine($"a={a}, Ma={Ma}"); Debug.WriteLine($"a={a}, Da={Da}"); Debug.WriteLine($"l={l}, Ml={Ml}"); }
/// <summary> /// Debug Code: Cantilever beam with no support at left end and fixed support at right end that has single concentrated load at any point. /// Calculate results from User entered values and send output to Debug. /// </summary> /// <param name="loadConcentratedValues">Concentrated load values.</param> public static void CheckResultsSampleBeam04(LoadConcentratedValues loadConcentratedValues) { Debug.WriteLine("\nCantilever beam with no support at left end and fixed support at right end that has single concentrated load at any point:"); double E = CommonItems.doubleYoungsModulus; double I = CommonItems.doubleInertia; double l = CommonItems.doubleBeamLength; double P = loadConcentratedValues.DoubleLoadConcentratedForce; double a = loadConcentratedValues.DoubleLoadConcentratedPosition; double b = l - a; Debug.WriteLine($"Inputs: E={E}, I={I}, l={l}, P={P}, a={a}"); // Reverse signs, upward forces are positive, downward forces are negative. double Rright = -(P); double Ml = P * b; // Moment at left (fixed) end of beam. double D0 = P * b * b * (3d * l - b) / (6d * E * I); double Da = P * b * b * b / (3d * E * I); Debug.WriteLine($"Reaction left={0d}, Reaction right={Rright}"); Debug.WriteLine($"Shear left={0d}, Shear right={Rright}"); Debug.WriteLine($"l={l}, Ml={Ml}"); Debug.WriteLine($"a={a}, Ma={0d}"); Debug.WriteLine($"a={a}, Da={Da}"); Debug.WriteLine($"At left end of beam, Dmax={D0}"); }
/*** private static methods follow *************************************************************************************/ /// <summary> /// Calculate list of concentrated loads that simulate a uniform load. Concentrated loads are derived from segments of uniform load. /// The area of each segment is calculated and an equivalent concentrated load is placed at centroid of each segment. /// Parameters used to keep method independent from equivalent CommonItems values. /// </summary> /// <param name="loadUniformValues">Class used to save User entered uniform loads.</param> /// <param name="doubleLoadUniformPositionLeft">Left uniform load position from left end of beam. Minimum value is 0d. Maximum value is doubleBeamLength.</param> /// <param name="doubleLoadUniformPositionRight">Right uniform load position from left end of beam. Value must be > DoublePositionLeft and <= doubleBeamLength.</param> /// <param name="doubleLoadUniformForceLeft">Left uniform load force. Uniform forces are distributed via straight line from left to right. Downward forces are negative.</param> /// <param name="doubleLoadUniformForceRight">Right uniform load force. Uniform forces are distributed via straight line from left to right. Downward forces are negative.</param> private static void UniformLoadSimulate(ref LoadUniformValues loadUniformValues, double doubleLoadUniformPositionLeft, double doubleLoadUniformPositionRight, double doubleLoadUniformForceLeft, double doubleLoadUniformForceRight) { loadUniformValues.DoublePositionLeft = doubleLoadUniformPositionLeft; loadUniformValues.DoublePositionRight = doubleLoadUniformPositionRight; loadUniformValues.DoubleForceLeft = doubleLoadUniformForceLeft; loadUniformValues.DoubleForceRight = doubleLoadUniformForceRight; loadUniformValues.DoubleLoadLength = doubleLoadUniformPositionRight - doubleLoadUniformPositionLeft; if (doubleOutputSegmentLength == 0d) { // Case if doubleOutputSegmentLength was not entered or set to 0. loadUniformValues.IntNumberOfSegments = 1; loadUniformValues.DoubleSegmentLength = loadUniformValues.DoubleLoadLength; } else { // Calculate number of beam segments to spread uniform load across beam length. int intBeamSegments = (int)Round(doubleBeamLength / doubleOutputSegmentLength, MidpointRounding.AwayFromZero); double doubleBeamSegmentLength = doubleBeamLength / intBeamSegments; //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): doubleBeamLength={doubleBeamLength}, intBeamSegments={intBeamSegments}, doubleBeamSegmentLength={doubleBeamSegmentLength}"); // Use beam segment length as starting value to calculate load segment length. if (doubleBeamSegmentLength >= loadUniformValues.DoubleLoadLength) { loadUniformValues.IntNumberOfSegments = 1; loadUniformValues.DoubleSegmentLength = loadUniformValues.DoubleLoadLength; } else { loadUniformValues.IntNumberOfSegments = (int)Round(loadUniformValues.DoubleLoadLength / doubleBeamSegmentLength, MidpointRounding.AwayFromZero); loadUniformValues.DoubleSegmentLength = loadUniformValues.DoubleLoadLength / loadUniformValues.IntNumberOfSegments; } } //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): loadUniformValues.IntNumberOfSegments={loadUniformValues.IntNumberOfSegments}, loadUniformValues.DoubleSegmentLength={loadUniformValues.DoubleSegmentLength}"); // Total uniform load force is area of uniform load. Absolute values need to be considered since forces can be positive or negative. // Next two variables are used as 'ref' variables if uniform load is triangle or trapazoid. Therefore they need to be initialized to 0d. double doubleArea = 0d; // Calculated segment area (force) of rectangle, triangle, or trapazoid. double doubleCentroid = 0d; // Calculated segment centroid of rectangle, triangle, or trapazoid. loadUniformValues.ListSimulatedLoads = new List <LoadConcentratedValues> { }; // Case #1: Uniform load is a rectangle. bool boolLoadIsRectangle = false; if (loadUniformValues.DoubleForceLeft == loadUniformValues.DoubleForceRight) { //Debug.WriteLine($"EnterLoadsUniform.UniformLoadSimulate(): Uniform load is a rectangle."); boolLoadIsRectangle = true; doubleCentroid = loadUniformValues.DoublePositionLeft + loadUniformValues.DoubleSegmentLength / 2d; doubleArea = loadUniformValues.DoubleForceLeft * loadUniformValues.DoubleLoadLength / loadUniformValues.IntNumberOfSegments; if (loadUniformValues.IntNumberOfSegments == 1) // Applied single rectangle load. { //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Applied single rectangle load, doubleCentroid={doubleCentroid}, doubleArea={doubleArea}"); LoadConcentratedValues loadConcentratedValues = new LoadConcentratedValues { DoubleLoadConcentratedPosition = doubleCentroid, DoubleLoadConcentratedForce = doubleArea, DoubleLoadConcentratedMoment = 0d // Moment always zero if uniform load. }; loadUniformValues.ListSimulatedLoads.Add(loadConcentratedValues); } else { doubleCentroid -= loadUniformValues.DoubleSegmentLength; // Initialize doubleCentroid value for first pass in next loop. for (int i = 0; i < loadUniformValues.IntNumberOfSegments; i++) { doubleCentroid += loadUniformValues.DoubleSegmentLength; //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Applied multiple rectangle loads, doubleCentroid={doubleCentroid}, doubleArea={doubleArea}"); LoadConcentratedValues loadConcentratedValues = new LoadConcentratedValues { DoubleLoadConcentratedPosition = doubleCentroid, DoubleLoadConcentratedForce = doubleArea, DoubleLoadConcentratedMoment = 0d // Moment always zero if uniform load. }; loadUniformValues.ListSimulatedLoads.Add(loadConcentratedValues); } } } // Case #2: Uniform load is a triangle or trapazoid. double doubleTriangleHeight; // Difference of ForceLeft and ForceRight is triangle height. if (!boolLoadIsRectangle) { //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Uniform load is a triangle or trapazoid."); if (loadUniformValues.IntNumberOfSegments == 1) // Applied single triangle or trapazoid uniform load. { doubleTriangleHeight = CalcTriangleHeight(loadUniformValues.DoubleForceLeft, loadUniformValues.DoubleForceRight); if (Abs(loadUniformValues.DoubleForceLeft) > Abs(loadUniformValues.DoubleForceRight)) { CalcCentroidValues(ref doubleArea, ref doubleCentroid, loadUniformValues.DoubleLoadLength, loadUniformValues.DoubleForceRight, doubleTriangleHeight, true); //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Case: Abs(DoubleForceLeft) > Abs(DoubleForceRight), doubleArea={doubleArea}, doubleCentroid={doubleCentroid}"); } else { CalcCentroidValues(ref doubleArea, ref doubleCentroid, loadUniformValues.DoubleLoadLength, loadUniformValues.DoubleForceLeft, doubleTriangleHeight, false); //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Case: Abs(DoubleForceLeft) < Abs(DoubleForceRight), doubleArea={doubleArea}, doubleCentroid={doubleCentroid}"); } doubleCentroid = loadUniformValues.DoublePositionLeft + doubleCentroid; //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Case: Applied single triangle or trapazoid uniform load, doubleCentroid={doubleCentroid}, doubleArea={doubleArea}"); LoadConcentratedValues loadConcentratedValues = new LoadConcentratedValues { DoubleLoadConcentratedPosition = doubleCentroid, DoubleLoadConcentratedForce = doubleArea, DoubleLoadConcentratedMoment = 0d // Moment always zero if uniform load. }; loadUniformValues.ListSimulatedLoads.Add(loadConcentratedValues); } else { // Equation of slope is m=(y2-y1)/(x2-x1) where m is the slope. More at: https://cls.syr.edu/mathtuneup/grapha/Unit4/Unit4a.html double doubleSlope = (loadUniformValues.DoubleForceRight - loadUniformValues.DoubleForceLeft) / loadUniformValues.DoubleLoadLength; // Equation of a line is y=mx+b where m is the slope and b is the y-intercept. double doubleInterceptForce = loadUniformValues.DoubleForceLeft; // Save value for use below. double doubleInterceptPosition = loadUniformValues.DoublePositionLeft; // Save value for use below. double doubleLoadSegmentPositionLeft = loadUniformValues.DoublePositionLeft - loadUniformValues.DoubleSegmentLength; // Initialize value for first pass in next loop. double doubleSegmentPositionLeft; // Initialize value for first pass in next loop. double doubleSegmentForceLeft; // Initialize value for first pass in next loop. double doubleSegmentPositionRight = loadUniformValues.DoublePositionLeft; // Initialize value for first pass in next loop. double doubleSegmentForceRight = loadUniformValues.DoubleForceLeft; // Initialize value for first pass in next loop. //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): doubleSlope={doubleSlope}, doubleInterceptPosition={doubleInterceptPosition}, doubleInterceptForce={doubleInterceptForce}, loadUniformValues.DoubleSegmentLength={loadUniformValues.DoubleSegmentLength}"); for (int i = 0; i < loadUniformValues.IntNumberOfSegments; i++) { doubleSegmentPositionLeft = doubleSegmentPositionRight; doubleSegmentPositionRight = doubleSegmentPositionLeft + loadUniformValues.DoubleSegmentLength; doubleSegmentForceLeft = doubleSegmentForceRight; doubleSegmentForceRight = doubleSlope * (doubleSegmentPositionRight - doubleInterceptPosition) + doubleInterceptForce; //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Segment {i + 1} of {loadUniformValues.IntNumberOfSegments}: Line points are (doubleSegmentPositionLeft={doubleSegmentPositionLeft}, doubleSegmentForceLeft={doubleSegmentForceLeft}), (doubleSegmentPositionRight={doubleSegmentPositionRight}, doubleSegmentForceRight={doubleSegmentForceRight})"); doubleTriangleHeight = CalcTriangleHeight(doubleSegmentForceLeft, doubleSegmentForceRight); if (Abs(doubleSegmentForceLeft) > Abs(doubleSegmentForceRight)) { CalcCentroidValues(ref doubleArea, ref doubleCentroid, loadUniformValues.DoubleSegmentLength, doubleSegmentForceRight, doubleTriangleHeight, true); //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Abs(doubleSegmentForceLeft) > Abs(doubleSegmentForceRight), doubleArea={doubleArea}, doubleCentroid={doubleCentroid}"); } else { CalcCentroidValues(ref doubleArea, ref doubleCentroid, loadUniformValues.DoubleSegmentLength, doubleSegmentForceLeft, doubleTriangleHeight, false); //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Abs(doubleSegmentForceLeft) < Abs(doubleSegmentForceRight), doubleArea={doubleArea}, doubleCentroid={doubleCentroid}"); } doubleLoadSegmentPositionLeft += loadUniformValues.DoubleSegmentLength; doubleCentroid = doubleLoadSegmentPositionLeft + doubleCentroid; //Debug.WriteLine($"CommonItems.UniformLoadSimulate(): Applied sloping uniform loads {i + 1} of {loadUniformValues.IntNumberOfSegments}, doubleCentroid={doubleCentroid}, doubleArea={doubleArea}"); LoadConcentratedValues loadConcentratedValues = new LoadConcentratedValues { DoubleLoadConcentratedPosition = doubleCentroid, DoubleLoadConcentratedForce = doubleArea, DoubleLoadConcentratedMoment = 0d // Moment always zero if uniform load. }; loadUniformValues.ListSimulatedLoads.Add(loadConcentratedValues); } } } }