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]:
table = pd.read_csv(filename('nodes'))
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]:
table = pd.read_csv(filename('members'))
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:
    lctable = pd.read_csv(filename('load_combinations'))
    use_all = False
    COMBO = {}
    for i,row in lctable.iterrows():
        if row.CASE == lcase:
            COMBO[row.LOAD.lower()] = row.FACTOR
except OSError:
    use_all = True
    COMBO = None
COMBO

In [8]:
table = pd.read_csv(filename('node_loads'))
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 [10]:
try:
    table = pd.read_csv(filename('pdelta_forces',lcase))
    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 [11]:
table = pd.read_csv(filename('reaction_forces',lcase))
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[11]:
NODEID FX FY MZ
0 A -3625.020453 989141.474477 6.332451e+07
1 D -69040.008304 1060858.525523 2.057977e+08
2 I -2744.482817 500000.000000 NaN
3 J -2368.101512 500000.000000 NaN

4 rows × 4 columns


In [12]:
mtable = pd.read_csv(filename('member_end_forces',lcase))
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[12]:
MEMBERID FXJ FYJ MZJ FXK FYK MZK
0 AB 989141.474477 3625.020453 6.332451e+07 -989141.474477 -3625.020453 -3.976188e+07
1 BC 450829.917117 -86071.539660 -2.365727e+08 -450829.917117 86071.539660 -2.368208e+08
2 DE 1060858.525523 69040.008304 2.057977e+08 -1060858.525523 -69040.008304 2.429624e+08
3 EF 471670.082883 117583.181532 3.004759e+08 -471670.082883 -117583.181532 3.462316e+08
4 IG 500000.000000 2744.482817 4.639151e-08 -500000.000000 -2744.482817 1.783914e+07
5 GH 225000.000000 -3243.479692 -1.783914e+07 -225000.000000 3243.479692 1.173612e-08
6 JK 500000.000000 2368.101512 3.059540e-09 -500000.000000 -2368.101512 1.539266e+07
7 KL 225000.000000 -2798.665423 -1.539266e+07 -225000.000000 2798.665423 1.389708e-08
8 CF 90673.363911 225829.917117 2.368208e+08 -90673.363911 246670.082883 -3.462316e+08
9 BE -90621.641809 263311.557360 2.763346e+08 90621.641809 314188.442640 -5.434382e+08
10 FH -25712.591580 225000.000000 0.000000e+00 25712.591580 225000.000000 0.000000e+00
11 EG -38911.114770 275000.000000 0.000000e+00 38911.114770 275000.000000 0.000000e+00
12 KB -3738.873400 275000.000000 0.000000e+00 3738.873400 275000.000000 0.000000e+00
13 LC 3399.701061 225000.000000 0.000000e+00 -3399.701061 225000.000000 0.000000e+00

14 rows × 7 columns


In [13]:
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[13]:
(1060858.52552286, 543438242.58540702)

In [14]:
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[14]:
sumFX sumFY sumMZ
ID
K 0 0 0
J 0 0 0
F 0 0 0
B 0 0 0
H 0 0 0
C 0 0 0
D 0 0 0
E 0 0 0
L 0 0 0
A 0 0 0
G 0 0 0
I 0 0 0

12 rows × 3 columns


In [15]:
sums.abs().max()


Out[15]:
sumFX    0
sumFY    0
sumMZ    0
dtype: float64

In [ ]: