report_internship_trc aachen

14
Report Modelling of origami concrete crease pattern and export into Abaqus using open source software – Pyformex Name: Viktoras Jarmolkovicius Home university: University of Sheffield Host institute: RWTH – Institut für Massivbau Project supervisor: Jan Dirk van Der Woerd Duration: 2014.06.09 – 2014.08.01

Upload: viktoras-jarmolkovicius

Post on 12-Aug-2015

288 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Report_Internship_TRC Aachen

Report

Modelling of origami concrete crease pattern and export into Abaqus using open source software – Pyformex

Name: Viktoras Jarmolkovicius

Home university: University of Sheffield

Host institute: RWTH – Institut für Massivbau

Project supervisor: Jan Dirk van Der Woerd

Duration: 2014.06.09 – 2014.08.01

Page 2: Report_Internship_TRC Aachen

2

Table of Contents

Executive Summary 3

Introduction 3

Exploration of Pyformex functionality 4

General information 4

Features worth mentioning 5

Creation of the crease and export into Abaqus 5

1. Input Parameters 5

2. Reading of data 6

3. Offset 6

4. Creation of crease 7

5. Subdivision (Meshing) 7

6. Assignment of properties and .inp export 8

Analysis of Abaqus 8

Conclusions 9

References 9

Appendix 10

Page 3: Report_Internship_TRC Aachen

3

Executive Summary

This report focuses on the presentation of the internship project that was undertaken in the Institute

for Structural Concrete, RWTH, Aachen, Germany, under supervision of Mr. Jan Dirr van der Woerd.

The main purpose of the project was to develop a software tool (code) to facilitate the analysis of

Textile Reinforced Concrete plate structures via the Finite Element Method. Firstly, the detailed

scope of the project is introduced and important background information is given to present already

existing and available facilities and to present associated expectations and further development

areas. The main body of the report consists of 3 main sections: exploration of existing Pyformex

software functionality, development of the analysis tool and modelling of laboratory test in Abaqus.

Images and brief explanations are given where appropriate. In the end, the outcome of the project is

concluded and an appendix featuring a full detailed script of the tool is given for reference purposes.

Introduction

Internship material focuses on some specific areas of a major research project which is being carried

out in the Institut für Massivbau in RWTH, Aachen under supervision of the doctoral student Jan Dirk

van Der Woerd and the research assistant Mr. Rotislav Chudoba. So far, a computer simulation

platform was developed which creates a 3D structure consisting of folded TRC concrete plates.

Simulation software is undergoing constant development and in order to achieve satisfying results a

specific definition of the crease pattern that joins TRC plates is necessary. Internship covers explicit

definition and modelling of a crease pattern using open source python-based software Pyformex.

After crease patterned was appropriately modelled, it is expected to be meshed into Finite Elements

and prepared for subsequent analysis in Abaqus. Internship outcome also includes the exploration of

the functionality of Pyformex for the main research application and generally learning how to use

Pyformex and Abaqus and familiarise myself better with Finite Element Analysis for Structural

Engineering Applications. Ultimate goal is to use Abaqus to simulate the laboratory experiment

performed on a real structure.

Pyformex is open source software which is undergoing constant development and changes, yet it is

free and easily accessible to a new user. For the purpose of the research project, Pyformex is

intended to be used as an intermediate step between Oricrete Simulation Platform and Finite

Element Analysis Software Abaqus with an ultimate intention to integrate all the steps as modules

and plugins into Oricrete Simulation Platform.

Page 4: Report_Internship_TRC Aachen

4

The process could be visualized as follows:

Exploration of Pyformex functionality

General information

The exploration has revealed that Pyformex is very powerful software that is capable of performing

different actions related to objects, their properties with an ultimate intention to create an input file

(.inp) for analysis in Abaqus. A detailed description of all Pyformex functions is available in the

keyword manual accessible at http://nongnu.mirrors.hostinginnederland.nl//pyformex/pyformex.pdf

The manual provides a total overview of the functionality, however does not include any comments

