## Check Member End Forces

This notebook reads files describing a structure, and the files output by Frame2D after an analysis, and checks that the member end forces computed here from the displacements and member loads agree with those computed by Frame2D.

It does this in the simplest way possible, using quite different logic than Frame2D, resulting in a higher degree of confidence in the results. It would have been better had someone else programmed it, but oh well ...

``````

In [1]:

ds = 'KG82'
lcase = 'all'
#ds = 'l22x6'
#lcase = 'Case-2b'

def filename(basename,lc=None):
if lc is not None:
basename = lc + '/' + basename
return 'data/' + ds + '.d/' + basename + '.csv'

def Warn(msg):
print('!!!!! Warning: {}'.format(msg))

``````
``````

In [2]:

import pandas as pd
import math

``````
``````

In [3]:

class Node(object):

def __init__(self,id,x,y):
self.id = id
self.x = x
self.y = y
self.deltaX = 0.
self.deltaY = 0.
self.thetaZ = 0.

``````
``````

In [4]:

NODES = {}
for i,n in ntable.iterrows():
if n.NODEID in NODES:
Warn("Node '{}' is multiply defined.".format(n.NODEID))
NODES[n.NODEID] = Node(n.NODEID,float(n.X),float(n.Y))
#ntable

``````
``````

In [5]:

for i,n in dtable.iterrows():
node = NODES[n.NODEID]
node.deltaX = float(n.DX)
node.deltaY = float(n.DY)
node.thetaZ = float(n.RZ)
dtable

``````
``````

Out[5]:

.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

text-align: right;
}

NODEID
DX
DY
RZ

0
A
0.000000
0.000000
0.000000

1
B
26.392119
-2.613585
-0.007546

2
C
41.058763
-3.621538
-0.007561

3
D
0.000000
0.000000
0.000000

4
E
26.744537
-2.803081
0.002720

5
F
40.706144
-3.857628
0.005554

6
G
26.888652
-1.321138
-0.003266

7
H
40.801376
-1.824187
-0.002161

8
I
0.000000
0.000000
-0.004572

9
J
0.000000
0.000000
-0.004434

10
K
26.378272
-1.321138
-0.003307

11
L
41.071354
-1.824187
-0.002354

``````
``````

In [6]:

pd.DataFrame([vars(v) for v in NODES.values()]).set_index('id')

``````
``````

Out[6]:

.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

text-align: right;
}

deltaX
deltaY
thetaZ
x
y

id

A
0.000000
0.000000
0.000000
10000.0
0.0

B
26.392119
-2.613585
-0.007546
10000.0
6500.0

C
41.058763
-3.621538
-0.007561
10000.0
12000.0

D
0.000000
0.000000
0.000000
20500.0
0.0

E
26.744537
-2.803081
0.002720
20500.0
6500.0

F
40.706144
-3.857628
0.005554
20500.0
12000.0

G
26.888652
-1.321138
-0.003266
30500.0
6500.0

H
40.801376
-1.824187
-0.002161
30500.0
12000.0

I
0.000000
0.000000
-0.004572
30500.0
0.0

J
0.000000
0.000000
-0.004434
0.0
0.0

K
26.378272
-1.321138
-0.003307
0.0
6500.0

L
41.071354
-1.824187
-0.002354
0.0
12000.0

``````
``````

In [7]:

class Member(object):

E = 200000.

def __init__(self,id,nodej,nodek):
self.id = id
self.nodej = nodej
self.nodek = nodek

dx = nodek.x - nodej.x
dy = nodek.y - nodej.y
self.L = L = math.sqrt(dx*dx + dy*dy)
self.cosx = dx/L
self.cosy = dy/L

self.Ix = 0.
self.A = 0.
self.releases = set()

for a in 'FXJ FXK FYJ FYK MZJ MZK'.split():
setattr(self,a,0.)

``````
``````

In [8]:

MEMBERS = {}
for i,m in table.iterrows():
if m.MEMBERID in MEMBERS:
Warn("Member '{}' is multiply defined.".format(m.MEMBERID))
MEMBERS[m.MEMBERID] = Member(m.MEMBERID,NODES[m.NODEJ],NODES[m.NODEK])

``````
``````

In [9]:

import sst
SST = sst.SST()
defIx = defA = None
for i,row in table.iterrows():
if not pd.isnull(row.SIZE):
defIx,defA = SST.section(row.SIZE,'Ix,A')
memb = MEMBERS[row.MEMBERID]
memb.Ix = float(defIx if pd.isnull(row.IX) else row.IX)
memb.A = float(defA if pd.isnull(row.A) else row.A)
if not pd.isnull(row.IX):
defIx = row.IX
if not pd.isnull(row.A):
defA = row.A

``````
``````

In [10]:

try:
use_all = False
COMBO = {}
for i,row in lctable.iterrows():
if row.CASE == lcase:
except OSError:
use_all = True
COMBO = None
COMBO

``````
``````

In [11]:

