PyFlex  1.0
Riser cross section analysis
axisymmetric.py
Go to the documentation of this file.
1 import numpy as np
2 import collections
3 import itertools
4 
5 
6 
7 def solver(layerinfo,r,t,b,A,alpha,n,E,nu,gap_ini,intpresslayer,extpresslayer
8  , T_eff, p_int, p_ext):
9 
10  # calculation section
11  # setting up the equation system
12  K,R,eps11index,u3index,deltatindex,pindex,fillfactor_in,fillfactor_out = systemsetup(r,t,b,A,n,E,nu,alpha,gap_ini,intpresslayer,extpresslayer,layerinfo,T_eff,p_int,p_ext)
13  solution=np.linalg.solve(K,R)
14 
15  np.savetxt('k.csv', K, fmt='%.18e', delimiter=',', newline='\n')
16  np.savetxt('solution.csv', solution[:,0], fmt='%.18e', delimiter=',', newline='\n')
17  np.savetxt('r.csv', R[:,0], fmt='%.18e', delimiter=',', newline='\n')
18 
19  Nlayers=len(layerinfo)
20  # correcting the solution if there should be gaps
21  solution=corrector(r,t,b,A,n,E,nu,alpha,gap_ini,intpresslayer,extpresslayer,layerinfo,T_eff,p_int,p_ext,solution,pindex,Nlayers)
22 
23  # finding the stresses
24  stress=np.zeros((Nlayers,len(T_eff),3))
25  for i in range(Nlayers):
26  if layerinfo[i]=='wires':
27  stress[i,:,0]=solution[i,:]*E[i]
28  if i>0:
29  stress[i,:,0]+=nu[i]*solution[pindex+i,:]/(2.0*fillfactor_in[i])
30  if i<Nlayers-1:
31  stress[i,:,0]+=nu[i]*solution[pindex+1+i,:]/(2.0*fillfactor_out[i])
32  if i== intpresslayer:
33  stress[i,:,0]+=nu[i]*p_int/(2.0*fillfactor_in[i])
34  if i== extpresslayer:
35  stress[i,:,0]+=nu[i]*p_ext/(2.0*fillfactor_out[i])
36  stress[i,:,1]=0.0
37  stress[i,:,2]=solution[deltatindex+i,:]/t[i]*E[i]-nu[i]*stress[i,:,0]
38 
39  elif layerinfo[i]=='sheath':
40  router=r[i]+t[i]/2.0
41  rinner=r[i]-t[i]/2.0
42  #Finding coefficients from standard thick shell solution (https://en.wikipedia.org/wiki/Cylinder_stress)
43  if i>0:
44  stress[i,:,1]+=(solution[pindex+i+1,:]*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
45  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) +
46  solution[pindex+i,:]*(r[i]-t[i]/2.0)**2
47  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
48  stress[i,:,2]+=(-solution[pindex+i,:]*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
49  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) +
50  solution[pindex+i,:]*(r[i]-t[i]/2.0)**2
51  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
52 
53  if i< Nlayers-1:
54  stress[i,:,1]+=(-solution[pindex+i+1,:]*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
55  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) -
56  solution[pindex+i,:]*(r[i]+t[i]/2.0)**2
57  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
58  stress[i,:,2]+=(solution[pindex+i+1,:]*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
59  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) -
60  solution[pindex+i,:]*(r[i]+t[i]/2.0)**2
61  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
62  if i==intpresslayer:
63  stress[i,:,1]+=(p_int*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
64  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) +
65  p_int*(r[i]-t[i]/2.0)**2
66  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
67  stress[i,:,2]+=(-p_int*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
68  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) +
69  p_int*(r[i]-t[i]/2.0)**2
70  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
71  if i== extpresslayer:
72  stress[i,:,1]+=(-p_ext*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
73  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) -
74  p_ext*(r[i]+t[i]/2.0)**2
75  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
76  stress[i,:,2]+=(p_ext*(r[i]+t[i]/2.0)**2*(r[i]-t[i]/2.0)**2
77  / (((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2)*r[i]**2) -
78  p_ext*(r[i]+t[i]/2.0)**2
79  /((r[i]+t[i]/2.0)**2-(r[i]-t[i]/2.0)**2))
80 
81  stress[i,:,0]+=E[i]*solution[-1,:]+nu[i]*(stress[i,:,1]+stress[i,:,2])
82 
83  contpress=np.zeros((len(T_eff),Nlayers))
84  contpress[:,1:]=solution[pindex+1:pindex+Nlayers].T
85  axialstress = stress[:,:,0].T
86  hoopstress = stress[:,:,1].T
87  radialstress= stress[:,:,2].T
88  # printout for testing
89  np.savetxt('stress.csv', stress[:,:,0], fmt='%.18e', delimiter=',', newline='\n')
90  np.savetxt('contpress.csv', contpress.T, fmt='%.18e', delimiter=',', newline='\n')
91  np.savetxt('finalsolution.csv', solution[:,-1], fmt='%.18e', delimiter=',', newline='\n')
92  return axialstress,hoopstress,radialstress,contpress
93 
94 
95 def combfinder(combinations):
96  sol=[]
97  for i in range(1,len(combinations)+1):
98  sol.append(itertools.combinations(combinations,i))
99  return sol
100 
101 def systemsetup(r,t,b,A,n,E,nu,alpha,gap_ini,intpresslayer,extpresslayer,layerinfo,T_eff,p_int,p_ext,gaplayers=[0]):
102  # finding constants and setting up matrices and counters
103  fillfactor_in=n*b/(2*np.pi*(r-t)*np.cos(alpha))
104  fillfactor_out=n*b/(2*np.pi*(r+t)*np.cos(alpha))
105  Nlayers=len(E)
106 
107  linecounter=0
108  presscounter=1
109  temp=collections.Counter(layerinfo)
110  Nhelic=temp['wires']
111  Nsheath=temp['sheath']
112  eps11index=0
113  u3index=Nhelic
114  deltatindex=Nhelic+Nlayers
115  pindex=Nhelic+2*Nlayers-1
116  ihelic=-1
117 
118  if gaplayers==[0]:
119  layersequence=[(0,Nlayers)]
120  nequations=Nhelic*4+3*Nsheath
121  else:
122  tmp=list(gaplayers)
123  nequations=Nhelic*4+3*Nsheath-len(gaplayers)
124  layersequence=[]
125  layersequence.append((0,tmp[0]+1))
126  for i in range(len(gaplayers)):
127  if i<len(gaplayers)-1:
128  layersequence.append((tmp[i]+1,tmp[i+1]+1))
129  else:
130  layersequence.append((tmp[i]+1,Nlayers))
131  K=np.zeros((nequations,nequations))
132  R=np.zeros((nequations,len(T_eff)))
133  # setting up equations system
134  for currentlayers in layersequence:
135  presscounter-=1
136 
137  for i in range(currentlayers[0],currentlayers[1]):
138  if layerinfo[i]=='wires':
139  ihelic+=1
140  # solving for
141  #local strain, radial expansion, change in thickness, contact pressure,global strain
142  #eps1,eps2...,u31,u32,u33...,deltat1,deltat2,deltat3...,p1,p2,p3,..epsglobal
143  # kinematics local/global
144 
145  K[linecounter,eps11index+ihelic]+=-r[i]
146  K[linecounter,u3index+i]+=np.sin(alpha[i])**2
147  K[linecounter,-1]+=np.cos(alpha[i])**2*r[i]
148  #Last row is total axial equilibrium
149  K[-1,eps11index+ihelic]+=n[i]*E[i]*A[i]*np.cos(alpha[i])
150  if i>currentlayers[0]:
151  K[-1,pindex+presscounter]+=-nu[i]*n[i]*A[i]*np.cos(alpha[i])/(2.0*fillfactor_in[i])
152  if i<currentlayers[1]-1:
153  K[-1,pindex+presscounter+1] +=-nu[i]*n[i]*A[i]*np.cos(alpha[i])/(2.0*fillfactor_out[i])
154  if i==0:
155  R[-1,:]+=T_eff+np.pi*p_int*(r[intpresslayer]-t[intpresslayer]/2.0)**2-np.pi*p_ext*(r[extpresslayer]+t[extpresslayer]/2.0)**2
156  if i==intpresslayer:
157  R[-1,:]+=nu[i]*n[i]*A[i]*np.cos(alpha[i])/(2.0*fillfactor_in[i])*p_int
158  if i==extpresslayer:
159  R[-1,:]+=nu[i]*n[i]*A[i]*np.cos(alpha[i])/(2.0*fillfactor_out[i])*p_ext
160  # Second row is pressure equilibrium
161  # check row number
162  linecounter+=1
163  K[linecounter,eps11index+ihelic]+=np.sin(alpha[i])**2*A[i]*E[i]*n[i]/(np.cos(alpha[i])*r[i])
164  if i>currentlayers[0]:
165  K[linecounter,pindex+presscounter]+=-nu[i]*np.sin(alpha[i])**2*A[i]*n[i]/(fillfactor_in[i]*2*r[i]*np.cos(alpha[i]))-\
166  2*np.pi*(r[i]-t[i]/2.0)
167  if i<currentlayers[1]-1:
168  K[linecounter,pindex+presscounter+1] +=-nu[i]*np.sin(alpha[i])**2*A[i]*n[i]/(fillfactor_out[i]*2*r[i]*np.cos(alpha[i]))+\
169  2*np.pi*(r[i]+t[i]/2.0)
170  if i == intpresslayer:
171  R[linecounter]+=+nu[i]*np.sin(alpha[i])**2*A[i]*n[i]/(fillfactor_in[i]*2*r[i]*\
172  np.cos(alpha[i]))*p_int+\
173  2*np.pi*(r[i]-t[i]/2.0)*p_int
174  if i == extpresslayer:
175  R[linecounter]+=+nu[i]*np.sin(alpha[i])**2*A[i]*n[i]/(fillfactor_out[i]*2*r[i]*\
176  np.cos(alpha[i]))*p_ext\
177  -2*np.pi*(r[i]+t[i]/2.0)*p_ext
178  # Radial squeeze
179  linecounter+=1
180  K[linecounter,eps11index+ihelic]+=nu[i]
181  K[linecounter,deltatindex+i]+=1.0/t[i]
182  if i>currentlayers[0]:
183  K[linecounter,pindex+presscounter]+=(1+nu[i]**2)/(2*E[i]*fillfactor_in[i])
184  if i<currentlayers[1]-1:
185  K[linecounter,pindex+presscounter+1] +=(1+nu[i]**2)/(2*E[i]*fillfactor_out[i])
186  if i==intpresslayer:
187  R[linecounter] +=-(1+nu[i]**2)/(2*E[i]*fillfactor_in[i])*p_int
188  if i == extpresslayer:
189  R[linecounter] +=-(1+nu[i]**2)/(2*E[i]*fillfactor_out[i])*p_ext
190 
191  #Radial continuity
192  #Only for closed interfaces of this one
193  linecounter+=1
194  if i>currentlayers[0]:
195  K[linecounter,u3index+i-1]+=-1
196  K[linecounter,u3index+i]+=1
197  K[linecounter,deltatindex+i-1]+=-0.5
198  K[linecounter,deltatindex+i]+=-0.5
199  R[linecounter]+=-gap_ini[i]
200  linecounter+=1
201  # add system for plastic layers
202  if layerinfo[i]=='sheath':
203  router=r[i]+t[i]/2.0
204  rinner=r[i]-t[i]/2.0
205  # adding to axial equilibrium
206  K[-1,-1]+=A[i]*E[i]
207  # using eqs 4 and 5 from Custodio
208  if i>currentlayers[0]:
209  K[-1,pindex+presscounter]+= nu[i]*2.0*rinner**2*A[i]/(router**2-rinner**2)
210  if i<currentlayers[1]-1:
211  K[-1,pindex+presscounter+1]+=-nu[i]*2.0*router**2*A[i]/(router**2-rinner**2)
212  if i==0:
213  R[-1,:]+=T_eff+np.pi*p_int*(r[intpresslayer]-t[intpresslayer]/2.0)**2-np.pi*p_ext*(r[extpresslayer]+t[extpresslayer]/2.0)**2
214  if i ==intpresslayer:
215  R[-1,:]+= -nu[i]*2.0*rinner**2*A[i]/(router**2-rinner**2)*p_int
216  if i==extpresslayer:
217  R[-1,:]+= nu[i]*2.0*router**2*A[i]/(router**2-rinner**2)*p_ext
218 
219 
220 
221  # radial equilibrium
222  K[linecounter,-1]+=r[i]*nu[i]
223  K[linecounter,u3index+i]+=1.0
224  if i>currentlayers[0]:
225  K[linecounter,pindex+presscounter] +=-(1+nu[i])*rinner**2*((2*nu[i]-1)*r[i]**2-router**2)/(E[i]*(rinner**2-router**2)*r[i])
226  if i<currentlayers[1]-1:
227  K[linecounter,pindex+presscounter+1]+= (1+nu[i])*router**2*((2*nu[i]-1)*r[i]**2-rinner**2)/(E[i]*(rinner**2-router**2)*r[i])
228  if i==intpresslayer:
229  R[linecounter] += (1+nu[i])*rinner**2*((2*nu[i]-1)*r[i]**2-router**2)/(E[i]*(rinner**2-router**2)*r[i])*p_int
230  if i==extpresslayer:
231  R[linecounter] += -(1+nu[i])*router**2*((2*nu[i]-1)*r[i]**2-rinner**2)/(E[i]*(rinner**2-router**2)*r[i])*p_ext
232  linecounter+=1
233 
234  # Thickness equilibrium
235  K[linecounter,-1]+=t[i]*nu[i]
236  K[linecounter,deltatindex+i]+=1.0
237  if i>currentlayers[0]:
238  K[linecounter,presscounter+pindex]+= (1+nu[i])*rinner*((2*nu[i]-1)*rinner+router)/(E[i]*(rinner+router))
239  if i < currentlayers[1]-1:
240  K[linecounter,presscounter+pindex+1]+= -(1+nu[i])*router*((2*nu[i]-1)*router+rinner)/(E[i]*(rinner+router))
241  if i==intpresslayer:
242  R[linecounter] += -(1+nu[i])*rinner*((2*nu[i]-1)*rinner+router)/(E[i]*(rinner+router))*p_int
243  if i==extpresslayer:
244  R[linecounter] += (1+nu[i])*router*((2*nu[i]-1)*router+rinner)/(E[i]*(rinner+router))*p_ext
245  linecounter+=1
246 
247 
248  # Radial continuity
249  # Only for closed interfaces (could be moved out of loop
250  if i>currentlayers[0]:
251  K[linecounter,u3index+i-1]+=-1
252  K[linecounter,u3index+i]+=1
253  K[linecounter,deltatindex+i-1]+=-0.5
254  K[linecounter,deltatindex+i]+=-0.5
255  R[linecounter]+=-gap_ini[i]
256  linecounter+=1
257  presscounter+=1
258  return K,R,eps11index,u3index,deltatindex,pindex,fillfactor_in,fillfactor_out
259 
260 def corrector(r,t,b,A,n,E,nu,alpha,gap_ini,intpresslayer,extpresslayer,layerinfo,T_eff,p_int,p_ext,solution,pindex,Nlayers):
261  # find solutions with negative gap
262  negpresindices=np.where(solution[pindex+1:pindex+Nlayers,:] < 0)
263 
264  if len(negpresindices[0])>0:
265  # found negative pressure
266  negtime=np.unique(negpresindices[1])
267  #neglayers=np.unique(negpresindices[0])
268  neglayers=list(range(0,Nlayers-1))
269  # correct solutions is gap in one or more of the neglayers
270  solution_options=combfinder(neglayers)
271  # brute force through solving all possible solutions
272  for sol in reversed(solution_options):
273  for sol2 in sol:
274  # fill in changed stuff and solve
275  K,R,eps11index,u3index,deltatindex,pindex,fillfactor_in,fillfactor_out =\
276  systemsetup(r,t,b,A,n,E,nu,alpha,gap_ini,intpresslayer,extpresslayer,layerinfo,T_eff[negtime],
277  p_int[negtime],p_ext[negtime],gaplayers=sol2)
278 
279  solutionalternative=np.linalg.solve(K,R)
280  np.savetxt('k1.csv', K, fmt='%.18e', delimiter=',', newline='\n')
281  np.savetxt('solution1.csv', solutionalternative[:,0], fmt='%.18e', delimiter=',', newline='\n')
282  np.savetxt('r1.csv', R[:,0], fmt='%.18e', delimiter=',', newline='\n')
283  # checking if solution is correct at some time, if so, fill into original solution
284  negpresindicesalternative=np.where(solutionalternative[pindex+1:pindex+Nlayers-len(sol2),:] < 0)
285  negtimealternative=np.unique(negpresindicesalternative[1])
286  # check if we have times with no negative pressures
287  if len(negtimealternative) < len(negtime):
288  nonegative=sorted(set(range(0,negtime[-1]+1)).difference(negtimealternative))
289  # check if no unallowed layer contact
290  interface=list(sol2)
291  u3indices=np.array([x+u3index for x in interface])
292  u3plusoneindices=np.array([x+u3index+1 for x in interface])
293  deltatindices=np.array([x+deltatindex for x in interface])
294  deltatplusoneindices=np.array([x+deltatindex+1 for x in interface])
295  gapindices=np.array([x+1 for x in interface])
296  # Checking for positive gap
297  #now approved indices is the indices of the new solution, not the original solution
298  approvedindices=np.where(-solutionalternative[u3indices,:]
299  -0.5*solutionalternative[deltatindices,:]
300  -0.5*solutionalternative[deltatplusoneindices,:]
301  +solutionalternative[u3plusoneindices,:]
302  +gap_ini[gapindices].reshape(-1,1) > np.min((solutionalternative[deltatindices,:],solutionalternative[deltatplusoneindices,:]))*1.0e-3
303  )
304  # check the approved indices for each time against the number that should be approved. Move that into the solution from before, and check if we are done.
305  # check if approved for all interfaces
306  approvedtimeindices=[k for k,v in collections.Counter(approvedindices[1]).items() if v==len(interface)]
307  # Putting the approved solutions into the original solution matrix
308  solution[eps11index:pindex+1,negtime[approvedtimeindices]]=solutionalternative[eps11index:pindex+1,approvedtimeindices]
309  count=0
310  for i in range(Nlayers-1):
311  if i in interface:
312  solution[pindex+1+i,negtime[approvedtimeindices]]=0.0
313  else:
314  solution[pindex+1+i,negtime[approvedtimeindices]]=solutionalternative[pindex+1+count,approvedtimeindices]
315  count+=1
316  solution[-1,negtime[approvedtimeindices]]=solutionalternative[-1,approvedtimeindices]
317  # update negative indices
318  negpresindices=np.where(solution[pindex+1:pindex+Nlayers,:] < 0)
319  if negpresindices[0].size == 0:
320  #solution is great eject!!
321  return solution
322 
323  else:
324  return solution
def solver(layerinfo, r, t, b, A, alpha, n, E, nu, gap_ini, intpresslayer, extpresslayer, T_eff, p_int, p_ext)
Definition: axisymmetric.py:8
def corrector(r, t, b, A, n, E, nu, alpha, gap_ini, intpresslayer, extpresslayer, layerinfo, T_eff, p_int, p_ext, solution, pindex, Nlayers)
def systemsetup(r, t, b, A, n, E, nu, alpha, gap_ini, intpresslayer, extpresslayer, layerinfo, T_eff, p_int, p_ext, gaplayers=[0])
def combfinder(combinations)
Definition: axisymmetric.py:95