|
################################### |
|
# Grid Girder Analysis |
|
################################### |
|
import numpy as np |
|
import sys |
|
import time |
|
|
|
def PRINP_FRM(fnameW,npoin,nele,nsec,npfix,nlod,ae,x,fp,mpfix,rdis,node,qw): |
|
fout=open(fnameW,'w') |
|
# print out of input data |
|
print('{0:>5s} {1:>5s} {2:>5s} {3:>5s} {4:>5s}'.format('npoin','nele','nsec','npfix','nlod'),file=fout) |
|
print('{0:5d} {1:5d} {2:5d} {3:5d} {4:5d}'.format(npoin,nele,nsec,npfix,nlod),file=fout) |
|
print('{0:>5s} {1:>15s} {2:>15s} {3:>15s} {4:>15s} {5:>15s}' |
|
.format('sec','E','po','A','I','J'),file=fout) |
|
for i in range(0,nsec): |
|
print('{0:5d} {1:15.7e} {2:15.7e} {3:15.7e} {4:15.7e} {5:15.7e}' |
|
.format(i+1,ae[0,i],ae[1,i],ae[2,i],ae[3,i],ae[4,i]),file=fout) |
|
print('{0:>5s} {1:>15s} {2:>15s} {3:>15s} {4:>15s} {5:>15s} {6:>5s} {7:>5s} {8:>5s}' |
|
.format('node','x','y','fx','fy','fz','kox','koy','koz'),file=fout) |
|
for i in range(0,npoin): |
|
lp=i+1 |
|
print('{0:5d} {1:15.7e} {2:15.7e} {3:15.7e} {4:15.7e} {5:15.7e} {6:5d} {7:5d} {8:5d}' |
|
.format(lp,x[0,i],x[1,i],fp[3*lp-3],fp[3*lp-2],fp[3*lp-1],mpfix[0,i],mpfix[1,i],mpfix[2,i]),file=fout) |
|
print('{0:>5s} {1:>5s} {2:>5s} {3:>5s} {4:>15s} {5:>15s} {6:>15s}' |
|
.format('node','kox','koy','koz','rdis_x','rdis_y','rdis_z'),file=fout) |
|
for i in range(0,npoin): |
|
if 0<mpfix[0,i]+mpfix[1,i]+mpfix[2,i]: |
|
lp=i+1 |
|
print('{0:5d} {1:5d} {2:5d} {3:5d} {4:15.7e} {5:15.7e} {6:15.7e}' |
|
.format(lp,mpfix[0,i],mpfix[1,i],mpfix[2,i],rdis[0,i],rdis[1,i],rdis[2,i]),file=fout) |
|
print('{0:>5s} {1:>5s} {2:>5s} {3:>5s} {4:>15s}'.format('elem','i','j','sec','qw'),file=fout) |
|
for ne in range(0,nele): |
|
print('{0:5d} {1:5d} {2:5d} {3:5d} {4:15.7e}'.format(ne+1,node[0,ne],node[1,ne],node[2,ne],qw[ne]),file=fout) |
|
fout.close() |
|
|
|
def PROUT_FRM(fnameW,npoin,nele,disg,fsec): |
|
fout=open(fnameW,'a') |
|
# displacement |
|
print('{0:>5s} {1:>15s} {2:>15s} {3:>15s}'.format('node','dis-x','dis-y','dis-z'),file=fout) |
|
for i in range(0,npoin): |
|
lp=i+1 |
|
print('{0:5d} {1:15.7e} {2:15.7e} {3:15.7e}'.format(lp,disg[3*lp-3],disg[3*lp-2],disg[3*lp-1]),file=fout) |
|
# section force |
|
print('{0:>5s} {1:>15s} {2:>15s} {3:>15s} {4:>15s} {5:>15s} {6:>15s}' |
|
.format('elem','T_i','M_i','Q_i','T_j','M_j','Q_j'),file=fout) |
|
for ne in range(0,nele): |
|
print('{0:5d} {1:15.7e} {2:15.7e} {3:15.7e} {4:15.7e} {5:15.7e} {6:15.7e}' |
|
.format(ne+1,fsec[0,ne],fsec[1,ne],fsec[2,ne],fsec[3,ne],fsec[4,ne],fsec[5,ne]),file=fout) |
|
fout.close() |
|
|
|
|
|
def SM_GRD(ne,node,x,ae): |
|
ek=np.zeros([6,6],dtype=np.float64) # local stiffness matrix |
|
tt=np.zeros([6,6],dtype=np.float64) # transformation matrix |
|
i=node[0,ne]-1 |
|
j=node[1,ne]-1 |
|
x1=x[0,i] |
|
y1=x[1,i] |
|
x2=x[0,j] |
|
y2=x[1,j] |
|
xx=x2-x1 |
|
yy=y2-y1 |
|
el=np.sqrt(xx**2+yy**2) |
|
m=node[2,ne]-1 |
|
ee=ae[0,m] |
|
po=ae[1,m] |
|
aa=ae[2,m] |
|
ai=ae[3,m] |
|
aj=ae[4,m] |
|
GJ=0.5*ee/(1.0+po)*aj |
|
EA=ee*aa |
|
EI=ee*ai |
|
ek[0,0]= GJ/el; ek[0,1]= 0.0; ek[0,2]= 0.0; ek[0,3]=-GJ/el; ek[0,4]= 0.0; ek[0,5]= 0.0 |
|
ek[1,0]= 0.0; ek[1,1]= 4*EI/el ; ek[1,2]= -6*EI/el**2; ek[1,3]= 0.0; ek[1,4]= 2*EI/el ; ek[1,5]= 6*EI/el**2 |
|
ek[2,0]= 0.0; ek[2,1]=-6*EI/el**2; ek[2,2]= 12*EI/el**3; ek[2,3]= 0.0; ek[2,4]=-6*EI/el**2; ek[2,5]=-12*EI/el**3 |
|
ek[3,0]=-GJ/el; ek[3,1]= 0.0; ek[3,2]= 0.0; ek[3,3]= GJ/el; ek[3,4]= 0.0; ek[3,5]= 0.0 |
|
ek[4,0]= 0.0; ek[4,1]= 2*EI/el ; ek[4,2]= -6*EI/el**2; ek[4,3]= 0.0; ek[4,4]= 4*EI/el ; ek[4,5]= 6*EI/el**2 |
|
ek[5,0]= 0.0; ek[5,1]= 6*EI/el**2; ek[5,2]=-12*EI/el**3; ek[5,3]= 0.0; ek[5,4]= 6*EI/el**2; ek[5,5]= 12*EI/el**3 |
|
s=yy/el |
|
c=xx/el |
|
tt[0,0]= c; tt[0,1]= s; tt[0,2]=0.0; tt[0,3]=0.0; tt[0,4]=0.0; tt[0,5]=0.0 |
|
tt[1,0]= -s; tt[1,1]= c; tt[1,2]=0.0; tt[1,3]=0.0; tt[1,4]=0.0; tt[1,5]=0.0 |
|
tt[2,0]=0.0; tt[2,1]=0.0; tt[2,2]=1.0; tt[2,3]=0.0; tt[2,4]=0.0; tt[2,5]=0.0 |
|
tt[3,0]=0.0; tt[3,1]=0.0; tt[3,2]=0.0; tt[3,3]= c; tt[3,4]= s; tt[3,5]=0.0 |
|
tt[4,0]=0.0; tt[4,1]=0.0; tt[4,2]=0.0; tt[4,3]= -s; tt[4,4]= c; tt[4,5]=0.0 |
|
tt[5,0]=0.0; tt[5,1]=0.0; tt[5,2]=0.0; tt[5,3]=0.0; tt[5,4]=0.0; tt[5,5]=1.0 |
|
return ek,tt |
|
|
|
|
|
def QWVEC_GRD(ne,node,x,qq): |
|
# Distributed vertical load vector |
|
qfe_g=np.zeros(6,dtype=np.float64) |
|
i=node[0,ne]-1 |
|
j=node[1,ne]-1 |
|
el=np.sqrt((x[0,j]-x[0,i])**2+(x[1,j]-x[1,i])**2) |
|
qfe_g[0]=0.0 |
|
qfe_g[1]=0.0 |
|
qfe_g[2]=0.5*qq*el |
|
qfe_g[3]=0.0 |
|
qfe_g[4]=0.0 |
|
qfe_g[5]=0.5*qq*el |
|
return qfe_g |
|
|
|
|
|
# Main routine |
|
start=time.time() |
|
args = sys.argv |
|
fnameR=args[1] # input data file |
|
fnameW=args[2] # output data file |
|
|
|
f=open(fnameR,'r') |
|
text=f.readline() |
|
text=text.strip() |
|
text=text.split() |
|
npoin=int(text[0]) # Number of nodes |
|
nele =int(text[1]) # Number of elements |
|
nsec =int(text[2]) # Number of sections |
|
npfix=int(text[3]) # Number of restricted nodes |
|
nlod =int(text[4]) # Number of loaded nodes |
|
nod=2 # Number of nodes per element |
|
nfree=3 # Degree of freedom per node |
|
n=nfree*npoin |
|
|
|
x =np.zeros([2,npoin],dtype=np.float64) # Coordinates of nodes |
|
ae =np.zeros([5,nsec],dtype=np.float64) # Section characteristics |
|
node =np.zeros([nod+1,nele],dtype=np.int) # Node-element relationship |
|
qw =np.zeros(nele,dtype=np.float64) # Uniformly distributed load per unit length |
|
fp =np.zeros(nfree*npoin,dtype=np.float64) # External force vector |
|
mpfix =np.zeros([nfree,npoin],dtype=np.int) # Ristrict conditions |
|
rdis =np.zeros([nfree,npoin],dtype=np.float64) # Ristricted displacement |
|
ir =np.zeros(nod*nfree,dtype=np.int) # Work vector for matrix assembly |
|
gk =np.zeros([n,n],dtype=np.float64) # Global stiffness matrix |
|
fsec =np.zeros([nod*nfree,nele],dtype=np.float64) # Section force vector |
|
work =np.zeros(nod*nfree,dtype=np.float64) # work vector for section force calculation |
|
|
|
# section characteristics |
|
for i in range(0,nsec): |
|
text=f.readline() |
|
text=text.strip() |
|
text=text.split() |
|
ae[0,i]=float(text[0]) # E : Elastic modulus |
|
ae[1,i]=float(text[1]) # po : Poisson's ratio |
|
ae[2,i]=float(text[2]) # AA : Section area |
|
ae[3,i]=float(text[3]) # AI : Moment of inertia |
|
ae[4,i]=float(text[4]) # AJ : Tortional constant |
|
# element-node |
|
for i in range(0,nele): |
|
text=f.readline() |
|
text=text.strip() |
|
text=text.split() |
|
node[0,i]=int(text[0]) #node_1 |
|
node[1,i]=int(text[1]) #node_2 |
|
node[2,i]=int(text[2]) #section characteristic number |
|
qw[i]=float(text[3]) #uniformly distributed vertical load |
|
# node coordinates |
|
for i in range(0,npoin): |
|
text=f.readline() |
|
text=text.strip() |
|
text=text.split() |
|
x[0,i]=float(text[0]) # x-coordinate |
|
x[1,i]=float(text[1]) # y-coordinate |
|
# boundary conditions (0:free, 1:restricted) |
|
for i in range(0,npfix): |
|
text=f.readline() |
|
text=text.strip() |
|
text=text.split() |
|
lp=int(text[0]) #fixed node |
|
mpfix[0,lp-1]=int(text[1]) #index of restriction for tortional rotation |
|
mpfix[1,lp-1]=int(text[2]) #index of restriction for bending rotation |
|
mpfix[2,lp-1]=int(text[3]) #index of restriction for vertical displacement |
|
rdis[0,lp-1]=float(text[4]) #given tortional rotation |
|
rdis[1,lp-1]=float(text[5]) #given bending rotation |
|
rdis[2,lp-1]=float(text[6]) #given vertical displacement |
|
# load |
|
if 0<nlod: |
|
for i in range(0,nlod): |
|
text=f.readline() |
|
text=text.strip() |
|
text=text.split() |
|
lp=int(text[0]) #loaded node |
|
fp[3*lp-3]=float(text[1]) #tortional moment load |
|
fp[3*lp-2]=float(text[2]) #bending moment load |
|
fp[3*lp-1]=float(text[3]) #vertical load |
|
f.close() |
|
|
|
PRINP_FRM(fnameW,npoin,nele,nsec,npfix,nlod,ae,x,fp,mpfix,rdis,node,qw) |
|
|
|
# assembly of stiffness matrix & load vectors |
|
for ne in range(0,nele): |
|
ek,tt=SM_GRD(ne,node,x,ae) # Stiffness matrix in local coordinate |
|
ck =np.dot(np.dot(tt.T,ek),tt) # Stiffness matrix in global coordinate |
|
qfe_g=QWVEC_GRD(ne,node,x,qw[ne]) # Distributed vertical load vector |
|
i=node[0,ne]-1 |
|
j=node[1,ne]-1 |
|
ir[5]=3*j+2; ir[4]=ir[5]-1; ir[3]=ir[4]-1 |
|
ir[2]=3*i+2; ir[1]=ir[2]-1; ir[0]=ir[1]-1 |
|
for i in range(0,nod*nfree): |
|
it=ir[i] |
|
fp[it]=fp[it]+qfe_g[i] |
|
for j in range(0,nod*nfree): |
|
jt=ir[j] |
|
gk[it,jt]=gk[it,jt]+ck[i,j] |
|
|
|
# treatment of boundary conditions |
|
for i in range(0,npoin): |
|
for j in range(0,nfree): |
|
if mpfix[j,i]==1: |
|
iz=i*nfree+j |
|
fp[iz]=0.0 |
|
for k in range(0,n): |
|
fp[k]=fp[k]-rdis[j,i]*gk[k,iz] |
|
gk[k,iz]=0.0 |
|
gk[iz,iz]=1.0 |
|
|
|
# solution of simultaneous linear equations |
|
disg = np.linalg.solve(gk, fp) |
|
|
|
# recovery of restricted displacements |
|
for i in range(0,npoin): |
|
for j in range(0,nfree): |
|
if mpfix[j,i]==1: |
|
iz=i*nfree+j |
|
for k in range(0,n): |
|
disg[iz]=rdis[j,i] |
|
|
|
# calculation of section force |
|
for ne in range(0,nele): |
|
ek,tt=SM_GRD(ne,node,x,ae) |
|
i=node[0,ne]-1 |
|
j=node[1,ne]-1 |
|
work[0]=disg[3*i]; work[1]=disg[3*i+1]; work[2]=disg[3*i+2] |
|
work[3]=disg[3*j]; work[4]=disg[3*j+1]; work[5]=disg[3*j+2] |
|
fsec[:,ne]=np.dot(ek,np.dot(tt,work)) |
|
|
|
|
|
PROUT_FRM(fnameW,npoin,nele,disg,fsec) |
|
|
|
dtime=time.time()-start |
|
print('n={0} time={1:.3f}'.format(n,dtime)+' sec') |
|
fout=open(fnameW,'a') |
|
print('n={0} time={1:.3f}'.format(n,dtime)+' sec',file=fout) |
|
fout.close() |