for i,row in table.iterrows():
memb = MEMBERS[row.MEMBERID]
typ = row.TYPE
f = 1.0 if use_all else COMBO.get(row.LOAD.lower(),0.)
if f != 0.:
w1 = None if pd.isnull(row.W1) else (float(row.W1)*f)
w2 = None if pd.isnull(row.W2) else (float(row.W2)*f)
a = None if pd.isnull(row.A) else float(row.A)
b = None if pd.isnull(row.B) else float(row.B)
c = None if pd.isnull(row.C) else float(row.C)

``````
``````

In [12]:

for i,row in table.iterrows():
memb = MEMBERS[row.MEMBERID]

``````
``````

In [13]:

t = pd.DataFrame([vars(v) for v in MEMBERS.values()]).set_index('id')
del t['nodej']
del t['nodek']
t

``````
``````

Out[13]:

.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

text-align: right;
}

A
FXJ
FXK
FYJ
FYK
Ix
L
MZJ
MZK
cosx
cosy
releases

id

AB
12300.0
0.0
0.0
0.0
0.0
222000000.0
6500.0
0.0
0.0
0.0
1.0
{}

BC
12300.0
0.0
0.0
0.0
0.0
222000000.0
5500.0
0.0
0.0
0.0
1.0
{}

DE
12300.0
0.0
0.0
0.0
0.0
222000000.0
6500.0
0.0
0.0
0.0
1.0
{}

EF
12300.0
0.0
0.0
0.0
0.0
222000000.0
5500.0
0.0
0.0
0.0
1.0
{}

IG
12300.0
0.0
0.0
0.0
0.0
222000000.0
6500.0
0.0
0.0
0.0
1.0
{}

GH
12300.0
0.0
0.0
0.0
0.0
222000000.0
5500.0
0.0
0.0
0.0
1.0
{}

JK
12300.0
0.0
0.0
0.0
0.0
222000000.0
6500.0
0.0
0.0
0.0
1.0
{}

KL
12300.0
0.0
0.0
0.0
0.0
222000000.0
5500.0
0.0
0.0
0.0
1.0
{}

CF
13500.0
0.0
0.0
0.0
0.0
488000000.0
10500.0
0.0
0.0
1.0
0.0
{}

BE
13500.0
0.0
0.0
0.0
0.0
488000000.0
10500.0
0.0
0.0
1.0
0.0
{}

FH
13500.0
0.0
0.0
0.0
0.0
488000000.0
10000.0
0.0
0.0
1.0
0.0
{MZJ, MZK}

EG
13500.0
0.0
0.0
0.0
0.0
488000000.0
10000.0
0.0
0.0
1.0
0.0
{MZJ, MZK}

KB
13500.0
0.0
0.0
0.0
0.0
488000000.0
10000.0
0.0
0.0
1.0
0.0
{MZJ, MZK}

LC
13500.0
0.0
0.0
0.0
0.0
488000000.0
10000.0
0.0
0.0
1.0
0.0
{MZJ, MZK}

``````
``````

In [14]:

MEFS

``````
``````

Out[14]:

.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

text-align: right;
}

FXJ
FYJ
MZJ
FXK
FYK
MZK

MEMBERID

AB
9.891415e+05
3625.020453
6.332451e+07
-9.891415e+05
-3625.020453
-3.976188e+07

BC
4.508299e+05
-86071.539660
-2.365727e+08
-4.508299e+05
86071.539660
-2.368208e+08

DE
1.060859e+06
69040.008304
2.057977e+08
-1.060859e+06
-69040.008304
2.429624e+08

EF
4.716701e+05
117583.181532
3.004759e+08
-4.716701e+05
-117583.181532
3.462316e+08

IG
5.000000e+05
2744.482817
2.980232e-08
-5.000000e+05
-2744.482817
1.783914e+07

GH
2.250000e+05
-3243.479692
-1.783914e+07
-2.250000e+05
3243.479692
0.000000e+00

JK
5.000000e+05
2368.101512
1.490116e-08
-5.000000e+05
-2368.101512
1.539266e+07

KL
2.250000e+05
-2798.665423
-1.539266e+07
-2.250000e+05
2798.665423
0.000000e+00

CF
9.067336e+04
225829.917117
2.368208e+08
-9.067336e+04
246670.082883
-3.462316e+08

BE
-9.062164e+04
263311.557360
2.763346e+08
9.062164e+04
314188.442640
-5.434382e+08

FH
-2.571259e+04
225000.000000
0.000000e+00
2.571259e+04
225000.000000
0.000000e+00

EG
-3.891111e+04
275000.000000
0.000000e+00
3.891111e+04
275000.000000
0.000000e+00

KB
-3.738873e+03
275000.000000
0.000000e+00
3.738873e+03
275000.000000
0.000000e+00

LC
3.399701e+03
225000.000000
0.000000e+00
-3.399701e+03
225000.000000
0.000000e+00

``````
``````

In [15]:

cols = 'FXJ FXK FYJ FYK MZJ MZK'.split()
for m in MEMBERS.values():
for a in cols:
setattr(m,a,0.)