on how to implement the functions, examples should be sought elsewhere. It gives a good idea of

what Pyformex is capable of though: it is possible to perform majority of mathematical and

geometrical operations, since Pyformex has a module called “numpy” in its library.

A very good source of data which was used extensively during the internship is the website called

“nullege”. It contains numerous .py files with all plugins, also working and useful examples, such as

Fe_Abq.py where a random object is created, manipulated, meshed, assigned different properties to

and finally written as a .inp file. This example was extensively referred to while creating a code for

export of .inp file of the crease. The author of the scripts is the creator of the Pyformex himself –

prof. Benedict Verhegghe.

http://nullege.com/codes/show/src%40p%40y%40pyformex-

0.9.0%40pyformex%40extra%40dxfparser%40ReadDxf.py/41/pyformex.plugins.geomtools.anyPerpe

ndicularVector/python

Oricrete

•Output result: list of nodes and elements corresponding to facets of of the structure - no crease specified

Pyformex

•modelling of the crease

•creation of FE mesh

•assignment of properties

•writing .inp file

Abaqus

•FE analysis of the structure

•Interpretation of different loading conditions, support constraints, material properties and their impact on results

Page 5: Report_Internship_TRC Aachen

5

Features worth mentioning

Similar to programing in “Eclipse” various modules and plugins have to be imported in order

to use their functionality.

Pyformex can perform some very useful geometrical and mathematical operations, like

creating a Finite Element Mesh for instance, but certain operations can be performed only on

specific object classes. The most usual ones are “Formex”, “TriSurface”, “Array”, “Mesh”.

Necessity for usage of different classes will be elaborated on in the next section.

Pyformex is similar to CAD software in a way that objects and files can be

imported/created/manipulated/exported both via direct scripting (writing appropriate

commands) and via the usage of graphical user interface (using toolbars and drawing options).

Pyformex has a very convenient and user friendly drawing facility of the “Formex” class which

is the most frequently used one. Command is simply draw(g) where “g” is a “Formex” object.

Also conversion from an “array” to “Formex” is very simple. This is very useful, because it is

convenient to perform mathematical and geometrical operations on “arrays” using “numpy”

functions. A modified object can be easily drawn afterwards.

“Formices” of same plexitude can be superposed to one another by a simple mathematical addition operation (+). Plexitude refers to the number nodes that compose a single element.

Creation of the crease and export into Abaqus

This section is mainly structured in way that a brief explanation of the code will be presented

alongside with illustrative images whereas a detailed version of the code can be found in the

appendix of the report – thus the focus will be kept on the most important aspects and concepts of

the tool that was developed during an internship. The code was run and tested to work properly on

both Pyformex and Abaqus, provided that two input files 'nodes.txt' and 'elements.txt' (described in

more detail in the next section) are given. Although the code addresses a particular crease pattern

arrangement, it is generally multipurpose and is applicable to any number of elements.

1. Input Parameters

This is where the actual work on input data begins. Some very basic user input parameters have to

be specified. Changing one of those values will affect the gaps between elements and the size of

the mesh. These parameters define the outcome of the analysis:

1. Number of elements

2. Number of divisions, or mesh density

3. Crease mesh density

4. Offset distance

Offset distance – is unitless but is essentially of the same units as coordinates. So if coordinates

are implied to be in centimetres then distance will be implied in centimetres too.

Page 6: Report_Internship_TRC Aachen

6

2. Reading of data

Lists of nodes and nodal connectivity are imported into Pyformex and converted into a “Formex”

class. Files “nodes.txt” and “elements.txt” are essentially the only input parameters and they are

being manipulated later. Nodes file should be structured in a way that numbers are x,y,z

coordinates of each node 0,1,2…,n:

0.0536, 0.0024, 0.0412,

0.0536, 0.4012, 0.0412,

0.0536, 0.8000, 0.0412,

0.3555, 0.0024, 0.2184,

Numbering is implied. Within itself Pyformex counts starting with zero: 0,1,2,…,n. Elements file

would have a very similar structure:

