Beispiel #1
0
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
Beispiel #2
0
def createRectPart(res=None):
    """Create a rectangular domain from user input"""
    if not checkNoModel():
        return

    if res is None:
        res = askItems([
            _I('P0',
               P[0],
               itemtype='point',
               ndim=2,
               tooltip='The x- and y-value of one of the corners'),
            _I('P2',
               P[2],
               itemtype='point',
               ndim=2,
               tooltip='The x- and y-value of the opposite corner'),
            _I('nx', nx, tooltip='Number of elements along side 0-1'),
            _I('ny', ny, tooltip='Number of elements along side 1-2'),
            _I('eltype',
               eltype,
               itemtype='radio',
               choices=['quad', 'tri-u', 'tri-d']),
        ])
    if res:
        storeData(res)
        x, y = P.x, P.y
        if x[0] > x[2]:
            x[0], x[2] = x[2], x[0]
        if y[0] > y[2]:
            y[0], y[2] = y[2], y[0]
        diag = {'quad': '', 'tri-u': 'u', 'tri-d': 'd'}[eltype]
        M = rectangle(nx, ny, x[2] - x[0], y[2] - y[0],
                      diag=diag).toMesh().trl([x[0], y[0], 0])
        addPart(M)
Beispiel #3
0
def run():

    clear()
    smoothwire()
    layout(3)

    F = simple.rectangle(4, 3)
    M = F.toMesh()
    #M.attrib(color=yellow)

    # add some fields

    # 1. distance from point 7, defined at nodes

    data = length(M.coords - M.coords[7])
    M.addField('node', data, 'dist')

    # 2. convert to field defined at element nodes
    M.convertField('dist', 'elemn', 'distn')

    # 3. convert to field constant over elements
    M.convertField('distn', 'elemc', 'distc')

    print(M.fieldReport())

    # draw two fields
    viewport(0)
    drawField(M.getField('distn'))
    zoom(1.25)
    viewport(1)
    drawField(M.getField('distc'))
    zoom(1.25)
    viewport(2)
    drawField(M.getField('dist'))
    zoom(1.25)
Beispiel #4
0
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)
Beispiel #5
0
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)
Beispiel #6
0
def icon_wirenone():
    view('front')
    F = rectangle(2, 2)
    draw(F, color=red)
    smooth()
    zoomAll()
    zoomIn()
    zoomIn()
Beispiel #7
0
def icon_wireall():
    view('front')
    F = rectangle(2, 2)
    draw(F, color=red, linewidth=2)
    smoothwire()
    zoomAll()
    zoomIn()
    zoomIn()
Beispiel #8
0
def icon_wireborder():
    view('front')
    F = rectangle(2, 2)
    draw(F, color=red)
    B = F.toMesh().getBorderMesh()
    draw(B, color=black, linewidth=2, ontop=True, opak=True, nolight=True)
    smooth()
    zoomAll()
    zoomIn()
    zoomIn()
Beispiel #9
0
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})
Beispiel #10
0
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)
Beispiel #11
0
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.), True)
    view('myview1', True)

    setDrawOptions({'bbox': 'last'})
    for i in range(19):
        createView('myview2', (i * 10., 20., 0.), True)
        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)
Beispiel #12
0
def createQuadPart(res=None):
    """Create a quadrilateral domain from user input"""
    if not checkNoModel():
        return

    if res is None:
        res = askItems([
            _I('isopar',
               isopar,
               choices=['quad4', 'quad8', 'quad9'],
               tooltip='Isoparametric model'),
            _I('P0', P[0], itemtype='point', ndim=2, tooltip='First corner'),
            _I('P1', P[1], itemtype='point', ndim=2, tooltip='Second corner'),
            _I('P2', P[2], itemtype='point', ndim=2, tooltip='Third corner'),
            _I('P3', P[3], itemtype='point', ndim=2, tooltip='Fourth corner'),
            _I('P4', P[4], itemtype='point', ndim=2, tooltip='Midside P0-P1'),
            _I('P5', P[5], itemtype='point', ndim=2, tooltip='Midside P1-P2'),
            _I('P6', P[6], itemtype='point', ndim=2, tooltip='Midside P2-P3'),
            _I('P7', P[7], itemtype='point', ndim=2, tooltip='Midside P3-P4'),
            _I('P8', P[8], itemtype='point', ndim=2, tooltip='Center point'),
            _I('nx', nx),
            _I('ny', ny),
            _I('eltype',
               eltype,
               itemtype='radio',
               choices=['quad', 'tri-u', 'tri-d']),
        ],
                       enablers=[
                           ('isopar', 'quad8', 'P4', 'P5', 'P6', 'P7'),
                           ('isopar', 'quad9', 'P4', 'P5', 'P6', 'P7', 'P8'),
                       ])
    if res:
        storeData(res)
        diag = {'quad': '', 'tri-u': 'u', 'tri-d': 'd'}[eltype]
        xold = Coords(getattr(elements, isopar.capitalize()).vertices)
        np = int(isopar[-1])
        xnew = P[:np]
        M = rectangle(nx, ny, 1., 1.,
                      diag=diag).toMesh().isopar(isopar, xnew, xold)
        addPart(M)