# difference in end displacements, global coords
dX = m.nodek.deltaX - m.nodej.deltaX
dY = m.nodek.deltaY - m.nodej.deltaY

# axial deformation / force:
ldX = dX*m.cosx + dY*m.cosy
T = m.E*m.A*ldX/m.L
m.FXK += T
m.FXJ += -T
#print(m.id,ldX,T)

# shear deformation / force:
vdY = dY*m.cosx - dX*m.cosy
M = -6.*m.E*m.Ix*vdY/(m.L*m.L)
V = 2.*M/m.L
m.MZJ += M
m.MZK += M
m.FYJ += V
m.FYK += -V
#print(m.id,vdY,M,V)

# end rotations / moments:
MJ = (m.E*m.Ix/m.L)*(4.*m.nodej.thetaZ + 2.*m.nodek.thetaZ)
MK = (m.E*m.Ix/m.L)*(2.*m.nodej.thetaZ + 4.*m.nodek.thetaZ)
VJ = (MJ+MK)/m.L
m.MZJ += MJ
m.MZK += MK
m.FYJ += VJ
m.FYK += -VJ
#print(m.id,m.nodej.thetaZ,m.nodek.thetaZ,MJ,MK,VJ)

# applied loads: fixed-end moments and shears:
mj = mk = 0.
vj = vk = 0.
if ltype == 'PL':
b = m.L - a
P = w1
mj = -P*a*b*b/(m.L*m.L)
mk = P*b*a*a/(m.L*m.L)
vj = (-P*b + nj + mk)/m.L
vk = -P - vj
elif ltype == 'UDL':
mj = -w1*m.L**2/12.
mk = -mj
vj = -w1*m.L/2.
vk = vj
else:
Warn("Load type '{}' not implemented here ...".format(ltype))
continue
m.MZJ += mj
m.MZK += mk
m.FYJ += vj
m.FYK += vk

# member end moment releases:
relc = m.releases.copy()
if 'MZJ' in m.releases:
mj = -m.MZJ
mk = 0. if 'MZK' in m.releases else 0.5*mj
vj = (mj + mk)/m.L
##print(m.id,'MZJ',m.MZJ,m.MZK,mj,mk,rel)
m.MZJ += mj
m.MZK += mk
m.FYJ += vj
m.FYK += -vj
relc.remove('MZJ')
if 'MZK' in m.releases:
mk = -m.MZK
mj = 0. if 'MZJ' in m.releases else 0.5*mk
vj = (mj + mk)/m.L
##print(m.id,'MZK',m.MZJ,m.MZK,mj,mk,rel)
m.MZJ += mj
m.MZK += mk
m.FYJ += vj
m.FYK += -vj
relc.remove('MZK')
if relc:
Warn("Member end-releases not processed: {}".format(relc))

``````
``````

In [16]:

computed = pd.DataFrame([{k:getattr(m,k) for k in ['id']+cols}
for m in MEMBERS.values()]).set_index('id')
diff = (computed - MEFS[cols])
lim = 1E-12
for c in cols:
biggest = MEFS[c].abs().max()
diff[c][diff[c].abs() < biggest*lim] = 0
diff

``````
``````

Out[16]:

.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

text-align: right;
}

FXJ
FXK
FYJ
FYK
MZJ
MZK

id

AB
0.0
0.0
0.0
0.0
0.0
0.0

BC
0.0
0.0
0.0
0.0
0.0
0.0

DE
0.0
0.0
0.0
0.0
0.0
0.0

EF
0.0
0.0
0.0
0.0
0.0
0.0

IG
0.0
0.0
0.0
0.0
0.0
0.0

GH
0.0
0.0
0.0
0.0
0.0
0.0

JK
0.0
0.0
0.0
0.0
0.0
0.0

KL
0.0
0.0
0.0
0.0
0.0
0.0

CF
0.0
0.0
0.0
0.0
0.0
0.0

BE
0.0
0.0
0.0
0.0
0.0
0.0

FH
0.0
0.0
0.0
0.0
0.0
0.0

EG
0.0
0.0
0.0
0.0
0.0
0.0

KB
0.0
0.0
0.0
0.0
0.0
0.0

LC
0.0
0.0
0.0
0.0
0.0
0.0

``````
``````

In [17]:

diff.abs().max()

``````
``````

Out[17]:

FXJ    0.0
FXK    0.0
FYJ    0.0
FYK    0.0
MZJ    0.0
MZK    0.0
dtype: float64

``````

### Maximum relative differences

``````

In [18]:

diff = (computed - MEFS[cols])
for c in cols:
biggest = MEFS[c].abs().max()
r = (diff[c]/biggest)
idr = r.abs().idxmax()
print(c,idr,r[idr])

``````
``````

FXJ FH 1.1937316732449982e-14
FXK FH -1.1937316732449982e-14
FYJ EF 1.1641532182693482e-15
FYK EF -1.0189494315398125e-15
MZJ GH 1.7109195840949047e-15
MZK EF 9.871256031345683e-16

``````
``````

In [ ]:

``````