0, 3, 19,

1, 4, 20,

3, 6, 21,

4, 7, 22,

Again, numbering of elements is implied. Numbers show the connectivity of nodes. For example,

element 0 connects nodes 0, 3 and 19 and so on. This essentially means that the output file from

the ‘Oricrete’ Platform should be modified such that all nodes have number values minus one.

Input data can be presented in the visual form:

3. Offset

Now elements are offset by a certain user defined distance specified at the beginning of the script

(mentioned above). Offsetting is based on area coordinate method which ensures that each side

of the triangle is moved by a constant distance. Pyformex by default used unitless numbers.

Therefore the units of the distance are the same as units of length and area of the triangle. This

means that if a user gives nodal coordinate date in centimetres, then offset distance will be

understood in centimetres too.

Page 7: Report_Internship_TRC Aachen

7

4. Creation of crease

Once triangles are offset, the crease has to be created, joining the gaps between triangles. The

script works in such way that on the lowest level 2 adjacent triangles are analysed at one time: 4

nodes defining a gap between 2 triangles are located and are used to create a new “Formex”.

Once this “Formex” is created, rest of the operations remain the same regardless of which two of

the triangles of the general structure are analysed. A newly created “Formex” is a 4-plex structure

(definition of plexitude is explained above) which is essentially a desired crease assuming the

structure is 3D but consists of 2D plates.

5. Subdivision (Meshing)

By this point there are two objects created: a 3-plex Formex of offset triangles and a 4-plex

Formex consisting of the crease elements. Due to the fact that assignment of properties can be

done to object of same plexitude only, each of the crease elements has to be subdivided into two

triangles. Superposition of the triangles’ Formex and crease Formex gives the desired final

structure, it is, however, convenient to keep them two separate because later different properties

are assigned to them. This is what the final superposed Formex looks like:

Page 8: Report_Internship_TRC Aachen

8

6. Assignment of properties and .inp export

Last section of the code is creation of the .inp file which itself consists of 3 main subparts: creation

of properties, assignment of properties and export of the .inp file ready for analysis in Abaqus.

First of all, property database is created. It is very important to import properties’ plugin and make

sure that the name of the property database (which can be essentially arbitrary) is consistently

followed through the rest of the process, because this is where all the properties of the entire

structure are stored and read from. Next, final Formex is converted into TriSurface so that nodes

and elements can be easily obtained. These will be required later, during the export of .inp file. It

is important to note here at this point that we are working with one unique Formex by the name

“final” but its constituents – crease and triangles are still having their nodes and elements

indirectly associated with them. We assign two properties: “pa” and “pb” which are nothing else

but colors (1 and 2 in this example) to triangles and crease respectively. This is not used directly

but assists later in creation of two different kinds of element sets that will have different

properties assigned to them. After that, a standard procedure for creating material properties,

section properties and creation of the sections follows. Once that is done, element properties can

be assigned to their respective sets (colours) and saved in the property database. Next, boundary

and loaded node sets are defined by the user. A standard procedure for nodal property

assignment follows. Finally, nodes, elements and property database, also output requests and

loading steps are all put together and an export file of the format .inp is created and run in

Abaqus.

Analysis of Abaqus

An example of loading the crease pattern:

Boundary: edges are pinned

Loading: 6 point loads applied at middle crease gap

Plates are modelled as thin steel shell elements

Crease is modelled as thin glass shell elements

Page 9: Report_Internship_TRC Aachen

9

Conclusions

This project proved that Pyformex indeed offers great assistance and already existing functionality to

manipulate both simple and complex geometrical objects with the purpose of either performing

Finite Element Analysis directly or preparing the input file for analysis in other FE software programs.

It is important to note that further development of the tool is necessary to account for real geometry

and improve the simulation of the laboratory experiment. Another valuable conclusion is the

reliability aspect of open source software: it was observed that there are multiple errors and

functions that do not work properly and/or are not designed and explained completely. The risks of

using constantly changing open source software have to be properly assessed and evaluated before