Beispiel #13
0
def run():
    resetAll()
    setDrawOptions({'clear': True, 'shrink': True})
    delay(1)

    # A square domain of triangles
    n = 16
    F = simple.rectangle(n, n, diag='d')

    # Novation (Spots)
    m = 4
    h = 0.15 * n
    r = n // m
    s = n // r
    a = [[r * i, r * j, h] for j in range(1, s) for i in range(1, s)]

    for p in a:
        F = F.bump(2, p, lambda x: exp(-0.75 * x), [0, 1])

    # Define a plane
    plane_p = [3.2, 3.0, 0.0]
    plane_n = [2.0, 1.0, 0.0]
    #compute number of nodes above/below the plane
    dist = F.distanceFromPlane(plane_p, plane_n)
    above = (dist > 0.0).sum(-1)
    below = (dist < 0.0).sum(-1)

    # Define a line by a point and direction
    line_p = [0.0, 0.0, 0.0]
    line_n = [1., 1., 1. / 3]
    d = F.distanceFromLine(line_p, line_n)
    # compute number of nodes closer that 2.2 to line
    close = (d < 2.2).sum(-1)

    sel = [
        F.test(nodes=0, dir=0, min=1.5, max=3.5),
        F.test(nodes=[0, 1], dir=0, min=1.5, max=3.5),
        F.test(nodes=[0, 1, 2], dir=0, min=1.5, max=3.5),
        F.test(nodes='all', dir=1, min=1.5, max=3.5),
        F.test(nodes='any', dir=1, min=1.5, max=3.5),
        F.test(nodes='none', dir=1, min=1.5),
        (above > 0) * (below > 0),
        close == 3,
    ]

    txt = [
        'First node has x between 1.5 and 3.5',
        'First two nodes have x between 1.5 and 3.5',
        'First 3 nodes have x between 1.5 and 3.5',
        'All nodes have y between 1.5 and 3.5',
        'Any node has y between 1.5 and 3.5',
        'No node has y larger than 1.5',
        'Touching the plane P = [3.2,3.0,0.0], n = [2.0,1.0,0.0]',
        '3 nodes close to line through [0.0,0.0,0.0] and [1.0,1.0,1.0]',
    ]

    draw(F)

    color = getcfg('canvas/colormap')[1:]  # omit the black
    while len(color) < len(sel):
        color.extend(color)
    color[0:0] = ['black']  # restore the black
    prop = zeros(F.nelems())
    i = 1
    for s, t in zip(sel, txt):
        prop[s] = i
        F.setProp(prop)
        print('%s (%s): %s' % (color[i], sum(s), t))
        draw(F)
        i += 1

    print('Clip Formex to last selection')
    draw(F.clip(s), view=None)

    print('Clip complement')
    draw(F.cclip(s))
Beispiel #14
0
def Grid(nx=(1, 1, 1),
         ox=(0.0, 0.0, 0.0),
         dx=(1.0, 1.0, 1.0),
         lines='b',
         planes='b',
         linecolor=colors.black,
         planecolor=colors.white,
         alpha=0.3,
         **kargs):
    """Creates a (set of) grid(s) in (some of) the coordinate planes.

    Parameters:

    - `nx`: a list of 3 integers, specifying the number of divisions of the
      grid in the three coordinate directions. A zero value may be specified
      to avoid the grid to extend in that direction. Thus, setting the last
      value to zero will result in a planar grid in the xy-plane.
    - `ox`: a list of 3 floats: the origin of the grid.
    - `dx`: a list of 3 floats: the step size in each coordinate direction.
    - `planes`: one of 'first', 'box', 'all', 'no' (the string can be
      shortened to the first chartacter): specifies how many planes are
      drawn in each direction: 'f' only draws the first, 'b' draws the first
      and the last, resulting in a box, 'a' draws all planes,
      'n' draws no planes.

    Returns a list with up to two Meshes: the planes, and the lines.

    """
    from pyformex import simple
    from pyformex.olist import List
    from pyformex.mesh import Mesh
    G = List()

    planes = planes[:1].lower()
    P = []
    L = []
    for i in range(3):
        n0, n1, n2 = np.roll(nx, i)
        d0, d1, d2 = np.roll(dx, i)
        if n0 * n1:
            if planes != 'n':
                M = simple.rectangle(b=n0 * d0, h=n1 * d1)
                if n2:
                    if planes == 'b':
                        M = M.replic(2, dir=2, step=n2 * d2)
                    elif planes == 'a':
                        M = M.replic(n2 + 1, dir=2, step=d2)
                P.append(M.rollAxes(-i).toMesh())
            if lines != 'n':
                M = Formex('1').scale(n0*d0).replic(n1+1,dir=1,step=d1) + \
                    Formex('2').scale(n1*d1).replic(n0+1,dir=0,step=d0)
                if n2:
                    if lines == 'b':
                        M = M.replic(2, dir=2, step=n2 * d2)
                    elif lines == 'a':
                        M = M.replic(n2 + 1, dir=2, step=d2)

                L.append(M.rollAxes(-i).toMesh())

    if P:
        M = Mesh.concatenate(P)
        M.attrib(name='__grid_planes__',
                 mode='flat',
                 lighting=False,
                 color=planecolor,
                 alpha=alpha,
                 **kargs)
        G.append(M)
    if L:
        M = Mesh.concatenate(L)
        M.attrib(name='__grid_lines__',
                 mode='flat',
                 lighting=False,
                 color=linecolor,
                 alpha=0.6,
                 **kargs)
        G.append(M)

    return G.trl(ox)
