def createQuadPart(res=None): """Create a quadrilateral domain from user input""" global x0,y0,x1,y1,x2,y2,x3,y3,nx,ny,eltype if model is not None: if ask('You have already merged the parts! I can not add new parts anymore.\nYou should first delete everything and recreate the parts.',['Delete','Cancel']) == 'Delete': deleteAll() else: return if res is None: res = askItems([ _I('Vertex 0',(x0,y0)), _I('Vertex 1',(x1,y1)), _I('Vertex 2',(x2,y2)), _I('Vertex 3',(x3,y3)), _I('nx',nx), _I('ny',ny), _I('eltype',eltype,itemtype='radio',choices=['quad','tri-u','tri-d']), ]) if res: x0,y0 = res['Vertex 0'] x1,y1 = res['Vertex 1'] x2,y2 = res['Vertex 2'] x3,y3 = res['Vertex 3'] nx = res['nx'] ny = res['ny'] eltype = res['eltype'] diag = {'quad':'', 'tri-u':'u', 'tri-d':'d'}[eltype] xold = rectangle(1,1).coords xnew = Coords([[x0,y0],[x1,y1],[x2,y2],[x3,y3]]) M = rectangle(nx,ny,1.,1.,diag=diag).toMesh().isopar('quad4',xnew,xold) addPart(M)
def createQuadPart(res=None): """Create a quadrilateral domain from user input""" global x0,y0,x1,y1,x2,y2,x3,y3,nx,ny,eltype if model is not None: if ask('You have already merged the parts! I can not add new parts anymore.\nYou should first delete everything and recreate the parts.',['Delete','Cancel']) == 'Delete': deleteAll() else: return if res is None: res = askItems([ I('Vertex 0',(x0,y0)), I('Vertex 1',(x1,y1)), I('Vertex 2',(x2,y2)), I('Vertex 3',(x3,y3)), I('nx',nx), I('ny',ny), I('eltype',eltype,itemtype='radio',choices=['quad','tri-u','tri-d']), ]) if res: x0,y0 = res['Vertex 0'] x1,y1 = res['Vertex 1'] x2,y2 = res['Vertex 2'] x3,y3 = res['Vertex 3'] nx = res['nx'] ny = res['ny'] eltype = res['eltype'] diag = {'quad':'', 'tri-u':'u', 'tri-d':'d'}[eltype] xold = rectangle(1,1).coords xnew = Coords([[x0,y0],[x1,y1],[x2,y2],[x3,y3]]) M = rectangle(nx,ny,1.,1.,diag=diag).toMesh().isopar('quad4',xnew,xold) addPart(M)
def cone(r0, r1, h, t=360., nr=1, nt=24, diag=None): """Constructs a Formex which is (a sector of) a circle / (truncated) cone / cylinder. r0,r1,h are the lower and upper radius and the height of the truncated cone. All can be positive, negative or zero. Special cases: r0 = r1 : cylinder h = 0 : (flat) circle r0 = 0 or r1 = 0 : untruncated cone Only a sector of the structure, with opening angle t, is modeled. The default results in a full circumference. The cone is modeled by nr elements in height direction and nt elements in circumferential direction. By default, the result is a 4-plex Formex whose elements are quadrilaterals (some of which may collapse into triangles). If diag='up' or diag = 'down', all quads are divided by an up directed diagonal and a plex-3 Formex results. """ B = simple.rectangle(nt, nr, 1., 1., diag=diag) # grid with size 1x1 B = B.map(lambda x, y, z: [x, y, r0 - y * (r0 - r1)]) # translate and tilt it B = B.scale([t, h, 1.]) # scale to fit parameters return B.cylindrical(dir=[2, 0, 1]) # roll it into a cone
def createRectangle(): _data_ = _name_ + 'createRectangle_data' dia = Dialog(items=[ _I('name', '__auto__'), _I('object type', choices=['Formex', 'Mesh', 'TriSurface']), _I('nx', 1), _I('ny', 1), _I('width', 1.), _I('height', 1.), _I('bias', 0.), _I('diag', 'up', choices=['none', 'up', 'down', 'x-both']), ]) if _data_ in pf.PF: dia.updateData(pf.PF[_data_]) res = dia.getResults() if res: pf.PF[_data_] = res name = res['name'] if name == '__auto__': name = autoName(res['object type']).next() F = simple.rectangle(nx=res['nx'], ny=res['ny'], b=res['width'], h=res['height'], bias=res['bias'], diag=res['diag'][0]) F = convertFormex(F, res['object type']) export({name: F}) selection.set([name]) if res['object type'] == 'TriSurface': surface_menu.selection.set([name]) selection.draw()
def createRectPart(res=None): """Create a rectangular domain from user input""" global x0,y0,x2,y2,nx,ny,eltype if model is not None: if ask('You have already merged the parts! I can not add new parts anymore.\nYou should first delete everything and recreate the parts.',['Delete','Cancel']) == 'Delete': deleteAll() else: return if res is None: res = askItems([ _I('x0',x0,tooltip='The x-value of one of the corners'), _I('y0',y0), _I('x2',x2),_I('y2',y2), _I('nx',nx),_I('ny',ny), _I('eltype',eltype,itemtype='radio',choices=['quad','tri-u','tri-d']), ]) if res: globals().update(res) if x0 > x2: x0,x2 = x2,x0 if y0 > y2: y0,y2 = y2,y0 diag = {'quad':'', 'tri-u':'u', 'tri-d':'d'}[eltype] M = rectangle(nx,ny,x2-x0,y2-y0,diag=diag).toMesh().trl([x0,y0,0]) addPart(M)
def run(): clear() smoothwire() view('iso') # create a 2D xy mesh nx, ny = 6, 2 G = simple.rectangle(1, 1, 1., 1.).replic2(nx, ny) M = G.toMesh() draw(M, color='red') # create a 3D axial-symmetric mesh by REVOLVING n, a = 8, 45. R = M.revolve(n, angle=a, axis=1, around=[1., 0., 0.]) draw(R, color='yellow') # reduce the degenerate elements to WEDGE6 clear() ML = R.fuse().splitDegenerate() # keep only the non-empty meshes ML = [m for m in ML if m.nelems() > 0] print("After splitting: %s meshes:" % len(ML)) for m in ML: print(" %s elements of type %s" % (m.nelems(), m.elName())) ML = [Mi.setProp(i + 4) for i, Mi in enumerate(ML)] draw(ML)
def run(): clear() smoothwire() nx = 4 ny = 3 nz = 7 delay(2) # A rectangular mesh M1 = simple.rectangle(nx, ny).toMesh().setProp(1) # Same mesh, rotated and translated M2 = M1.rotate(45, 0).translate([1., -1., nz]).setProp(3) draw([M1, M2]) # Leave out the first and the last two elements sel = arange(M1.nelems())[1:-2] m1 = M1.select(sel) m2 = M2.select(sel) clear() draw([m1, m2], view=None) # Connect both meshes to a hexaeder mesh m = m1.connect(m2, nz) clear() draw(m, color=red, view=None)
def run(): clear() smoothwire() nx = 4 ny = 3 nz = 7 delay(2) # A rectangular mesh M1 = simple.rectangle(nx,ny).toMesh().setProp(1) # Same mesh, rotated and translated M2 = M1.rotate(45,0).translate([1.,-1.,nz]).setProp(3) draw([M1,M2]) # Leave out the first and the last two elements sel = arange(M1.nelems())[1:-2] m1 = M1.select(sel) m2 = M2.select(sel) clear() draw([m1,m2],view=None) # Connect both meshes to a hexaeder mesh m = m1.connect(m2,nz) clear() draw(m,color=red,view=None)
def createRectPart(res=None): """Create a rectangular domain from user input""" global x0,y0,x2,y2,nx,ny,eltype if model is not None: if ask('You have already merged the parts! I can not add new parts anymore.\nYou should first delete everything and recreate the parts.',['Delete','Cancel']) == 'Delete': deleteAll() else: return if res is None: res = askItems([ I('x0',x0,tooltip='The x-value of one of the corners'), I('y0',y0), I('x2',x2),I('y2',y2), I('nx',nx),I('ny',ny), I('eltype',eltype,itemtype='radio',choices=['quad','tri-u','tri-d']), ]) if res: globals().update(res) if x0 > x2: x0,x2 = x2,x0 if y0 > y2: y0,y2 = y2,y0 diag = {'quad':'', 'tri-u':'u', 'tri-d':'d'}[eltype] M = rectangle(nx,ny,x2-x0,y2-y0,diag=diag).toMesh().trl([x0,y0,0]) addPart(M)
def cone(r0,r1,h,t=360.,nr=1,nt=24,diag=None): """Constructs a Formex which is (a sector of) a circle / (truncated) cone / cylinder. r0,r1,h are the lower and upper radius and the height of the truncated cone. All can be positive, negative or zero. Special cases: r0 = r1 : cylinder h = 0 : (flat) circle r0 = 0 or r1 = 0 : untruncated cone Only a sector of the structure, with opening angle t, is modeled. The default results in a full circumference. The cone is modeled by nr elements in height direction and nt elements in circumferential direction. By default, the result is a 4-plex Formex whose elements are quadrilaterals (some of which may collapse into triangles). If diag='up' or diag = 'down', all quads are divided by an up directed diagonal and a plex-3 Formex results. """ B = simple.rectangle(nt,nr,1.,1.,diag=diag) # grid with size 1x1 B = B.map(lambda x,y,z:[x,y,r0-y*(r0-r1)]) # translate and tilt it B = B.scale([t,h,1.]) # scale to fit parameters return B.cylindrical(dir=[2,0,1]) # roll it into a cone
def createGrid(): """Create the grid from global parameters""" global B nx, ny = grid_size b, h = x_range[1] - x_range[0], y_range[1] - y_range[0] if grid_base.startswith('tri'): diag = grid_base[-1] else: diag = '' B = rectangle(nx, ny, b, h, diag=diag, bias=grid_bias).translate([x_range[0], y_range[0], 1.]) if grid_skewness != 0.0: B = B.shear(0, 1, grid_skewness * b * ny / (h * nx)) if x_clip: B = B.clip( B.test('any', dir=0, min=x_clip[0] + tol * b, max=x_clip[1] - tol * b)) if y_clip: B = B.clip( B.test('any', dir=1, min=y_clip[0] + tol * h, max=y_clip[1] - tol * h)) export({grid_name: B})
def createGrid(): res = askItems([('name','__auto__'),('nx',3),('ny',3),('b',1),('h',1)]) if res: globals().update(res) #name = res['name'] #nx = res['nx'] #ny = res['ny'] #b = S = TriSurface(simple.rectangle(nx,ny,b,h,diag='d')) export({name:S}) selection.set([name]) selection.draw()
def createGrid(): res = askItems([_I("name", "__auto__"), _I("nx", 3), _I("ny", 3), _I("b", 1), _I("h", 1)]) if res: globals().update(res) # name = res['name'] # nx = res['nx'] # ny = res['ny'] # b = S = TriSurface(simple.rectangle(nx, ny, b, h, diag="d")) export({name: S}) selection.set([name]) selection.draw()
def showSuperEgg(): """Draw a super Egg from set global parameters""" nx,ny = grid b,h = long_range[1]-long_range[0], lat_range[1]-lat_range[0] if grid_base.startswith('tri'): diag = grid_base[-1] else: diag = '' B = rectangle(nx,ny,b,h,diag=diag,bias=grid_bias).translate([long_range[0],lat_range[0],1.]) if grid_skewness != 0.0: B = B.shear(0,1,grid_skewness) F = B.superSpherical(n=north_south,e=east_west,k=eggness).scale(scale) clear() draw(F,color=color) export({name:F})
def run(): reset() smoothwire() transparent() lights(True) nx, ny = 20, 10 F = simple.rectangle(nx, ny) F = F.trl(-F.center() + [0., 0., nx / 2]) draw(F) G = F.projectOnSphere(ny) draw(G, color=red) H = F.rotate(30).projectOnCylinder(ny) draw(H, color=blue)
def createGrid(): """Create the grid from global parameters""" global B nx,ny = grid_size b,h = x_range[1]-x_range[0], y_range[1]-y_range[0] if grid_base.startswith('tri'): diag = grid_base[-1] else: diag = '' B = rectangle(nx,ny,b,h,diag=diag,bias=grid_bias).translate([x_range[0],y_range[0],1.]) if grid_skewness != 0.0: B = B.shear(0,1,grid_skewness*b*ny/(h*nx)) if x_clip: B = B.clip(B.test('any',dir=0,min=x_clip[0]+tol*b,max=x_clip[1]-tol*b)) if y_clip: B = B.clip(B.test('any',dir=1,min=y_clip[0]+tol*h,max=y_clip[1]-tol*h)) export({grid_name:B})
def run(): reset() smoothwire() transparent() lights(True) nx,ny = 20,10 F = simple.rectangle(nx,ny) F = F.trl(-F.center()+[0.,0.,nx/2]) draw(F) G = F.projectOnSphere(ny) draw(G,color=red) H = F.rotate(30).projectOnCylinder(ny) draw(H,color=blue)
def run(): reset() clear() linewidth(1) delay(1) if roof is None: createRoof() F = roof.rotate(-90, 0) # put the structure upright draw(F) createView('myview1', (30., 0., 0.)) view('myview1', True) setDrawOptions({'bbox': 'last'}) for i in range(19): createView('myview2', (i * 10., 20., 0.)) view('myview2', True) delay(0.1) # fly tru if ack("Do you want to fly through the structure?"): totaltime = 10 nsteps = 50 # make sure bottom iz at y=0 and structure is centered in (x,z) F = F.centered() F = F.translate(1, -F.bbox()[0, 1]) clear() linewidth(1) draw(F) bb = F.bbox() # create a bottom plate B = simple.rectangle(1, 1).swapAxes(1, 2).centered().scale( F.sizes()[0] * 1.5) smooth() draw(B, color='slategrey') # Fly at reasonable height bb[0, 1] = bb[1, 1] = 170. ends = interpolate(Formex([[bb[0]]]), Formex([[bb[1]]]), [-0.5, 0.6]) path = Formex(ends.coords.reshape(-1, 2, 3)).divide(nsteps) linewidth(2) draw(path) steptime = float(totaltime) / nsteps flyAlong(path, sleeptime=steptime)
def createPart(res=None): """Create a rectangular domain from user input""" global x0, y0, x1, y1 if model is not None: if ( ask( "You have already merged the parts! I can not add new parts anymore.\nYou should first delete everything and recreate the parts.", ["Delete", "Cancel"], ) == "Delete" ): deleteAll() else: return if res is None: res = askItems( [ ("x0", x0), ("y0", y0), ("x1", x1), ("y1", y1), ("nx", nx), ("ny", ny), ("eltype", eltype, "select", ["quad", "tri-u", "tri-d"]), ] ) if res: globals().update(res) if x0 > x1: x0, x1 = x1, x0 if y0 > y1: y0, y1 = y1, y0 diag = {"quad": "", "tri-u": "u", "tri-d": "d"}[eltype] F = rectangle(nx, ny, x1 - x0, y1 - y0, diag=diag).trl([x0, y0, 0]) addPart(F) drawParts()
def createPart(res=None): """Create a rectangular domain from user input""" global x0,y0,x1,y1 if model is not None: if ask('You have already merged the parts! I can not add new parts anymore.\nYou should first delete everything and recreate the parts.',['Delete','Cancel']) == 'Delete': deleteAll() else: return if res is None: res = askItems([('x0',x0),('y0',y0), ('x1',x1),('y1',y1), ('nx',nx),('ny',ny), ('eltype',eltype,'select',['quad','tri-u','tri-d']), ]) if res: globals().update(res) if x0 > x1: x0,x1 = x1,x0 if y0 > y1: y0,y1 = y1,y0 diag = {'quad':'', 'tri-u':'u', 'tri-d':'d'}[eltype] F = rectangle(nx,ny,x1-x0,y1-y0,diag=diag).trl([x0,y0,0]) addPart(F) drawParts()
""" import simple from mesh import Mesh clear() smoothwire() nx = 4 ny = 3 nz = 7 delay(2) # A rectangular mesh M1 = simple.rectangle(nx,ny).toMesh().setProp(1) # Same mesh, rotated and translated M2 = M1.rotate(45,0).translate([1.,-1.,nz]).setProp(3) draw([M1,M2]) # Leave out the first and the last two elements sel = arange(M1.nelems())[1:-2] m1 = M1.select(sel) m2 = M2.select(sel) clear() draw([m1,m2],view=None) # Connect both meshes to a hexaeder mesh m = m1.connect(m2,nz) clear() draw(m,color=red,view=None)
h = 200.0 # beam height b = 200.0 # flange width tf = 15.0 # flange thickness tw = 9.0 # body thickness l = 400.0 # beam length r = 18.0 # filling radius # MESH PARAMETERS el = 20 # number of elements along the length etb = 2 # number of elements over half of the thickness of the body ehb = 5 # number of elements over half of the height of the body etf = 5 # number of elements over the thickness of the flange ewf = 8 # number of elements over half of the width of the flange er = 6 # number of elements in the circular segment Body = simple.rectangle(etb, ehb, tw / 2.0, h / 2.0 - tf - r) Flange1 = simple.rectangle(er / 2, etf - etb, tw / 2.0 + r, tf - tw / 2.0).translate( [0.0, h / 2.0 - (tf - tw / 2.0), 0.0] ) Flange2 = simple.rectangle(ewf, etf - etb, b / 2.0 - r - tw / 2.0, tf - tw / 2.0).translate( [tw / 2.0 + r, h / 2.0 - (tf - tw / 2.0), 0.0] ) Flange3 = simple.rectangle(ewf, etb, b / 2.0 - r - tw / 2.0, tw / 2.0).translate([tw / 2.0 + r, h / 2.0 - tf, 0.0]) c1a = simple.line([0, h / 2 - tf - r, 0], [0, h / 2 - tf + tw / 2, 0], er / 2) c1b = simple.line([0, h / 2 - tf + tw / 2, 0], [tw / 2 + r, h / 2 - tf + tw / 2, 0], er / 2) c1 = c1a + c1b c2 = simple.circle(90.0 / er, 0.0, 90.0).reflect(0).scale(r).translate([tw / 2 + r, h / 2 - tf - r, 0]) Filled = simple.connectCurves(c2, c1, etb) Quarter = Body + Filled + Flange1 + Flange2 + Flange3 Half = Quarter + Quarter.reflect(1).reverse() Full = Half + Half.reflect(0).reverse()
def run(): reset() clear() # Property numbers used pbol = 1 # Bol ptop = 2 # Top plate pbot = 3 # Bottom plate scale = 15. # scale (grid unit in mm) # Create a solid sphere BolSurface = simple.sphere().scale(scale) try: # tetmesh may not be available Bol = BolSurface.tetmesh(quality=True).setProp(pbol) except: return draw(Bol) # Create top and bottom plates plate = simple.rectangle(4, 4).toMesh().centered() topplate = plate.setProp(ptop).trl(2, 1.).scale(scale) botplate = plate.setProp(pbot).trl(2, -1.).scale(scale) draw([topplate, botplate]) # model is completely drawn, keep fixed bbox setDrawOptions({'bbox': 'last', 'marksize': 8}) # Assemble the model M = Model(meshes=[Bol, topplate, botplate]) # Create the property database P = PropertyDB() # In this simple example, we do not use a material/section database, # but define the data directly steel = { 'name': 'steel', 'young_modulus': 207000, 'poisson_ratio': 0.3, 'density': 7.85e-9, 'plastic': [ (305.45, 0.), (306.52, 0.003507), (308.05, 0.008462), (310.96, 0.01784), (316.2, 0.018275), (367.5, 0.047015), (412.5, 0.093317), (448.11, 0.154839), (459.6, 0.180101), (494., 0.259978), (506.25, 0.297659), (497., 0.334071), (482.8, 0.348325), (422.5, 0.366015), (399.58, 0.3717), (1., 0.37363), ], } solid_steel = { 'name': 'solid_steel', 'sectiontype': 'solid', 'material': 'steel', # Need material reference for Abaqus } steel_plate = { 'name': 'solid_steel', 'sectiontype': 'solid', 'thickness': 3, 'material': 'steel', # Need material reference for Abaqus } # Set the element properties eset = dict([(p, where(M.prop == p)[0]) for p in [pbol, ptop, pbot]]) # Bol is elasto/plastic P.elemProp(set=eset[pbol], name='Bol', eltype='C3D4', section=ElemSection(section=solid_steel, material=steel)) # Top plate is rigid or elasto-plastic topplate_rigid = True if topplate_rigid: # Rigid bodies need a reference node. # We select the most central node, but any node would also work, # e.g. pbref = M.elems[1][0][0], the very first node in the group reftop = groupCentralPoint(M, 1) print("Top plate refnode: %s" % reftop) draw(M.coords[reftop], color=green) P.elemProp(set=eset[ptop], name='TopPlate', eltype='R3D4', section=ElemSection(sectiontype='rigid', refnode=reftop)) else: P.elemProp(set=eset[ptop], name='TopPlate', eltype='CPS4', section=ElemSection(section=steel_plate, material=steel)) # Bottom plate is rigid or elasto-plastic refbot = groupCentralPoint(M, 2) print("Bottom plate refnode: %s" % refbot) draw(M.coords[refbot], color=blue) P.elemProp(set=eset[pbot], name='BottomPlate', eltype='R3D4', section=ElemSection(sectiontype='rigid', refnode=refbot)) # Set the boundary conditions # Bottom plate is fixed fixed = unique(M.elems[2]) P.nodeProp(tag='init', set=[refbot], name='Fixed', bound=[1, 1, 1, 1, 1, 1]) # Set the loading conditions # Top plate gets z-displacement of -5 mm displ = unique(M.elems[1]) P.nodeProp(tag='init', set=[reftop], name='Displ', bound=[1, 1, 0, 1, 1, 1]) P.nodeProp(tag='step1', set=[reftop], name='Refnod', displ=[(2, -0.5)]) ## # Set the loading conditions ## # All elements of Plate1 have a pressure loading of 10 MPa ## loaded = M.elemNrs(1) ## P.elemProp(tag='step1',set=loaded,name='Loaded',dload=ElemLoad('P',10.0)) from plugins.fe_abq import Interaction P.Prop(tag='init', generalinteraction=Interaction(name='interaction1', friction=0.1)) print("Element properties") for p in P.getProp('e'): print(p) print("Node properties") for p in P.getProp('n'): print(p) print("Model properties") for p in P.getProp(''): print(p) out = [ Output(type='history'), Output(type='field'), ] # Create requests for output to the .fil file. # - the displacements in all nodes # - the stress components in all elements # - the stresses averaged at the nodes # - the principal stresses and stress invariants in the elements of part B. # (add output='PRINT' to get the results printed in the .dat file) res = [ Result(kind='NODE', keys=['U']), Result(kind='ELEMENT', keys=['S'], set='Bol'), Result(kind='ELEMENT', keys=['S'], pos='AVERAGED AT NODES', set='Bol'), Result(kind='ELEMENT', keys=['SP', 'SINV'], set='Bol'), ] # Define steps (default is static) step1 = Step('DYNAMIC', time=[1., 1., 0.01, 1.], tags=['step1']) data = AbqData(M, prop=P, steps=[step1], res=res, bound=['init']) if ack('Export this model in ABAQUS input format?', default='No'): fn = askNewFilename(filter='*.inp') if fn: data.write(jobname=fn, group_by_group=True)
def run(): # GEOMETRICAL PARAMETERS FOR HE200B wide flange beam h = 200. #beam height b = 200. #flange width tf = 15. #flange thickness tw = 9. #body thickness l = 400. #beam length r = 18. #filling radius # MESH PARAMETERS el = 20 #number of elements along the length etb = 2 #number of elements over half of the thickness of the body ehb = 5 #number of elements over half of the height of the body etf = 5 #number of elements over the thickness of the flange ewf = 8 #number of elements over half of the width of the flange er = 6 #number of elements in the circular segment Body = simple.rectangle(etb,ehb,tw/2.,h/2.-tf-r) Flange1 = simple.rectangle(er/2,etf-etb,tw/2.+r,tf-tw/2.).translate([0.,h/2.-(tf-tw/2.),0.]) Flange2 = simple.rectangle(ewf,etf-etb,b/2.-r-tw/2.,tf-tw/2.).translate([tw/2.+r,h/2.-(tf-tw/2.),0.]) Flange3 = simple.rectangle(ewf,etb,b/2.-r-tw/2.,tw/2.).translate([tw/2.+r,h/2.-tf,0.]) c1a = simple.line([0,h/2-tf-r,0],[0,h/2-tf+tw/2,0],er/2) c1b = simple.line([0,h/2-tf+tw/2,0],[tw/2+r,h/2-tf+tw/2,0],er/2) c1 = c1a + c1b c2 = simple.circle(90./er,0.,90.).reflect(0).scale(r).translate([tw/2+r,h/2-tf-r,0]) Filled = simple.connectCurves(c2,c1,etb) Quarter = Body + Filled + Flange1 + Flange2 + Flange3 Half = Quarter + Quarter.reflect(1).reverse() Full = Half + Half.reflect(0).reverse() Section = Full.toMesh() clear() draw(Section,color=red) #return #pause() method = ask("Choose extrude method:",['Cancel','Sweep','Connect','Extrude','ExtrudeQuadratic','Revolve','RevolveLoop']) import timer t = timer.Timer() if method == 'Sweep': L = simple.line([0,0,0],[0,0,l],el) x = concatenate([L.coords[:,0],L.coords[-1:,1]]) path = curve.PolyLine(x) Beam = Section.sweep(path,normal=[0.,0.,1.],upvector=[0.,1.,0.]) elif method == 'Connect': Section1 = Section.trl([0,0,l]) Beam = Section.connect(Section1,el) elif method == 'Extrude': Beam = Section.extrude(el,step=l/el,dir=2) elif method == 'ExtrudeQuadratic': Section = Section.convert('quad9') Beam = Section.extrude(el,step=l/el,dir=2,degree=2) elif method == 'Revolve': Beam = Section.revolve(el,axis=1,angle=60.,around=[-l,0.,0.]) elif method == 'RevolveLoop': Beam = Section.revolve(el,axis=1,angle=240.,around=[-l,0.,0.],loop=True) else: return print("Computing: %s seconds" % t.seconds()) #print Beam.prop #print Beam.elems.shape t.reset() clear() #draw(Beam,color='red',linewidth=2) draw(Beam.getBorderMesh(),color='red',linewidth=2) print("Drawing: %s seconds" % t.seconds()) export({'Beam':Beam})
view('myview1',True) drawtimeout = 1 for i in range(19): createView('myview2',(i*10.,20.,0.)) view('myview2',True) # fly tru if ack("Do you want to fly through the structure?"): totaltime = 10 nsteps = 50 # make sure bottom iz at y=0 and structure is centered in (x,z) F = F.centered() F = F.translate(1,-F.bbox()[0,1]) clear() linewidth(1) draw(F) bb = F.bbox() # create a bottom plate B = simple.rectangle(1,1).swapAxes(1,2).centered().scale(F.sizes()[0]*1.5) smooth() draw(B) # Fly at reasonable height bb[0,1] = bb[1,1] = 170. ends = interpolate(Formex([[bb[0]]]),Formex([[bb[1]]]),[-0.5,0.6]) path = connect([ends,ends],bias=[0,1]).divide(nsteps) linewidth(2) draw(path) steptime = float(totaltime)/nsteps flyAlong(path,sleeptime=steptime)
def run(): reset() clear() # Property numbers used pbol = 1 # Bol ptop = 2 # Top plate pbot = 3 # Bottom plate scale = 15. # scale (grid unit in mm) # Create a solid sphere BolSurface = simple.sphere().scale(scale) try: # tetmesh may not be available Bol = BolSurface.tetmesh(quality=True).setProp(pbol) except: return draw(Bol) # Create top and bottom plates plate = simple.rectangle(4,4).toMesh().centered() topplate = plate.setProp(ptop).trl(2,1.).scale(scale) botplate = plate.setProp(pbot).trl(2,-1.).scale(scale) draw([topplate,botplate]) # model is completely drawn, keep fixed bbox setDrawOptions({'bbox':'last','marksize':8}) # Assemble the model M = Model(meshes=[Bol,topplate,botplate]) # Create the property database P = PropertyDB() # In this simple example, we do not use a material/section database, # but define the data directly steel = { 'name': 'steel', 'young_modulus': 207000, 'poisson_ratio': 0.3, 'density': 7.85e-9, 'plastic' : [ (305.45, 0.), (306.52, 0.003507), (308.05, 0.008462), (310.96, 0.01784), (316.2, 0.018275), (367.5, 0.047015), (412.5, 0.093317), (448.11, 0.154839), (459.6, 0.180101), (494., 0.259978), (506.25, 0.297659), (497., 0.334071), (482.8, 0.348325), (422.5, 0.366015), (399.58, 0.3717), (1., 0.37363), ], } solid_steel = { 'name': 'solid_steel', 'sectiontype': 'solid', 'material': 'steel', # Need material reference for Abaqus } steel_plate = { 'name': 'solid_steel', 'sectiontype': 'solid', 'thickness': 3, 'material': 'steel', # Need material reference for Abaqus } # Set the element properties eset = dict([(p,where(M.prop==p)[0]) for p in [pbol,ptop,pbot]]) # Bol is elasto/plastic P.elemProp(set=eset[pbol],name='Bol',eltype='C3D4',section=ElemSection(section=solid_steel,material=steel)) # Top plate is rigid or elasto-plastic topplate_rigid = True if topplate_rigid: # Rigid bodies need a reference node. # We select the most central node, but any node would also work, # e.g. pbref = M.elems[1][0][0], the very first node in the group reftop = groupCentralPoint(M,1) print("Top plate refnode: %s" % reftop) draw(M.coords[reftop],color=green) P.elemProp(set=eset[ptop],name='TopPlate',eltype='R3D4',section=ElemSection(sectiontype='rigid',refnode=reftop)) else: P.elemProp(set=eset[ptop],name='TopPlate',eltype='CPS4',section=ElemSection(section=steel_plate,material=steel)) # Bottom plate is rigid or elasto-plastic refbot = groupCentralPoint(M,2) print("Bottom plate refnode: %s" % refbot) draw(M.coords[refbot],color=blue) P.elemProp(set=eset[pbot],name='BottomPlate',eltype='R3D4',section=ElemSection(sectiontype='rigid',refnode=refbot)) # Set the boundary conditions # Bottom plate is fixed fixed = unique(M.elems[2]) P.nodeProp(tag='init',set=[refbot],name='Fixed',bound=[1,1,1,1,1,1]) # Set the loading conditions # Top plate gets z-displacement of -5 mm displ = unique(M.elems[1]) P.nodeProp(tag='init',set=[reftop],name='Displ',bound=[1,1,0,1,1,1]) P.nodeProp(tag='step1',set=[reftop],name='Refnod',displ=[(2,-0.5)]) ## # Set the loading conditions ## # All elements of Plate1 have a pressure loading of 10 MPa ## loaded = M.elemNrs(1) ## P.elemProp(tag='step1',set=loaded,name='Loaded',dload=ElemLoad('P',10.0)) from plugins.fe_abq import Interaction P.Prop(tag='init',generalinteraction=Interaction(name='interaction1',friction=0.1)) print("Element properties") for p in P.getProp('e'): print(p) print("Node properties") for p in P.getProp('n'): print(p) print("Model properties") for p in P.getProp(''): print(p) out = [ Output(type='history'), Output(type='field'), ] # Create requests for output to the .fil file. # - the displacements in all nodes # - the stress components in all elements # - the stresses averaged at the nodes # - the principal stresses and stress invariants in the elements of part B. # (add output='PRINT' to get the results printed in the .dat file) res = [ Result(kind='NODE',keys=['U']), Result(kind='ELEMENT',keys=['S'],set='Bol'), Result(kind='ELEMENT',keys=['S'],pos='AVERAGED AT NODES',set='Bol'), Result(kind='ELEMENT',keys=['SP','SINV'],set='Bol'), ] # Define steps (default is static) step1 = Step('DYNAMIC',time=[1., 1., 0.01, 1.],tags=['step1']) data = AbqData(M,prop=P,steps=[step1],res=res,bound=['init']) if ack('Export this model in ABAQUS input format?',default='No'): fn = askNewFilename(filter='*.inp') if fn: data.write(jobname=fn,group_by_group=True)
h = 200. #beam height b = 200. #flange width tf = 15. #flange thickness tw = 9. #body thickness l = 400. #beam length r = 18. #filling radius # MESH PARAMETERS el = 20 #number of elements along the length etb = 2 #number of elements over half of the thickness of the body ehb = 5 #number of elements over half of the height of the body etf = 5 #number of elements over the thickness of the flange ewf = 8 #number of elements over half of the width of the flange er = 6 #number of elements in the circular segment Body = simple.rectangle(etb,ehb,tw/2.,h/2.-tf-r) Flange1 = simple.rectangle(er/2,etf-etb,tw/2.+r,tf-tw/2.).translate([0.,h/2.-(tf-tw/2.),0.]) Flange2 = simple.rectangle(ewf,etf-etb,b/2.-r-tw/2.,tf-tw/2.).translate([tw/2.+r,h/2.-(tf-tw/2.),0.]) Flange3 = simple.rectangle(ewf,etb,b/2.-r-tw/2.,tw/2.).translate([tw/2.+r,h/2.-tf,0.]) c1a = simple.line([0,h/2-tf-r,0],[0,h/2-tf+tw/2,0],er/2) c1b = simple.line([0,h/2-tf+tw/2,0],[tw/2+r,h/2-tf+tw/2,0],er/2) c1 = c1a + c1b c2 = simple.circle(90./er,0.,90.).reflect(0).scale(r).translate([tw/2+r,h/2-tf-r,0]) Filled = simple.connectCurves(c2,c1,etb) Quarter = Body + Filled + Flange1 + Flange2 + Flange3 Half = Quarter + Quarter.reflect(1).reverse() Full = Half + Half.reflect(0).reverse() Section = Full.toMesh() clear() draw(Section,color=red)
## """Projection level = 'normal' topics = ['geometry','surface'] techniques = ['colors'] """ import simple from gui.canvas import * nx,ny = 20,10 F = simple.rectangle(nx,ny) F = F.trl(-F.center()+[0.,0.,nx/2]) draw(F) x = F.f.projectOnSphere(ny) G = Formex(x) draw(G,color=red) x = F.f.rotate(30).projectOnCylinder(ny) H = Formex(x) draw(H,color=blue) smooth() n=200 for i in range (n): v = float(i)/(2*n)
def run(): reset() clear() processor = 'abq' # set to 'ccx' for calculix # Create a thin rectangular plate. # Because it is thin, we use a 2D model (in the xy plane. # We actually only model 1/4 of the plate' # The full plate could be found from mirroring wrt x and y axes. L = 400. # length of the plate (mm) B = 100. # width of the plate (mm) th = 10. # thickness of the plate (mm) L2,B2 = L/2, B/2 # dimensions of the quarter plate nl,nb = 10,16 # number of elements along length, width nl,nb = 2,2 # number of elements along length, width D = 20. r = D/2 e0 = 0.3 # User input res = askItems([ _I('geometry',choices=['Rectangle','Square with hole'],text='Plate geometry'), _I('material',choices=['Elastic','Plastic'],text='Material model'), _I('eltype',choices=['quad4','quad8','hex8','hex20'],text='Element type'), _I('interpolation',choices=['Linear','Quadratic'],text='Degree of interpolation'), _I('format',choices=['CalculiX','Abaqus'],text='FEA input format'), _I('run',True,text='Run simulation'), ]) if not res: return cmd = None if res['run']: cmd = {'CalculiX':'ccx','Abaqus':'abaqus'}[res['format']] if not utils.hasExternal(res['format'].lower()): ans = pf.warning("I did not find the command '%s' on your system.\nIf you continue, I can prepare the model and write the input file,but not run the simulation" % cmd,actions=['Cancel','Continue']) if ans == 'Continue': cmd = None else: return # Create geometry if res['geometry'] == 'Rectangle': plate = simple.rectangle(nl,nb,L2,B2).toMesh() else: plate = rectangle_with_hole(L2,B2,r,nl,nb,e0) if res['eltype'].startswith('hex'): plate = plate.extrude(1,step=1.0,dir=2) plate = plate.convert(res['eltype']) draw(plate) # model is completely shown, keep camera bbox fixed setDrawOptions({'bbox':'last','marksize':8}) # Assemble the FEmodel (this may renumber the nodes!) FEM = Model(meshes=[plate]) # Create an empty property database P = PropertyDB() # Define the material data: here we use an elasto-plastic model # for the steel steel = { 'name': 'steel', 'young_modulus': 207000e-6, 'poisson_ratio': 0.3, 'density': 7.85e-9, } if res['material'] == 'Plastic': steel.update( {'plastic': [ (305.45, 0.), (306.52, 0.003507), (308.05, 0.008462), (310.96, 0.01784), (316.2, 0.018275), (367.5, 0.047015), (412.5, 0.093317), (448.11, 0.154839), (459.6, 0.180101), (494., 0.259978), (506.25, 0.297659), (497., 0.334071), (482.8, 0.348325), (422.5, 0.366015), (399.58, 0.3717), (1., 0.37363), ] }) # Define the thin steel plate section steel_plate = { 'name': 'steel_plate', 'sectiontype': 'solid', 'thickness': th, 'material': 'steel', # Reference to the material name above } # Give the elements their properties: this is simple here because # all elements have the same properties. The element type is # for an Abaqus plain stress quadrilateral element with 4 nodes. P.elemProp(name='Plate',eltype='CPS4',section=ElemSection(section=steel_plate,material=steel)) # Set the boundary conditions # The xz and yz planes should be defined as symmetry planes. # First, we find the node numbers along the x, y axes: elsize = min(L2/nl,B2/nb) # smallest size of elements tol = 0.001*elsize # a tolerance to avoid roundoff errors nyz = FEM.coords.test(dir=0,max=tol) # test for points in the yz plane nxz = FEM.coords.test(dir=1,max=tol) # test for points in the xz plane nyz = where(nyz)[0] # the node numbers passing the above test nxz = where(nxz)[0] draw(FEM.coords[nyz],color=cyan) draw(FEM.coords[nxz],color=green) # Define the boundary conditions # For Abaqus, we could define it like follows #P.nodeProp(tag='init',set=nyz,name='YZ_plane',bound='XSYMM') #P.nodeProp(tag='init',set=nxz,name='XZ_plane',bound='YSYMM') # But as Calculix does not have the XSYMM/YSYMM possibilities # we define the conditions explicitely P.nodeProp(tag='init',set=nyz,name='YZ_plane',bound=[1,0,0,0,0,0]) P.nodeProp(tag='init',set=nxz,name='XZ_plane',bound=[0,1,0,0,0,0]) # The plate is loaded by a uniform tensile stress in the x-direction # First we detect the border brd,ind = FEM.meshes()[0].getBorder(return_indices=True) BRD = Mesh(FEM.coords,brd).compact() draw(BRD,color=red,linewidth=2) xmax = BRD.bbox()[1][0] # the maximum x coordinate loaded = BRD.test(dir=0,min=xmax-tol) # The loaded border elements loaded = where(loaded)[0] draw(BRD.select(loaded),color=blue,linewidth=4) sortedelems = sortElemsByLoadedFace(ind[loaded]) # Define the load # Apply 4 load steps: # 1: small load (10 MPa) # 2: higher load, but still elastic (100 MPa) # 3: slightly exceeding yield stress (320 MPa) # 4: high plastic deformation (400MPa) loads = [10.,100.,320.,400.] # tensile load in MPa steps = ['step%s'%(i+1) for i in range(len(loads)) ] # step names for face in sortedelems: abqface = face+1 # BEWARE: Abaqus numbers start with 1 for step,load in zip(steps,loads): P.elemProp(tag=step,set=sortedelems[face],name='Loaded-%s'%face,dload=ElemLoad('P%s'%(abqface),-load)) # Print the property database P.print() # Create requests for output to the .fil file. # - the displacements in all nodes # - the stress components in all elements # - the stresses averaged at the nodes # - the principal stresses and stress invariants in the elements of part B. # (add output='PRINT' to get the results printed in the .dat file) if res['format'] == 'Abaqus': result = [ Result(kind='NODE',keys=['U']), Result(kind='ELEMENT',keys=['S'],set='Plate'), Result(kind='ELEMENT',keys=['S'],pos='AVERAGED AT NODES',set='Plate'), Result(kind='ELEMENT',keys=['SP','SINV'],set='Plate'), ] else: result = [ Result(kind='NODE',keys=['U'],output='PRINT'), Result(kind='ELEMENT',keys=['S'],output='PRINT'), ] # Define the simulation steps # The tags refer to the property database simsteps = [ Step('STATIC',time=[1., 1., 0.01, 1.],tags=[step]) for step in steps ] data = AbqData(FEM,prop=P,steps=simsteps,res=result,bound=['init']) fn = askNewFilename(pf.cfg['workdir']+'/feplast.inp',filter='*.inp') if fn: data.write(jobname=fn,group_by_group=True) if cmd: chdir(fn) job = os.path.basename(fn)[:-4] if cmd == 'ccx': cmd = "ccx -i %s" % job elif cmd == 'abaqus': cmd == "abaqus job=%s" % job sta,out = utils.runCommand("ccx -i %s" % job) print(out) if ack('Create the result database?'): DB = ccxdat.createResultDB(FEM) ngp = 8 fn = utils.changeExt(fn,'.dat') ccxdat.readResults(fn,DB,DB.nnodes,DB.nelems,ngp) DB.printSteps() name = 'FeResult-%s'%job export({name:DB}) postproc_menu.setDB(DB) if showInfo("The results have been exported as %s\nYou can now use the postproc menu to display results" % name,actions=['Cancel','OK']) == 'OK': postproc_menu.selection.set(name) postproc_menu.selectDB(DB) postproc_menu.open_dialog()
""" import simple from connectivity import reverseUniqueIndex from plugins.mesh import * def drawMesh(mesh,ncolor='blue',ecolor='red'): if ncolor: draw(mesh.coords,color=ncolor) if ecolor: draw(mesh,color=ecolor,bbox='last') nx = 4 ny = 3 nz = 7 F = simple.rectangle(nx,ny).setProp(1) c1,e1 = F.feModel() c2 = c1.rotate(45,0).translate([1.,-1.,nz]) G = Formex(c2[e1]).setProp(3) draw([F,G]) e1 = e1[1:-2] m1 = Mesh(c1,e1) m2 = Mesh(c2,e1) clear() drawMesh(m1)
"""WedgeHex level = 'normal' topics = ['mesh'] techniques = ['revolve','degenerate'] """ import simple clear() smoothwire() # create a 2D xy mesh nx,ny = 6,2 G = simple.rectangle(1,1,1.,1.).replic2(nx,ny) M = G.toMesh() draw(M, color='red') view('iso') # create a 3D axial-symmetric mesh by REVOLVING n,a = 8,45. R = M.revolve(n,angle=a,axis=1,around=[1.,0.,0.]) sleep(2) draw(R,color='yellow') # reduce the degenerate elements to WEDGE6 sleep(2) clear() ML = R.splitDegenerate() ML = [ Mi.setProp(i) for i,Mi in enumerate(ML) ]
def revolve_QuadMesh(n0, e0, nr, ang=None): """it takes a Quad mesh on xy and revolve it along the z axis nr times by ang. If ang==None, then it is calculated in order to fill 360 degrees with the nr revolutions.""" if ang==None: ang=360./nr for i in range(int(nr)): n1=Formex(n0).rotate(-ang, 1)[:].reshape(-1, 3) n, e=connectMesh(n0,n1,e0) n0=n1.copy() parts.append(Formex(n[e], eltype='Hex8')) femodels = [part.feModel() for part in parts] nodes,elems = mergeModels(femodels) elems=concatenate([elems], 0).reshape(-1, 8) return nodes, elems clear() #create a 2D xy mesh n=4 G=simple.rectangle(1,1,1.,1.).replic(n,1.,dir=1).replic(n,1.,dir=0) draw(G, color='red') view('front') sleep(1) #create a 3D axial-symmetric mesh by REVOLVING n0, e0=G.feModel() parts=[] n, e=revolve_QuadMesh(n0, e0, nr=4, ang=20) C=Formex(n[e], eltype='Hex8') #check if there are Wedge elements in the global Hex mesh w, h= detectHex2Wedge(C) W=Formex(w, eltype='Wedge6')
draw(x1,color=blue) message('This is the set of nodes in cartesian coordinates') draw(x2,color=red) drawNumbers(x2,color=red) drawNumbers(x1) n = 8 stype = ask("Select type of structure",['Cancel','1D','2D','3D']) if stype == 'Cancel': exit() sdim = int(stype[0]) if sdim == 1: F = simple.line([0.,0.,0.],[1.,1.,0.],10) elif sdim == 2: F = simple.rectangle(1,1,1.,1.) else: v = array(elements.Hex8.vertices) f = array(elements.Hex8.faces) F = Formex(v[f]) if sdim > 1: for i in range(sdim): F = F.replic(n,1.,dir=i) if sdim < tdim: F = F.trl(2,0.5) clear() message('This is the initial Formex') FA=draw(F) sz = F.sizes()
def run(): # GEOMETRICAL PARAMETERS FOR HE200B wide flange beam h = 200. #beam height b = 200. #flange width tf = 15. #flange thickness tw = 9. #body thickness l = 400. #beam length r = 18. #filling radius # MESH PARAMETERS el = 20 #number of elements along the length etb = 2 #number of elements over half of the thickness of the body ehb = 5 #number of elements over half of the height of the body etf = 5 #number of elements over the thickness of the flange ewf = 8 #number of elements over half of the width of the flange er = 6 #number of elements in the circular segment Body = simple.rectangle(etb, ehb, tw / 2., h / 2. - tf - r) Flange1 = simple.rectangle(er / 2, etf - etb, tw / 2. + r, tf - tw / 2.).translate( [0., h / 2. - (tf - tw / 2.), 0.]) Flange2 = simple.rectangle(ewf, etf - etb, b / 2. - r - tw / 2., tf - tw / 2.).translate( [tw / 2. + r, h / 2. - (tf - tw / 2.), 0.]) Flange3 = simple.rectangle(ewf, etb, b / 2. - r - tw / 2., tw / 2.).translate([tw / 2. + r, h / 2. - tf, 0.]) c1a = simple.line([0, h / 2 - tf - r, 0], [0, h / 2 - tf + tw / 2, 0], er / 2) c1b = simple.line([0, h / 2 - tf + tw / 2, 0], [tw / 2 + r, h / 2 - tf + tw / 2, 0], er / 2) c1 = c1a + c1b c2 = simple.circle(90. / er, 0., 90.).reflect(0).scale(r).translate( [tw / 2 + r, h / 2 - tf - r, 0]) Filled = simple.connectCurves(c2, c1, etb) Quarter = Body + Filled + Flange1 + Flange2 + Flange3 Half = Quarter + Quarter.reflect(1).reverse() Full = Half + Half.reflect(0).reverse() Section = Full.toMesh() clear() draw(Section, color=red) #return #pause() method = ask("Choose extrude method:", [ 'Cancel', 'Sweep', 'Connect', 'Extrude', 'ExtrudeQuadratic', 'Revolve', 'RevolveLoop' ]) import timer t = timer.Timer() if method == 'Sweep': L = simple.line([0, 0, 0], [0, 0, l], el) x = concatenate([L.coords[:, 0], L.coords[-1:, 1]]) path = curve.PolyLine(x) Beam = Section.sweep(path, normal=[0., 0., 1.], upvector=[0., 1., 0.]) elif method == 'Connect': Section1 = Section.trl([0, 0, l]) Beam = Section.connect(Section1, el) elif method == 'Extrude': Beam = Section.extrude(el, step=l / el, dir=2) elif method == 'ExtrudeQuadratic': Section = Section.convert('quad9') Beam = Section.extrude(el, step=l / el, dir=2, degree=2) elif method == 'Revolve': Beam = Section.revolve(el, axis=1, angle=60., around=[-l, 0., 0.]) elif method == 'RevolveLoop': Beam = Section.revolve(el, axis=1, angle=240., around=[-l, 0., 0.], loop=True) else: return print("Computing: %s seconds" % t.seconds()) #print Beam.prop #print Beam.elems.shape t.reset() clear() #draw(Beam,color='red',linewidth=2) draw(Beam.getBorderMesh(), color='red', linewidth=2) print("Drawing: %s seconds" % t.seconds()) export({'Beam': Beam})