important analysis operations are performed.

References

1. http://nongnu.mirrors.hostinginnederland.nl//pyformex/pyformex.pdf

2. http://nullege.com/codes/show/src%40p%40y%40pyformex-

0.9.0%40pyformex%40extra%40dxfparser%40ReadDxf.py/41/pyformex.plugins.geomtools.anyPerpendi

cularVector/python

3. http://ocw.mit.edu/courses/mathematics/18-085-computational-science-and-engineering-i-fall-

2008/video-lectures/lecture-17-finite-elements-in-1d-part-1/

Page 10: Report_Internship_TRC Aachen

10

Appendix

This section features the full Python script used for the process described above.

1. #just trying out some things

2. #importing aaaalllll the stuff, just in case ;)

3. #Please be patient and respectful to the code! Pretty please :)

4. #I am still new to programming

5.

6.

7. import numpy as np

8. import pyformex as pf

9. from mesh import *

10. import utils

11. from lib import misc

12. import os

13. from formex import *

14. from connectivity import connectivity,connectedLineElems,adjacencyArrays

15. from mesh import Mesh

16. import geomtools

17. import fileread,filewrite

18. import utils

19. import os,tempfile

20. import tempfile

21. from utils import deprecation

22. from pyformex.olist import List

23. from numpy import array,arange

24. from plugins.fe_abq import *

25. from plugins.properties import *

26. from plugins.fe import *

27. from mydict import Dict,CDict

28. import pyformex as GD

29. from datetime import datetime

30. import os,sys

31. from mesh import *

#Specifying some fixed variables before start

36. ndiv = 6

37. rf1 = 1

38. rf2 = 1

39. dist = 0.01

40. nel = 36

41. clear()

#Read a set of nodes from an open mesh file

47. #Reading geometry

48. a = fromfile('nodes1f.txt',sep=',').reshape(-1,3)

49. a = Coords(a)

50. """print('coords',a)"""

51. """print('printing coordinates',a)"""

52. #Read a set of elemements of plexitude nplex from an open mesh file

53. e = fromfile('elements1f.txt',sep=',',dtype=Int).reshape(-1,3)

54. e = Connectivity(e)

55. """print('now printing elems..',e)"""

56. #Creating the desired formex

57. g = Formex(a[e]).setProp(3)

58. #Converting Formex to an array

59. clear()

Page 11: Report_Internship_TRC Aachen

11

#Offsetting

66. x = g

67. """print('original coords',x)"""

68. # calculate the cross sectional area of each triangle

69. v1 = x[:, 1, :] - x[:, 0, :]

70. v2 = x[:, 2, :] - x[:, 0, :]

71. # calculate cross product

72. v12 = np.cross(v1, v2,axis=1)

73. # claculate area

74. a = np.array([0.0]*nel)

75. for i in range (0,nel):

76. a[i] = np.linalg.norm(v12[i])/2.0

77. """print('area',a)"""

78. # calculate the edge lengths of each triangle

79. # first edge is at the opposite of the first node.

80. l = np.sqrt(np.sum((x[:, (2, 0, 1), :] - x[:, (1, 2, 0), :]) ** 2, axis=2))

81. """print('lengths',l)"""

82. # calculate the triangle heights relative to each edge

83. h = 2 * a[:, np.newaxis] / l

84. # get the area coordinate of all points at dist

85. xi_dist = dist / h

86. # construct the combinations of all three coords

87. # and calculate the third triangular coordinate.

88. cxi0 = np.c_[1 - xi_dist[:, 2] - xi_dist[:, 1], xi_dist[:, 1], xi_dist[:,

2]]

89. cxi1 = np.c_[xi_dist[:, 0], 1 - xi_dist[:, 0] - xi_dist[:, 2], xi_dist[:,

2]]

90. cxi2 = np.c_[xi_dist[:, 0], xi_dist[:, 1], 1 - xi_dist[:, 0] - xi_dist[:,

1]]

91. cx = np.array([cxi0, cxi1, cxi2], dtype='f')

