JWock82 / xlFrame

A free VBA library to make structural analysis easy in Microsoft Excel
MIT License
70 stars 21 forks source link

Member Internal Moment & Shear for Point Loads at Member Ends are Not Reported #3

Closed JWock82 closed 5 years ago

JWock82 commented 6 years ago

Describe the bug Member point loads and moments applied at x = 0 along the length of a member are not reported in member shear and moment results. This is because the results are always reported "looking to the left" (or "just to the right") of the cut. This causes the reaction and the point load to cancel each other out at x=0. This is rarely an issue, since it usually makes sense to apply these loads as nodal loads instead of member loads.

To Reproduce Steps to reproduce the behavior:

  1. Create a complete model with a support at x=0.
  2. Apply a member point load at x = 0 that will be resisted by the support.
  3. Solve the model.
  4. Request the shear force at x = 0.
  5. The shear force due to the point load will be left out, since the member end force and the point load are summed at this point, and they cancel each other out.

**Suggested Fix*** The fix is pretty simple: change the code to report member end forces at the starts and ends of members, rather than calculating the internal shear force or moment as you would away from the ends.

dmorchard commented 5 years ago

Hmmm... Consider this code, which defines a cantilever with it's free end at x=0...

Sub issue3()
'Investigating issue #3: https://github.com/JWock82/xlFrame/issues/3
    Dim myModel As New FEModel

'Define the nodes
    Call myModel.AddNode("N1", 0, 0)
    Call myModel.AddNode("N2", 5, 0)

'Define the members
    Call myModel.AddMember("M1", "N1", "N2", 1, 1, 1)

'Define the supports
    Call myModel.EditSupport("N2", True, True, True)

'Define member point loads
    Call myModel.AddMemberPointLoad("M1", 10, 0, Transverse)

'Results...
    With Sheet1
        .Cells.Clear
        .Range("B1") = "N1"
        .Range("C1") = "N2"
'Support reactions
        .Range("A2") = "FY"
        .Range("B2") = myModel.GetReaction("N1", FY)
        .Range("C2") = myModel.GetReaction("N2", FY)
'Support shear
        .Range("A3") = "V(x)"
        .Range("B3") = myModel.GetShear("M1", 0)
        .Range("C3") = myModel.GetShear("M1", 5)

'Get V(x) diagram
        .Range("A5") = "x"
        .Range("B5") = "V(x)"
        Call myModel.GetShearDiagram("M1").PrintEZArray(.Range("A6"))

    End With 'Sheet1
End Sub

...when graphed it looks right to me. image

Now shift the point load elsewhere... Call myModel.AddMemberPointLoad("M1", 10, 2, Transverse) ...and repeat... image

My interpretation of what's going on is that we are expecting a nice vertical step in V(x) at the location of applied P. In order to get that result we'd need two V(x) values at that single location, in this case V(2) = 0 and V(2) = -10, but xlFrame is hardwired to return shear values for 20 consecutive x-values.

In my own stiffness matrix solving spreadsheet I encountered this same issue, and in my diagram generating sub I resorted to spoon-feeding it all the extra V(x) and M(x) points necessary to get the diagrams to step properly. This included forcing it to evaluate at points of interest, i.e. at x=2 in my second attempt above. I found that the concept of singularity functions was particularly useful for this task and was going to suggest them as a feature request actually.

I haven't quite figured out what the segment class does in xlFrame, but my gut feeling is segmenting each member at points of interest like load locations, the roots of V(x) & M(x), etc. might have the desired effect.

JWock82 commented 5 years ago

That’s exactly what’s going on. Most commercial software I’ve used does this too. I believe STAAD and RISA both default to reporting member results at 10 intervals. While this is true for the force diagrams in xlFrame, if you request member maximum/minimum shears it uses exact equations derived from differentiation to identify the exact value.

xlFrame automatically divides each member into a series of mathematically continuous “segments”, bounded by loading discontinuities. There’s a function called "SegmentMember” in the “Member2D” class that takes care of this process and breaks the member into an array of segments. This allowed me to integrate the load, shear, moment, and slope diagrams to obtain exact results for each segment. I’ve documented how I did this so I wouldn’t forget going forward (see attached).

Sent from Mailhttps://go.microsoft.com/fwlink/?LinkId=550986 for Windows 10


