Ejemplo n.º 1
0
def smallestDirection(x,method='inertia',return_size=False):
    """Return the direction of the smallest dimension of a Coords

    - `x`: a Coords-like array
    - `method`: one of 'inertia' or 'random'
    - return_size: if True and `method` is 'inertia', a tuple of a direction
      vector and the size  along that direction and the cross directions;
      else, only return the direction vector.
    """
    x = x.reshape(-1,3)
    if method == 'inertia':
        # The idea is to take the smallest dimension in a coordinate
        # system aligned with the global axes.
        C,r,Ip,I = x.inertia()
        X = x.trl(-C).rot(r)
        sizes = X.sizes()
        i = sizes.argmin()
        # r gives the directions as column vectors!
        # TODO: maybe we should change that
        N = r[:,i]
        if return_size:
            return N,sizes[i]
        else:
            return N
    elif method == 'random':
        # Take the mean of the normals on randomly created triangles
        from plugins.trisurface import TriSurface
        n = x.shape[0]
        m = 3 * (n // 3)
        e = arange(m)
        random.shuffle(e)
        if n > m:
            e = concatenate([e,[0,1,n-1]])
        el = e[-3:]
        S = TriSurface(x,e.reshape(-1,3))
        A,N = S.areaNormals()
        ok = where(isnan(N).sum(axis=1) == 0)[0]
        N = N[ok]
        N = N*N
        N = N.mean(axis=0)
        N = sqrt(N)
        N = normalize(N)
        return N
Ejemplo n.º 2
0
def createShellModel():
    """Create the Finite Element Model.

    It is supposed here that the Geometry has been created and is available
    as a global variable F.
    """
    
    # Turn the Formex structure into a TriSurface
    # This guarantees that element i of the Formex is element i of the TriSurface
    S = TriSurface(F)
    print "The structure has %s nodes, %s edges and %s faces" % (S.ncoords(),S.nedges(),S.nfaces())
    nodes = S.coords
    elems = S.elems  # the triangles

    clear()
    draw(F)

    # Shell section and material properties
    # VALUES SHOULD BE SET CORRECTLY

    glass_plate = { 
        'name': 'glass_plate',
        'sectiontype': 'shell',
        'thickness': 18,
        'material': 'glass',
        }
    glass = {
        'name': 'glass',
        'young_modulus': 72000,
        'shear_modulus': 26200,
        'density': 2.5e-9,        # T/mm**3
        }
    print glass_plate
    print glass
    glasssection = ElemSection(section=glass_plate,material=glass)

    PDB = PropertyDB()
    # All elements have same property:
    PDB.elemProp(set=arange(len(elems)),section=glasssection,eltype='STRI3')    

    # Calculate the nodal loads

    # Area of triangles
    area,normals = S.areaNormals()
    print "Area:\n%s" % area

    ### DEFINE LOAD CASE (ask user) ###
    res = askItems([('Glass',True),('Snow',False)])
    if not res:
        return

    step = 0
    if res['Glass']:
        step += 1
        NODLoad = zeros((S.ncoords(),3))
        # add the GLASS weight
        wgt = 450e-6 # N/mm**2
        # Or, calculate weight from density:
        # wgt = glass_plate['thickness'] * glass['density'] * 9810 
        # assemble uniform glass load
        for e,a in zip(S.elems,area):
            NODLoad[e] += [ 0., 0., - a * wgt / 3 ]
        # Put the nodal loads in the properties database
        for i,P in enumerate(NODLoad):
            PDB.nodeProp(tag=step,set=i,cload=[P[0],P[1],P[2],0.,0.,0.])

    if res['Snow']:
        step += 1
        NODLoad = zeros((S.ncoords(),3))
        # add NON UNIFORM SNOW
        fn = 'hesperia-nieve.prop'
        snowp = fromfile(fn,sep=',')
        snow_uniform = 320e-6 # N/mm**2
        snow_non_uniform = { 1:333e-6, 2:133e-6, 3:133e-6, 4:266e-6, 5:266e-6, 6:667e-6 }
        # assemble non-uniform snow load
        for e,a,p in zip(S.elems,area,snowp):
            NODLoad[e] += [ 0., 0., - a * snow_non_uniform[p] / 3]
        # Put the nodal loads in the properties database
        for i,P in enumerate(NODLoad):
            PDB.nodeProp(tag=step,set=[i],cload=[P[0],P[1],P[2],0.,0.,0.])

    # Get support nodes
    botnodes = where(isClose(nodes[:,2], 0.0))[0]
    bot = nodes[botnodes].reshape((-1,1,3))
    pf.message("There are %s support nodes." % bot.shape[0])

    botofs = bot + [ 0.,0.,-0.2]
    bbot2 = concatenate([bot,botofs],axis=1)
    print bbot2.shape
    S = Formex(bbot2)
    draw(S)
    
##     np_central_loaded = NodeProperty(3, displacement=[[1,radial_displacement]],coords='cylindrical',coordset=[0,0,0,0,0,1])
##     #np_transf = NodeProperty(0,coords='cylindrical',coordset=[0,0,0,0,0,1])

##     # Radial movement only
##     np_fixed = NodeProperty(1,bound=[0,1,1,0,0,0],coords='cylindrical',coordset=[0,0,0,0,0,1])
    
    # Since we left out the ring beam, we enforce no movement at the botnodes
    bc = PDB.nodeProp(set=botnodes,bound=[1,1,1,0,0,0],csys=CoordSystem('C',[0,0,0,0,0,1]))

    # And we record the name of the bottom nodes set
    botnodeset = Nset(bc.nr)

    fe_model = Dict(dict(nodes=nodes,elems=elems,prop=PDB,botnodeset=botnodeset,nsteps=step))
    export({'fe_model':fe_model})
    smooth()
    lights(False)
Ejemplo n.º 3
0
def createFrameModel():
    """Create the Finite Element Model.

    It is supposed here that the Geometry has been created and is available
    as a global variable F.
    """
    wireframe()
    lights(False)
    
    # Turn the Formex structure into a TriSurface
    # This guarantees that element i of the Formex is element i of the TriSurface
    S = TriSurface(F)
    nodes = S.coords
    elems = S.elems  # the triangles

    # Create edges and faces from edges
    print "The structure has %s nodes, %s edges and %s faces" % (S.ncoords(),S.nedges(),S.nfaces())

    # Create the steel structure
    E = Formex(nodes[S.getEdges()])
    clear()
    draw(E)
    
    # Get the tri elements that are part of a quadrilateral:
    prop = F.prop
    quadtri = S.getFaceEdges()[prop==6]
    nquadtri = quadtri.shape[0]
    print "%s triangles are part of quadrilateral faces" % nquadtri
    if nquadtri > 0:
        # Create triangle definitions of the quadtri faces
        tri = Connectivity.tangle(quadtri,S.getEdges())
        D = Formex(nodes[tri])
        clear()
        flatwire()
        draw(D,color='yellow')

    conn = connections(quadtri)
    print conn

    # Filter out the single connection edges
    internal = [ c[0] for c in conn if len(c[1]) > 1 ]
    print "Internal edges in quadrilaterals: %s" % internal
    
    E = Formex(nodes[S.getEdges()],1)
    E.prop[internal] = 6
    wireframe()
    clear()
    draw(E)

    # Remove internal edges
    tubes = S.getEdges()[E.prop != 6]

    print "Number of tube elements after removing %s internals: %s" % (len(internal),tubes.shape[0])

    D = Formex(nodes[tubes],1)
    clear()
    draw(D)

    # Beam section and material properties
    b = 60
    h = 100
    t = 4
    b1 = b-2*t
    h1 = h-2*t
    A = b*h - b1*h1
    print b*h**3
    I1 = (b*h**3 - b1*h1**3) / 12
    I2 = (h*b**3 - h1*b1**3) / 12
    I12 = 0
    J = 4 * A**2 / (2*(b+h)/t)

    tube = { 
        'name':'tube',
        'cross_section': A,
        'moment_inertia_11': I1,
        'moment_inertia_22': I2,
        'moment_inertia_12': I12,
        'torsional_constant': J
        }
    steel = {
        'name':'steel',
        'young_modulus' : 206000,
        'shear_modulus' : 81500,
        'density' : 7.85e-9,
        }
    print tube
    print steel

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

    # Calculate the nodal loads

    # Area of triangles
    area,normals = S.areaNormals()
    print "Area:\n%s" % area
    # compute bar lengths
    bars = nodes[tubes]
    barV = bars[:,1,:] - bars[:,0,:]
    barL = sqrt((barV*barV).sum(axis=-1))
    print "Member length:\n%s" % barL


    ### DEFINE LOAD CASE (ask user) ###
    res = askItems([('Steel',True),
                    ('Glass',True),
                    ('Snow',False),
                    ('Solver',None,'select',['Calpy','Abaqus']),
                    ])
    if not res:
        return

    nlc = 0
    for lc in [ 'Steel','Glass','Snow' ]:
        if res[lc]:
            nlc += 1 
    NODLoad = zeros((nlc,S.ncoords(),3))

    nlc = 0
    if res['Steel']:
        # the STEEL weight
        lwgt = steel['density'] * tube['cross_section'] * 9810  # mm/s**2
        print "Weight per length %s" % lwgt
        # assemble steel weight load
        for e,L in zip(tubes,barL):
            NODLoad[nlc,e] += [ 0., 0., - L * lwgt / 2 ]
        nlc += 1
        
    if res['Glass']:
        # the GLASS weight
        wgt = 450e-6 # N/mm**2
        # assemble uniform glass load
        for e,a in zip(S.elems,area):
            NODLoad[nlc,e] += [ 0., 0., - a * wgt / 3 ]
        nlc += 1
        
    if res['Snow']:
        # NON UNIFORM SNOW
        fn = 'hesperia-nieve.prop'
        snowp = fromfile(fn,sep=',')
        snow_uniform = 320e-6 # N/mm**2
        snow_non_uniform = { 1:333e-6, 2:133e-6, 3:133e-6, 4:266e-6, 5:266e-6, 6:667e-6 }

        # assemble non-uniform snow load
        for e,a,p in zip(S.elems,area,snowp):
            NODLoad[nlc,e] += [ 0., 0., - a * snow_non_uniform[p] / 3]
        nlc += 1

    # For Abaqus: put the nodal loads in the properties database
    print NODLoad
    PDB = PropertyDB()
    for lc in range(nlc):
        for i,P in enumerate(NODLoad[lc]):
            PDB.nodeProp(tag=lc,set=i,cload=[P[0],P[1],P[2],0.,0.,0.])

    # Get support nodes
    botnodes = where(isClose(nodes[:,2], 0.0))[0]
    bot = nodes[botnodes]
    pf.message("There are %s support nodes." % bot.shape[0])

    # Upper structure
    nnodes = nodes.shape[0]              # node number offset
    ntubes = tubes.shape[0]              # element number offset
    
    PDB.elemProp(set=arange(ntubes),section=tubesection,eltype='FRAME3D')    
    
    # Create support systems (vertical beams)
    bot2 = bot + [ 0.,0.,-200.]         # new nodes 200mm below bot
    botnodes2 = arange(botnodes.shape[0]) + nnodes  # node numbers
    nodes = concatenate([nodes,bot2])
    supports = column_stack([botnodes,botnodes2])
    elems = concatenate([tubes,supports])
    ## !!!
    ## THIS SHOULD BE FIXED !!!
    supportsection = ElemSection(material=steel,section={ 
        'name':'support',
        'cross_section': A,
        'moment_inertia_11': I1,
        'moment_inertia_22': I2,
        'moment_inertia_12': I12,
        'torsional_constant': J
        })
    PDB.elemProp(set=arange(ntubes,elems.shape[0]),section=supportsection,eltype='FRAME3D')

    # Finally, the botnodes2 get the support conditions
    botnodes = botnodes2

##     # Radial movement only
##     np_fixed = NodeProperty(1,bound=[0,1,1,0,0,0],coords='cylindrical',coordset=[0,0,0,0,0,1])
    
##     # No movement, since we left out the ring beam
##     for i in botnodes:
##         NodeProperty(i,bound=[1,1,1,0,0,0],coords='cylindrical',coordset=[0,0,0,0,0,1])

##     np_central_loaded = NodeProperty(3, displacement=[[1,radial_displacement]],coords='cylindrical',coordset=[0,0,0,0,0,1])
##     #np_transf = NodeProperty(0,coords='cylindrical',coordset=[0,0,0,0,0,1])
    
    # Draw the supports
    S = connect([Formex(bot),Formex(bot2)])
    draw(S,color='black')

    if res['Solver'] == 'Calpy':
        fe_model = Dict(dict(solver='Calpy',nodes=nodes,elems=elems,prop=PDB,loads=NODLoad,botnodes=botnodes,nsteps=nlc))
    else:
        fe_model = Dict(dict(solver='Abaqus',nodes=nodes,elems=elems,prop=PDB,botnodes=botnodes,nsteps=nlc))
    export({'fe_model':fe_model})
    print "FE model created and exported as 'fe_model'"
Ejemplo n.º 4
0
def createShellModel():
    """Create the Finite Element Model.

    It is supposed here that the Geometry has been created and is available
    as a global variable F.
    """

    # Turn the Formex structure into a TriSurface
    # This guarantees that element i of the Formex is element i of the TriSurface
    S = TriSurface(F)
    print("The structure has %s nodes, %s edges and %s faces" %
          (S.ncoords(), S.nedges(), S.nfaces()))
    nodes = S.coords
    elems = S.elems  # the triangles

    clear()
    draw(F)

    # Shell section and material properties
    # VALUES SHOULD BE SET CORRECTLY

    glass_plate = {
        'name': 'glass_plate',
        'sectiontype': 'shell',
        'thickness': 18,
        'material': 'glass',
    }
    glass = {
        'name': 'glass',
        'young_modulus': 72000,
        'shear_modulus': 26200,
        'density': 2.5e-9,  # T/mm**3
    }
    print(glass_plate)
    print(glass)
    glasssection = ElemSection(section=glass_plate, material=glass)

    PDB = PropertyDB()
    # All elements have same property:
    PDB.elemProp(set=arange(len(elems)), section=glasssection, eltype='STRI3')

    # Calculate the nodal loads

    # Area of triangles
    area, normals = S.areaNormals()
    print("Area:\n%s" % area)

    ### DEFINE LOAD CASE (ask user) ###
    res = askItems([('Glass', True), ('Snow', False)])
    if not res:
        return

    step = 0
    if res['Glass']:
        step += 1
        NODLoad = zeros((S.ncoords(), 3))
        # add the GLASS weight
        wgt = 450e-6  # N/mm**2
        # Or, calculate weight from density:
        # wgt = glass_plate['thickness'] * glass['density'] * 9810
        # assemble uniform glass load
        for e, a in zip(S.elems, area):
            NODLoad[e] += [0., 0., -a * wgt / 3]
        # Put the nodal loads in the properties database
        for i, P in enumerate(NODLoad):
            PDB.nodeProp(tag=step, set=i, cload=[P[0], P[1], P[2], 0., 0., 0.])

    if res['Snow']:
        step += 1
        NODLoad = zeros((S.ncoords(), 3))
        # add NON UNIFORM SNOW
        fn = '../data/hesperia-nieve.prop'
        snowp = fromfile(fn, sep=',')
        snow_uniform = 320e-6  # N/mm**2
        snow_non_uniform = {
            1: 333e-6,
            2: 133e-6,
            3: 133e-6,
            4: 266e-6,
            5: 266e-6,
            6: 667e-6
        }
        # assemble non-uniform snow load
        for e, a, p in zip(S.elems, area, snowp):
            NODLoad[e] += [0., 0., -a * snow_non_uniform[p] / 3]
        # Put the nodal loads in the properties database
        for i, P in enumerate(NODLoad):
            PDB.nodeProp(tag=step,
                         set=[i],
                         cload=[P[0], P[1], P[2], 0., 0., 0.])

    # Get support nodes
    botnodes = where(isClose(nodes[:, 2], 0.0))[0]
    bot = nodes[botnodes].reshape((-1, 1, 3))
    pf.message("There are %s support nodes." % bot.shape[0])

    botofs = bot + [0., 0., -0.2]
    bbot2 = concatenate([bot, botofs], axis=1)
    print(bbot2.shape)
    S = Formex(bbot2)
    draw(S)

    ##     np_central_loaded = NodeProperty(3, displacement=[[1,radial_displacement]],coords='cylindrical',coordset=[0,0,0,0,0,1])
    ##     #np_transf = NodeProperty(0,coords='cylindrical',coordset=[0,0,0,0,0,1])

    ##     # Radial movement only
    ##     np_fixed = NodeProperty(1,bound=[0,1,1,0,0,0],coords='cylindrical',coordset=[0,0,0,0,0,1])

    # Since we left out the ring beam, we enforce no movement at the botnodes
    bc = PDB.nodeProp(set=botnodes,
                      bound=[1, 1, 1, 0, 0, 0],
                      csys=CoordSystem('C', [0, 0, 0, 0, 0, 1]))

    # And we record the name of the bottom nodes set
    botnodeset = Nset(bc.nr)

    fe_model = Dict(
        dict(nodes=nodes,
             elems=elems,
             prop=PDB,
             botnodeset=botnodeset,
             nsteps=step))
    export({'fe_model': fe_model})
    smooth()
    lights(False)
Ejemplo n.º 5
0
def createFrameModel():
    """Create the Finite Element Model.

    It is supposed here that the Geometry has been created and is available
    as a global variable F.
    """
    wireframe()
    lights(False)

    # Turn the Formex structure into a TriSurface
    # This guarantees that element i of the Formex is element i of the TriSurface
    S = TriSurface(F)
    nodes = S.coords
    elems = S.elems  # the triangles

    # Create edges and faces from edges
    print("The structure has %s nodes, %s edges and %s faces" %
          (S.ncoords(), S.nedges(), S.nfaces()))

    # Remove the edges between to quad triangles
    drawNumbers(S.coords)
    quadtri = where(S.prop == 6)[0]
    nquadtri = quadtri.shape[0]
    print("%s triangles are part of quadrilateral faces" % nquadtri)
    faces = S.getElemEdges()[quadtri]
    cnt, ind, xbin = histogram2(faces.reshape(-1), arange(faces.max() + 1))
    rem = where(cnt == 2)[0]
    print("Total edges %s" % len(S.edges))
    print("Removing %s edges" % len(rem))
    edges = S.edges[complement(rem, n=len(S.edges))]
    print("Remaining edges %s" % len(edges))

    # Create the steel structure
    E = Formex(nodes[edges])
    clear()
    draw(E)

    warning("Beware! This script is currently under revision.")

    conn = connections(quadtri)
    print(conn)

    # Filter out the single connection edges
    internal = [c[0] for c in conn if len(c[1]) > 1]
    print("Internal edges in quadrilaterals: %s" % internal)

    E = Formex(nodes[edges], 1)
    E.prop[internal] = 6
    wireframe()
    clear()
    draw(E)

    # Remove internal edges
    tubes = edges[E.prop != 6]

    print("Number of tube elements after removing %s internals: %s" %
          (len(internal), tubes.shape[0]))

    D = Formex(nodes[tubes], 1)
    clear()
    draw(D)

    # Beam section and material properties
    b = 60
    h = 100
    t = 4
    b1 = b - 2 * t
    h1 = h - 2 * t
    A = b * h - b1 * h1
    print(b * h**3)
    I1 = (b * h**3 - b1 * h1**3) / 12
    I2 = (h * b**3 - h1 * b1**3) / 12
    I12 = 0
    J = 4 * A**2 / (2 * (b + h) / t)

    tube = {
        'name': 'tube',
        'cross_section': A,
        'moment_inertia_11': I1,
        'moment_inertia_22': I2,
        'moment_inertia_12': I12,
        'torsional_constant': J
    }
    steel = {
        'name': 'steel',
        'young_modulus': 206000,
        'shear_modulus': 81500,
        'density': 7.85e-9,
    }
    print(tube)
    print(steel)

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

    # Calculate the nodal loads

    # Area of triangles
    area, normals = S.areaNormals()
    print("Area:\n%s" % area)
    # compute bar lengths
    bars = nodes[tubes]
    barV = bars[:, 1, :] - bars[:, 0, :]
    barL = sqrt((barV * barV).sum(axis=-1))
    print("Member length:\n%s" % barL)

    ### DEFINE LOAD CASE (ask user) ###
    res = askItems([
        _I('Steel', True),
        _I('Glass', True),
        _I('Snow', False),
        _I('Solver', choices=['Calpy', 'Abaqus']),
    ])
    if not res:
        return

    nlc = 0
    for lc in ['Steel', 'Glass', 'Snow']:
        if res[lc]:
            nlc += 1
    NODLoad = zeros((nlc, S.ncoords(), 3))

    nlc = 0
    if res['Steel']:
        # the STEEL weight
        lwgt = steel['density'] * tube['cross_section'] * 9810  # mm/s**2
        print("Weight per length %s" % lwgt)
        # assemble steel weight load
        for e, L in zip(tubes, barL):
            NODLoad[nlc, e] += [0., 0., -L * lwgt / 2]
        nlc += 1

    if res['Glass']:
        # the GLASS weight
        wgt = 450e-6  # N/mm**2
        # assemble uniform glass load
        for e, a in zip(S.elems, area):
            NODLoad[nlc, e] += [0., 0., -a * wgt / 3]
        nlc += 1

    if res['Snow']:
        # NON UNIFORM SNOW
        fn = '../data/hesperia-nieve.prop'
        snowp = fromfile(fn, sep=',')
        snow_uniform = 320e-6  # N/mm**2
        snow_non_uniform = {
            1: 333e-6,
            2: 133e-6,
            3: 133e-6,
            4: 266e-6,
            5: 266e-6,
            6: 667e-6
        }

        # assemble non-uniform snow load
        for e, a, p in zip(S.elems, area, snowp):
            NODLoad[nlc, e] += [0., 0., -a * snow_non_uniform[p] / 3]
        nlc += 1

    # For Abaqus: put the nodal loads in the properties database
    print(NODLoad)
    PDB = PropertyDB()
    for lc in range(nlc):
        for i, P in enumerate(NODLoad[lc]):
            PDB.nodeProp(tag=lc, set=i, cload=[P[0], P[1], P[2], 0., 0., 0.])

    # Get support nodes
    botnodes = where(isClose(nodes[:, 2], 0.0))[0]
    bot = nodes[botnodes]
    pf.message("There are %s support nodes." % bot.shape[0])

    # Upper structure
    nnodes = nodes.shape[0]  # node number offset
    ntubes = tubes.shape[0]  # element number offset

    PDB.elemProp(set=arange(ntubes), section=tubesection, eltype='FRAME3D')

    # Create support systems (vertical beams)
    bot2 = bot + [0., 0., -200.]  # new nodes 200mm below bot
    botnodes2 = arange(botnodes.shape[0]) + nnodes  # node numbers
    nodes = concatenate([nodes, bot2])
    supports = column_stack([botnodes, botnodes2])
    elems = concatenate([tubes, supports])
    ## !!!
    ## THIS SHOULD BE FIXED !!!
    supportsection = ElemSection(material=steel,
                                 section={
                                     'name': 'support',
                                     'cross_section': A,
                                     'moment_inertia_11': I1,
                                     'moment_inertia_22': I2,
                                     'moment_inertia_12': I12,
                                     'torsional_constant': J
                                 })
    PDB.elemProp(set=arange(ntubes, elems.shape[0]),
                 section=supportsection,
                 eltype='FRAME3D')

    # Finally, the botnodes2 get the support conditions
    botnodes = botnodes2

    ##     # Radial movement only
    ##     np_fixed = NodeProperty(1,bound=[0,1,1,0,0,0],coords='cylindrical',coordset=[0,0,0,0,0,1])

    ##     # No movement, since we left out the ring beam
    ##     for i in botnodes:
    ##         NodeProperty(i,bound=[1,1,1,0,0,0],coords='cylindrical',coordset=[0,0,0,0,0,1])

    ##     np_central_loaded = NodeProperty(3, displacement=[[1,radial_displacement]],coords='cylindrical',coordset=[0,0,0,0,0,1])
    ##     #np_transf = NodeProperty(0,coords='cylindrical',coordset=[0,0,0,0,0,1])

    # Draw the supports
    S = connect([Formex(bot), Formex(bot2)])
    draw(S, color='black')

    if res['Solver'] == 'Calpy':
        fe_model = Dict(
            dict(solver='Calpy',
                 nodes=nodes,
                 elems=elems,
                 prop=PDB,
                 loads=NODLoad,
                 botnodes=botnodes,
                 nsteps=nlc))
    else:
        fe_model = Dict(
            dict(solver='Abaqus',
                 nodes=nodes,
                 elems=elems,
                 prop=PDB,
                 botnodes=botnodes,
                 nsteps=nlc))
    export({'fe_model': fe_model})
    print("FE model created and exported as 'fe_model'")