Beispiel #15
0
    def __init__(self,
                 colorscale,
                 ncolors,
                 x,
                 y,
                 w,
                 h,
                 ngrid=0,
                 linewidth=None,
                 nlabel=-1,
                 size=18,
                 font=None,
                 dec=2,
                 scale=0,
                 lefttext=False,
                 **kargs):
        """Initialize the ColorLegend."""
        from pyformex.gui import colorscale as cs
        self.cl = cs.ColorLegend(colorscale, ncolors)
        self.x = float(x)
        self.y = float(y)
        self.w = float(w)
        self.h = float(h)
        self.ngrid = int(ngrid)
        if self.ngrid < 0:
            self.ngrid = ncolors
            if self.ngrid > 50:
                self.ngrid = 0
        self.linewidth = saneLineWidth(linewidth)
        self.nlabel = int(nlabel)
        if self.nlabel < 0:
            if self.ngrid > 0:
                self.nlabel = self.ngrid
            else:
                self.nlabel = ncolors
        self.dec = dec  # number of decimals
        self.scale = 10**scale  # scale all numbers with 10**scale
        self.lefttext = lefttext
        self.xgap = 4  # hor. gap between color bar and labels
        self.ygap = 4  # (min) vert. gap between labels

        F = simple.rectangle(1, ncolors, self.w,
                             self.h).trl([self.x, self.y, 0.])
        Actor.__init__(self,
                       F,
                       rendertype=2,
                       lighting=False,
                       color=self.cl.colors,
                       **kargs)

        if self.ngrid > 0:
            F = simple.rectangle(1, self.ngrid, self.w,
                                 self.h).trl([self.x, self.y, 0.])
            G = Actor(F,
                      rendertype=2,
                      lighting=False,
                      color=colors.black,
                      linewidth=self.linewidth,
                      mode='wireframe')
            self.children.append(G)

        # labels
        # print("LABELS: %s" % self.nlabel)
        if self.nlabel > 0:
            from pyformex.opengl import textext

            if font is None:
                font = FontTexture.default()
            elif isinstance(font, (str, unicode)):
                font = FontTexture(font, size)
            self.font = font
            fh = self.font.height
            pf.debug("FONT HEIGHT %s" % fh, pf.DEBUG.DRAW)

            if self.lefttext:
                x = F.coords[0, 0, 0] - self.xgap
                gravity = 'W'
            else:
                x = F.coords[0, 1, 0] + self.xgap
                gravity = 'E'

            # minimum label distance
            dh = fh + self.ygap
            da = self.h / self.nlabel

            # Check if labels will fit
            if da < dh and self.nlabel == ncolors:
                # reduce number of labels
                self.nlabel = int(self.h / dh)
                da = self.h / self.nlabel

            vals = cs.ColorLegend(colorscale, self.nlabel).limits
            #print("VALS",vals)

            ypos = self.y + da * np.arange(self.nlabel + 1)

            yok = self.y - 0.01 * dh
            for (y, v) in zip(ypos, vals):
                #print(y,v,yok)
                if y >= yok:
                    t = textext.Text(("%%.%df" % self.dec) % (v * self.scale),
                                     (x, y),
                                     size=size,
                                     gravity=gravity)
                    self.children.append(t)
                    yok = y + dh
Beispiel #16
0
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:
        # tetgen may not be available
        Bol = BolSurface.tetgen(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 pyformex.plugins.fe_abq import Interaction
    P.Prop(tag='init', generalinteraction=Interaction(name='interaction1', friction=0.1))
    P.Prop(tag='init', generalcontact='interaction1')

    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, initial=['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)
Beispiel #17
0
def run():
    smoothwire()
    # 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, name='Section', color=red)

    #pause()

    method = ask("Choose extrude method:", [
        'Cancel', 'Sweep', 'Connect', 'Extrude', 'ExtrudeQuadratic',
        'RevolveLoop', 'Revolve'
    ])

    from pyformex import timer
    t = timer.Timer()
    if method == 'Sweep':
        path = simple.line([0, 0, 0], [0, 0, l], el).toCurve()
        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, dir=2, length=l)

    elif method == 'ExtrudeQuadratic':
        Section = Section.convert('quad9')
        Beam = Section.extrude(el, dir=2, length=l, 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,name='Beam',color='red',linewidth=2)
    draw(Beam.getBorderMesh(), name='Beam', color='red', linewidth=2)
    print("Drawing: %s seconds" % t.seconds())
    export({'Beam': Beam})