From: dmorchard notifications@github.com Sent: Thursday, May 16, 2019 9:15:28 PM To: JWock82/xlFrame Cc: Craig; Author Subject: Re: [JWock82/xlFrame] Member Internal Moment & Shear for Point Loads at Member Ends are Not Reported (#3)

Hmmm... Consider this code, which defines a cantilever with it's free end at x=0...

Sub issue3() 'Investigating issue #3: https://github.com/JWock82/xlFrame/issues/3 Dim myModel As New FEModel

'Define the nodes Call myModel.AddNode("N1", 0, 0) Call myModel.AddNode("N2", 5, 0)

'Define the members Call myModel.AddMember("M1", "N1", "N2", 1, 1, 1)

'Define the supports Call myModel.EditSupport("N2", True, True, True)

'Define member point loads Call myModel.AddMemberPointLoad("M1", 10, 0, Transverse)

'Results... With Sheet1 .Cells.Clear .Range("B1") = "N1" .Range("C1") = "N2" 'Support reactions .Range("A2") = "FY" .Range("B2") = myModel.GetReaction("N1", FY) .Range("C2") = myModel.GetReaction("N2", FY) 'Support shear .Range("A3") = "V(x)" .Range("B3") = myModel.GetShear("M1", 0) .Range("C3") = myModel.GetShear("M1", 5)

'Get V(x) diagram .Range("A5") = "x" .Range("B5") = "V(x)" Call myModel.GetShearDiagram("M1").PrintEZArray(.Range("A6"))

End With 'Sheet1

End Sub

...when graphed it looks right to me. [image]https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F30359271%2F57899551-261af480-7823-11e9-8d97-d055788002bf.png&data=02%7C01%7C%7Ca0d9a92f724c46a2e1dc08d6da75e9fb%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636936597304775629&sdata=X5apWlQ15zwlGHenMYonCnERaRs3L8xudehNm3GN8Yw%3D&reserved=0

Now shift the point load elsewhere... Call myModel.AddMemberPointLoad("M1", 10, 2, Transverse) ...and repeat... [image]https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F30359271%2F57899667-8742c800-7823-11e9-89e8-4f9916217af4.png&data=02%7C01%7C%7Ca0d9a92f724c46a2e1dc08d6da75e9fb%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636936597304785640&sdata=2dNGS0Sd1Y4PIusEgwvVu18MgGxBj9FuoZHvR4aOU4U%3D&reserved=0

My interpretation of what's going on is that we are expecting a nice vertical step in V(x) at the location of applied P. In order to get that result we'd need two V(x) values at that single location, in this case V(2) = 0 and V(2) = -10, but xlFrame is hardwired to return shear values for 20 consecutive x-values.

In my own stiffness matrix solving spreadsheet I encountered this same issue, and in my diagram generating sub I resorted to spoon-feeding it all the extra V(x) and M(x) points necessary to get the diagrams to step properly. This included forcing it to evaluate at points of interest, i.e. at x=2 in my second attempt above. I found that the concept of singularity functionshttps://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FSingularity_function&data=02%7C01%7C%7Ca0d9a92f724c46a2e1dc08d6da75e9fb%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636936597304795651&sdata=xYif9q88zzARS4YrIoDs41%2FCBT%2FXIHcVE4crwVUSvN4%3D&reserved=0 was particularly useful for this task and was going to suggest them as a feature request actually.

I haven't quite figured out what the segment class does in xlFrame, but my gut feeling is segmenting each member at points of interest like load locations, the roots of V(x) & M(x), etc. might have the desired effect.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FJWock82%2FxlFrame%2Fissues%2F3%3Femail_source%3Dnotifications%26email_token%3DAH6HUEYSXMEGLIN7U7ELSIDPVYPNBA5CNFSM4GAWVFF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVTTPWI%23issuecomment-493303769&data=02%7C01%7C%7Ca0d9a92f724c46a2e1dc08d6da75e9fb%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636936597304805656&sdata=6QL3%2B89FUzrCvR9Ytb2kVgt5a8Tk%2FBRwc67g45j295A%3D&reserved=0, or mute the threadhttps://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAH6HUE7LE6QD25RMZGGWMNDPVYPNBANCNFSM4GAWVFFQ&data=02%7C01%7C%7Ca0d9a92f724c46a2e1dc08d6da75e9fb%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636936597304815661&sdata=Nhcqk7JazQ9zXcauuBJntst7VElq4HbUDIBzn%2FlJZkE%3D&reserved=0.

dmorchard commented 5 years ago

Not seeing your attached doc; just a link that takes me to a getting started page for Outlook.com. However, if I understand correctly then the shear diagram issue that caught my eye is something separate deserving of a feature request, i.e. Incorporate points associated with segment bounds into getShearDiagram. I'll start a new thread to that effect.

You mentioned RISA - do you have it? If so, good to know. It might be handy to pass R3D files back and forth from time to time. Also, on the topic of RISA - I've written a suite of VBA subs and functions that export any structure modeled in my stiffness matrix spreadsheet in RISA's R3D format. Gut feeling: it'd be really easy to do the same with xlFrame.

dmorchard commented 5 years ago

Further to issue #3... In your OP it was probably a simply-supported beam you had in mind, right? Altering my original code accordingly I'm getting V(0) = 0; same as you. However, I'm not so sure that's actually wrong...

Sub issue3()
'simply-supported, member point load @ N1
    Dim myModel As New FEModel
'Define the nodes
    Call myModel.AddNode("N1", 0, 0)
    Call myModel.AddNode("N2", 5, 0)
'Define the members
    Call myModel.AddMember("M1", "N1", "N2", 1, 1, 1)
'Define the supports
    Call myModel.EditSupport("N1", True, True, False)
    Call myModel.EditSupport("N2", False, True, False)
'Define member point loads
    Call myModel.AddMemberPointLoad("M1", 10, 0, Transverse)
'Results...
    With Sheet1
        .Cells.Clear
        .Range("B1") = "N1"
        .Range("C1") = "N2"
'Support reactions
        .Range("A2") = "FY"
        .Range("B2") = myModel.GetReaction("N1", FY)
        .Range("C2") = myModel.GetReaction("N2", FY)
'Support shear
        .Range("A3") = "V(x)"
        .Range("B3") = myModel.GetShear("M1", 0)
        .Range("C3") = myModel.GetShear("M1", 5)
'Get V(x) diagram
        .Range("A5") = "x"
        .Range("B5") = "V(x)"
        Call myModel.GetShearDiagram("M1").PrintEZArray(.Range("A6"))
    End With 'Sheet1
End Sub

image

Recreating it in RISA I get similar results: no value for shear at N1... image

...and also no difference if I swap the member point load for an equivalent nodal load in RISA... image

It seems to me that xlFrame's behavior is a perfect match to RISA's in this situation. That said, my professional focus being on engineering of lumber and timber I would be concerned about a wooden beam failing due to cross-grain crushing (a.k.a bearing failure) in this scenario, and perhaps you're thinking along similar lines. So indulge me as I reproduce this in Woodworks Sizer... full disclosure: I'm Canadian, as will be revealed if you read all the way to the design notes at the bottom of the Sizer output ;) Beam1.pdf

