## Check Equilibrium

This notebook reads files describing a structure, and the files output by Frame2D after an analysis, and checks that the forces and moments on every node are in equilibrium.

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.sumFX = 0.
self.sumFY = 0.
self.sumMZ = 0.

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

In [4]:

NODES = {}
for i,n in table.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))

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

In [5]:

class Member(object):

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

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

In [6]:

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 [7]:

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

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

In [8]:

for i,p in table.iterrows():
f = 1.0 if use_all else COMBO.get(p.LOAD.lower(),0.)
dirn = p.DIRN.upper()
if dirn in ['FX','FY','MZ']:
n = NODES[p.NODEID]
a = 'sum'+dirn
setattr(n,a,getattr(n,a,0.)+float(p.F)*f)
else:
Warn("Direction '{}' invalid for node '{}'.".format(dirn,p.NODEID))

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

In [9]:

try:
for i,p in table.iterrows():
n = NODES[p.NODEID]
n.sumFX += p.FX
n.sumFY += p.FY
n.sumMZ += p.MZ
except OSError:
pass

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

In [10]:

for i,r in table.iterrows():
n = NODES[r.NODEID]
n.sumFX += 0. if pd.isnull(r.FX) else float(r.FX)
n.sumFY += 0. if pd.isnull(r.FY) else float(r.FY)
n.sumMZ += 0. if pd.isnull(r.MZ) else float(r.MZ)
table

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

Out[10]:

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

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

text-align: right;
}

NODEID
FX
FY
MZ

0
A
-3625.020453
9.891415e+05
6.332451e+07

1
D
-69040.008304
1.060859e+06
2.057977e+08

2
I
-2744.482817
5.000000e+05
NaN

3
J
-2368.101512
5.000000e+05
NaN

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

In [11]:

for i,row in mtable.iterrows():
m = MEMBERS[row.MEMBERID]
n = m.nodej
n.sumFX -= row.FXJ*m.cosx - row.FYJ*m.cosy
n.sumFY -= row.FXJ*m.cosy + row.FYJ*m.cosx
n.sumMZ -= row.MZJ
n = m.nodek
n.sumFX -= row.FXK*m.cosx - row.FYK*m.cosy
n.sumFY -= row.FXK*m.cosy + row.FYK*m.cosx
n.sumMZ -= row.MZK
mtable

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

Out[11]:

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

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

text-align: right;
}

MEMBERID
FXJ
FYJ
MZJ
FXK
FYK
MZK

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

In [12]:

maxF = max([mtable[c].abs().max() for c in 'FXJ FXK FYJ FYK'.split()])
maxM = max([mtable[c].abs().max() for c in 'MZJ MZK'.split()])
maxF,maxM

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

Out[12]:

(1060858.52552286, 543438242.585413)

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

In [13]:

sums = pd.DataFrame([(n.id,n.sumFX,n.sumFY,n.sumMZ) for n in NODES.values()],
columns=['ID','sumFX','sumFY','sumMZ']).set_index(['ID'])
sums

lm = 1E-11
sums['sumFX'][sums['sumFX'].abs() <= maxF*lm] = 0
sums['sumFY'][sums['sumFY'].abs() <= maxF*lm] = 0
sums['sumMZ'][sums['sumMZ'].abs() <= maxM*lm] = 0
sums

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

Out[13]:

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

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

text-align: right;
}

sumFX
sumFY
sumMZ

ID

A
0.0
0.0
0.0

B
0.0
0.0
0.0

C
0.0
0.0
0.0

D
0.0
0.0
0.0

E
0.0
0.0
0.0

F
0.0
0.0
0.0

G
0.0
0.0
0.0

H
0.0
0.0
0.0

I
0.0
0.0
0.0

J
0.0
0.0
0.0

K
0.0
0.0
0.0

L
0.0
0.0
0.0

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

In [14]:

sums.abs().max()

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

Out[14]:

sumFX    0.0
sumFY    0.0
sumMZ    0.0
dtype: float64

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

In [ ]:

``````