92. # get the shifted nodal coordinates

93. xs = np.einsum('lik,ikj->ilj', cx, x)

94. F = Formex(xs)

95. draw(F)

#Creation of the crease

100. #now make a loop to go around each of the entries of adj and call it

"el_nr"

101. gg = g

102. adj = g.toMesh().adjacency(1,2)

103. """print('adjacency :)',adj)"""

104. bigcrease = Formex([])

105. for el_nr in range (0,36)

106. if adj[el_nr][0] == -1:

107. lim = 1

108. else:

109. lim = 0

110. #this inside loop is looping through adjacent elements

111. for i in range (lim,3):

112. i = adj[el_nr][i]

113. j = el_nr

114. n1,n2,n3,n4,n5,n6=0,0,0,0,0,0

115. for iii in range (0,3):

116. if length(gg[i][0]-gg[j][iii])==0:

117. n1=F[i][0]

118. n2=F[j][iii]

119. for iii in range (0,3):

120. if length(gg[i][1]-gg[j][iii])==0:

Page 12: Report_Internship_TRC Aachen

12

121. n3=F[i][1]

122. n4=F[j][iii]

123. for iii in range (0,3):

124. if length(gg[i][2]-gg[j][iii])==0:

125. n5=F[i][2]

126. n6=F[j][iii]

127. if length(n1) == 0:

128. point1=n3

129. point2=n4

130. point3=n5

131. point4=n6

132. if length(n3) == 0:

133. point1=n1

134. point2=n2

135. point3=n5

136. point4=n6

137. if length(n5) == 0:

138. point1=n1

139. point2=n2

140. point3=n3

141. point4=n4

142. # run through all of the "bigcrease" elements

143. # check if the crease is already created

144. cr_nr = (size(length(bigcrease)))/4

145. ii = cr_nr

146. counting = 1

147. """print('size of big crease is',cr_nr)"""

148. for cr_nr in range (0,ii-1):

149. check = Formex([bigcrease[cr_nr]])

150. current = Formex([[point1,point3,point4,point2]])

151. if (check[0][0][0]==current[0][3][0]) and

(check[0][1][0]==current[0][2][0]) and (check[0][0][2]==current[0][3][2]) and

check[0][0][0] > 0:

152. counting = 0

153. if counting == 1:

154. bigcrease = bigcrease.setProp(2) +

Formex([[point1,point3,point4,point2]]).setProp(2)

155.

#Subdivision

162. #First split the crease into rectangular elements

163. #Then take each rectangular element and split it into triangles

164. #To keep consistent with global Formex plexiture

165. endcrease = Formex([])

166. creasef = Formex([])

167. for number in range (0,46):

168. crease = Formex([bigcrease[number]])

169. crease = crease.toMesh()

170. crease = crease.subdivide(ndiv,1)

171. crease = crease.toFormex()

172. for i in range(0,ndiv):

173. creasei = Formex([crease[i]])

174. creasei =

(((creasei.toMesh()).subdivide(rf1,rf2)).toSurface()).toFormex()

175. creasef = creasef + creasei

176. endcrease = endcrease + creasef

177. clear()

178. draw(endcrease)

179. FF = Formex(xs).toMesh().toSurface().subdivide(ndiv)

Page 13: Report_Internship_TRC Aachen

13

# Assigning Properties

189. clear()

190. F = FF

191. crease_f = endcrease

192. draw(Formex(FF + endcrease))

193. PDB = PropertyDB()

194. # Turn the Formex structure into a TriSurface

195. # This guarantees that element i of the Formex is element i of the

TriSurface

196. S = TriSurface(F+crease_f)

197. nodes = S.coords

198. elems = S.elems # the triangles

199. # So now we have F (domain A) and crease_f (domain B): two ready formices

200. #Make sure property numbers never clash!

201. pa,pb = 1,2 #properties corresponding to domains A and B

202. F.setProp(pa)

203. crease_f.setProp(pb)

204. parts = [F,crease_f]

205. #Transfer properties from the parts in a global set