Like xlFrame and RISA, Sizer indicates no shear at x=0 (according to its shear diagram anyways), yet it has arrived at the conclusion that there is bearing failure, presumably based on the reaction force acting over the bearing area. Sizer, RISA and xlFrame are all reporting the reactions and shears identically, so I'm not so sure there's really anything going wrong here.

JWock82 commented 5 years ago

You're correct. You need a support at the load position to duplicate the error.

I think it's a common oversight in a lot of commercial software. They report results "looking at the left side" of the section cut, summing everything up to the cut. My background is primarily steel, and if the program reports 0 shear at the support it's ignoring the potential for web crippling. Reality is that the load has to go through the member to get to the support before the reaction cancels it out, and the program should indicate that. STAAD does it that way. I've actually fixed this problem on my local copy. I'll update the github code and close out this issue.

I've used both RISA and STAAD extensively, but I currently only have access to STAAD. I do want to be a little careful not to do anything that could be construed as reverse-engineering their software. I don't want to get into any legal trouble. I'm a little hesitant to use their software to validate ours. I've been sticking to textbook examples for testing.

Let me try that attachment again. Beam Equations.docx

JWock82 commented 5 years ago

Replaced Member2D.cls with a new version of the file that resolves this issue.

JWock82 commented 5 years ago

Also, I think your feature request is a good idea. I don't have time to take that on myself though. Take a look at those beam segment equations. They derive exactly which points to check for the max/min values. Those equations are used to get the max/min values, but are not yet implemented in the shear and moment diagrams. Until then, it still behaves on par with or better than most commercially available software I've seen.