206. elemprops = concatenate([part.prop for part in parts])

207. # Create element sets according to the properties pa,pb:

208. esets = {}

209. esets.update([(v,where(elemprops==v)[0]) for v in [pa,pb]])

210. # Set element properties

211. # This is where one can say that element groups will be different abq

eltypes

212. # creating some section and material properties

213. steel = {

214. 'name': 'steel',

215. 'young_modulus': 3e+10,

216. 'poisson_ratio': 0.2,

217. 'density': 2500,

218. }

219. glass = {

220. 'name': 'glass',

221. 'young_modulus': 72000,

222. 'shear_modulus': 26200,

223. 'density': 2.5,

224. }

225. medium_plate = {

226. 'name': 'glass_plate',

227. 'sectiontype': 'shell',

228. 'thickness': 0.006,

229. 'material': 'glass',

230. }

231. thin_plate = {

232. 'name': 'glass_plate',

233. 'sectiontype': 'shell',

234. 'thickness': 0.002,

235. 'material': 'glass',

236. }

237. tube = {

238. 'name':'tube',

239. 'cross_section': 799,

240. 'moment_inertia_11': 1000,

241. 'sectiontype': 'GENERAL',

242. 'moment_inertia_22': 1500,

243. 'moment_inertia_12': 1230,

244. 'torsional_constant': 900,

245. 'material': 'steel',

Page 14: Report_Internship_TRC Aachen

14

246. }

247. tubesection = ElemSection(section=tube,material=steel)

248. facetsection = ElemSection(secton=medium_plate,material=steel)

249. creasesection = ElemSection(section=thin_plate,material=glass)

250. #writing properties

251. PDB.elemProp(set=esets[pa],section=facetsection,eltype='S3R')

252. PDB.elemProp(set=esets[pb],section=creasesection,eltype='S3R')

253. # populate the property database

254. #Boundary nodes

255. bnodes = [1,2,3,50,51,52,53]

256. #Loaded nodes

257. lnodes = [240]

258. # Set the nodal properties

259. PDB.nodeProp(tag='init',set=bnodes,name='boundary',bound='pinned')

260. PDB.nodeProp(tag='step1',set=lnodes,name='Loaded',cload=[0.,0.,-

800.,0.,0.,0.])

261. # Request default output plus output of S in elements of part B.

262. # If the abqdata are written with group_by_group==True (see at bottom),

263. # all elements of each group in elems will be collected in a set named

264. # Eset('grp',index), where index is the index of the group in the elems

list.

265. # Thus, all elements of part B will end up in Eset('grp',1)

266. out = [ Output(type='history'),

267. Output(type='field')

268. ]

269. # Create requests for output to the .fil file.

270. # - the displacements in all nodes

271. # - the stress components in all elements

272. # - the stresses averaged at the nodes

273. # - the principal stresses and stress invariants in the elements of part B.

274. # (add output='PRINT' to get the results printed in the .dat file)

275. res = [ Result(kind='NODE',keys=['U']),

276. Result(kind='ELEMENT',keys=['S']),

277. Result(kind='ELEMENT',keys=['S'],pos='AVERAGED AT NODES')

278. ]

279. # Define steps (default is static)

280. step1 = Step(time=[0.1, 1., 1e-05,

1.],tags=['step1'],name='step1',out=out,res=res)

281. # collect all data

282. # !! currently output/result request are global to all steps

283. # !! this will be changed in future

284. #

285. fe_model = Dict(dict(solver='Abaqus',nodes=nodes,elems=elems,prop=PDB))

286. export({'fe_model':fe_model})

287. FE = named('fe_model')

288. nodes = FE.nodes

289. elems = FE.elems

290. prop = FE.prop

291. model = Model(nodes,elems)

292. data = AbqData(model,PDB,steps=[step1],bound=['init'])

293. if ack('Export this model in ABAQUS input format?',default='No'):

294. fn = askNewFilename(filter='*.inp')

295. if fn:

296. data.write(jobname=fn,group_by_group=True)

297.

298. # End