Ejemplo n.º 1
0
    v = calpyModel.SolveSystem(s,f)
    print "Calpy analysis has finished --- Runtime was %s seconds." % (time.clock()-starttime)
    displ = fe_util.selectDisplacements (v,bcon)
    if verbose:
        print "Displacements",displ

    if flavia:
        flavia.WriteMeshFile(jobname,"Quadrilateral",model.nnodel,coord,nodes,matnr)
        res=flavia.ResultsFile(jobname)
        
    # compute stresses
    for lc in range(calpyModel.nloads):
        
        print "Results for load case %d" %(lc+1)
        print "Displacements"
        aprint(displ[:,:,lc],header=['x','y'],numbering=True)

        if flavia:
            flavia.WriteResultsHeader(res,'"Displacement" "Elastic Analysis"',lc+1,'Vector OnNodes')
            flavia.WriteResults(res,displ[:,:,lc])
            
        stresn = count = None
        i = 0
        for e,P in zip(model.elems,PlaneGrp):
            i += 1
            #P.debug = 1
            stresg = P.StressGP (v[:,lc],mats)
            if verbose:
                print "elem group %d" % i
                print "GP Stress\n", stresg
            
Ejemplo n.º 2
0
def runCalpyAnalysis(jobname=None,verbose=False,flavia=False):
    """Create data for Calpy analysis module and run Calpy on the data.

    While we could write an analysis file in the Calpy format and then
    run the Calpy program on it (like we did with Abaqus), we can (and do)
    take another road here: Calpy has a Python/numpy interface, allowing
    us to directly present the numerical data in arrays to the analysis
    module.
    It is supposed that the Finite Element model has been created and
    exported under the name 'fe_model'.
    """

    ############################
    # Load the needed calpy modules    
    from plugins import calpy_itf
    calpy_itf.check()
    import calpy
    calpy.options.optimize=True
    from calpy import femodel,fe_util,plane
    from calpy.arrayprint import aprint
    ############################

    if model is None:
        warn()
        return

    if jobname is None:
        # ask job name from user
        res = askItems([('JobName','FeEx'),('Verbose Mode',False)])
        if res:
            jobname = res['JobName']
            verbose = res['Verbose Mode']

    if not jobname:
        print "No Job Name: bailing out"
        return
   
    # OK, start calpy
    print "Starting the Calpy analysis module --- this might take some time"
    GD.app.processEvents()
    starttime = time.clock()

    Model = femodel.FeModel(2,"elast","Plane_Stress")
    Model.nnodes = model.coords.shape[0]
    Model.nelems = model.celems[-1]
    Model.nnodel = 4

    # 2D model in calpy needs 2D coordinates
    coords = model.coords[:,:2]
    if verbose:
        fe_util.PrintNodes(coords)

    # Boundary conditions
    bcon = zeros((Model.nnodes,2),dtype=int32)
    bcon[:,2:6] = 1 # leave only ux and uy
    for p in PDB.getProp(kind='n',attr=['bound']):
        bnd = where(p.bound)[0]
        if p.set is None:
            nod = arange(Model.nnodes)
        else:
            nod = array(p.set)
        for i in bnd:
            bcon[p.set,i] = 1
    fe_util.NumberEquations(bcon)
    if verbose:
        fe_util.PrintDofs(bcon,header=['ux','uy'])

    # The number of free DOFs remaining
    Model.ndof = bcon.max()
    print "Number of DOF's: %s" % Model.ndof

    
    # We extract the materials/sections from the property database
    matprops = PDB.getProp(kind='e',attr=['section'])
    
    # E, nu, thickness, rho
    mats = array([[mat.young_modulus,
                   mat.poisson_ratio,
                   mat.thickness,
                   0.0,      # rho was not defined in material
                   ] for mat in matprops]) 
    Model.nmats = mats.shape[0]
    if verbose:
        fe_util.PrintMats(mats,header=['E','nu','thick','rho'])

   
    ########### Find number of load cases ############
    Model.nloads = 1
    Model.PrintModelData()
    ngp = 2
    nzem = 3
    Model.banded = True


    # Create element definitions:
    # In calpy, each element is represented by nnod + 1 integer numbers:
    #    matnr,  node1, node2, .... 
    # Also notice that Calpy numbering starts at 1, not at 0 as customary
    # in pyFormex; therefore we add 1 to elems.
    matnr = zeros(Model.nelems,dtype=int32)
    for i,mat in enumerate(matprops):  # proces in same order as above!
        matnr[mat.set] = i+1

    PlaneGrp = []
    
    for i,e in enumerate(model.elems):
        j,k = model.celems[i:i+2]
        Plane = plane.Quad("part-%s" % i,[ngp,ngp],Model)
        Plane.debug = 0
        fe_util.PrintElements(e+1,matnr[j:k])
        Plane.AddElements(e+1,matnr[j:k],mats,coords,bcon)
        PlaneGrp.append(Plane)

    # Create load vectors
    # Calpy allows for multiple load cases in a single analysis.
    # However, our script currently puts all loads together in a single
    # load case. So the processing hereafter is rather simple, especially
    # since Calpy provides a function to assemble a single concentrated
    # load into the load vector. We initialize the load vector to zeros
    # and then add all the concentrated loads from the properties database.
    # A single concentrated load consists of 6 components, corresponding
    # to the 6 DOFs of a node.
    #
    # AssembleVector takes 3 arguments: the global vector in which to
    # assemble a nodal vector (length ndof), the nodal vector values
    # (length 6), and a list of indices specifying the positions of the
    # nodal DOFs in the global vector.
    # Beware: The function does not change the global vector, but merely
    # returns the value after assembling.
    # Also notice that the indexing inside the bcon array uses numpy
    # convention (starting at 0), thus no adding 1 is needed!
    print "Assembling Concentrated Loads"
    Model.nloads = 1
    f = zeros((Model.ndof,Model.nloads),float)
    for p in PDB.getProp('n',attr=['cload']):
        if p.set is None:
            nodeset = range(Model.nnodes)
        else:
            nodeset = p.set
        F = [0.0,0.0]
        for i,v in p.cload:
            if i in [0,1]:
                F[i] = v
        for n in nodeset:
            print F
            print "HALLO"
            f[:,0] = fe_util.AssembleVector(f[:,0],F,bcon[n])

    print "Assembling distributed loads"
    # This is a bit more complex. See Calpy for details
    # We first generate the input data, then read them with the
    # calpy femodel.ReadBoundaryLoads function and finally
    # assemble them with plane.addBoundaryLoads.
    for p in PDB.getProp('n',attr=['dload']):
        print p
    #idloads,dloads = plane.ReadBoundaryLoads(*nb,model.ndim)
    
    if verbose:
        print "Calpy.Loads"
        print f

    ############ Create global stiffness matrix ##########
    s = Model.ZeroStiffnessMatrix(0)
    for elgrp in PlaneGrp:
        s = elgrp.Assemble(s,mats,Model)
    #print "The complete stiffness matrix"
    #print s
    print f
    v = Model.SolveSystem(s,f)
    if verbose:
        print "Displacements",v
    print "Calpy analysis has finished --- Runtime was %s seconds." % (time.clock()-starttime)
    displ = fe_util.selectDisplacements (v,bcon)
    print displ.shape
    if verbose:
        print displ

    if flavia:
        flavia.WriteMeshFile(jobname,"Quadrilateral",model.nnodel,coord,nodes,matnr)
        res=flavia.ResultsFile(jobname)
        
    # compute stresses
    for l in range(Model.nloads):
        
        print "Results for load case %d" %(l+1)
        print "Displacements"
        aprint(displ[:,:,l],header=['x','y'],numbering=True)

        if flavia:
            flavia.WriteResultsHeader(res,'"Displacement" "Elastic Analysis"',l+1,'Vector OnNodes')
            flavia.WriteResults(res,displ[:,:,l])
            
        stresn = count = None
        i = 0
        for e,P in zip(model.elems,PlaneGrp):
            i += 1
            #P.debug = 1
            stresg = P.StressGP (v[:,l],mats)
            if verbose:
                print "elem group %d" % i
                print "GP Stress\n", stresg
            
            strese = P.GP2Nodes(stresg)
            if verbose:
                print "Nodal Element Stress\n", strese

            #print "Nodes",e+1
            stresn,count = P.NodalAcc(e+1,strese,nnod=Model.nnodes,nodata=stresn,nodn=count)
            #print stresn,count
            
        #print stresn.shape
        #print count.shape
        #print "TOTAL",stresn,count
        stresn /= count.reshape(-1,1)
        #print "AVG",stresn
        if verbose:
            print "Averaged Nodal Stress\n"
            aprint(stresn,header=['sxx','syy','sxy'],numbering=True)
                
        if flavia:
            flavia.WriteResultsHeader(res,'"Stress" "Elastic Analysis"',l+1,'Matrix OnNodes')
            flavia.WriteResults(res,stresn)

    
    DB = FeResult()
    DB.nodes = model.coords
    DB.nnodes = model.coords.shape[0]
    DB.nodid = arange(DB.nnodes)
    DB.elems = dict(enumerate(model.elems))
    DB.nelems = model.celems[-1]
    DB.Finalize()
    DB.data_size['S'] = 3
    #print DB.elems
    for lc in range(Model.nloads):
        DB.Increment(lc,0)
        d = zeros((Model.nnodes,3))
        d[:,:2] = displ[:,:,lc]
        DB.R['U'] = d
        DB.R['S'] = stresn
    postproc_menu.setDB(DB)
    info("You can now use the postproc menu to display results")
    export({'FeResult':DB})
Ejemplo n.º 3
0
def runCalpyAnalysis(jobname=None, verbose=False, flavia=False):
    """Create data for Calpy analysis module and run Calpy on the data.

    While we could write an analysis file in the Calpy format and then
    run the Calpy program on it (like we did with Abaqus), we can (and do)
    take another road here: Calpy has a Python/numpy interface, allowing
    us to directly present the numerical data in arrays to the analysis
    module.
    It is supposed that the Finite Element model has been created and
    exported under the name 'fe_model'.
    """

    ############################
    # Load the needed calpy modules
    from plugins import calpy_itf

    calpy_itf.check()
    import calpy

    calpy.options.optimize = True
    from calpy import femodel, fe_util, plane
    from calpy.arrayprint import aprint

    ############################

    checkWorkdir()

    if model is None:
        warn()
        return

    if jobname is None:
        # ask job name from user
        res = askItems([("JobName", feresult_name.peek()), ("Verbose Mode", False)])
        if res:
            jobname = res["JobName"]
            verbose = res["Verbose Mode"]

    if not jobname:
        print "No Job Name: bailing out"
        return

    # OK, start calpy
    print "Starting the Calpy analysis module --- this might take some time"
    GD.app.processEvents()
    starttime = time.clock()

    calpyModel = femodel.FeModel(2, "elast", "Plane_Stress")
    calpyModel.nnodes = model.coords.shape[0]
    calpyModel.nelems = model.celems[-1]
    calpyModel.nnodel = 4

    # 2D model in calpy needs 2D coordinates
    coords = model.coords[:, :2]
    if verbose:
        fe_util.PrintNodes(coords)

    # Boundary conditions
    bcon = zeros((calpyModel.nnodes, 2), dtype=int32)
    bcon[:, 2:6] = 1  # leave only ux and uy
    for p in PDB.getProp(kind="n", attr=["bound"]):
        bnd = where(p.bound)[0]
        if p.set is None:
            nod = arange(calpyModel.nnodes)
        else:
            nod = array(p.set)
        for i in bnd:
            bcon[p.set, i] = 1
    fe_util.NumberEquations(bcon)
    if verbose:
        fe_util.PrintDofs(bcon, header=["ux", "uy"])

    # The number of free DOFs remaining
    calpyModel.ndof = bcon.max()
    print "Number of DOF's: %s" % calpyModel.ndof

    # We extract the materials/sections from the property database
    matprops = PDB.getProp(kind="e", attr=["section"])

    # E, nu, thickness, rho
    mats = array(
        [
            [mat.young_modulus, mat.poisson_ratio, mat.thickness, 0.0]  # rho was not defined in material
            for mat in matprops
        ]
    )
    calpyModel.nmats = mats.shape[0]
    if verbose:
        fe_util.PrintMats(mats, header=["E", "nu", "thick", "rho"])

    ########### Find number of load cases ############
    calpyModel.nloads = 1
    calpyModel.PrintModelData()
    ngp = 2
    nzem = 3
    calpyModel.banded = True

    # Create element definitions:
    # In calpy, each element is represented by nnod + 1 integer numbers:
    #    matnr,  node1, node2, ....
    # Also notice that Calpy numbering starts at 1, not at 0 as customary
    # in pyFormex; therefore we add 1 to elems.
    matnr = zeros(calpyModel.nelems, dtype=int32)
    for i, mat in enumerate(matprops):  # proces in same order as above!
        matnr[mat.set] = i + 1

    NodesGrp = []
    MatnrGrp = []
    PlaneGrp = []

    for i, e in enumerate(model.elems):
        j, k = model.celems[i : i + 2]
        Plane = plane.Quad("part-%s" % i, [ngp, ngp], calpyModel)
        Plane.debug = 0
        PlaneGrp.append(Plane)
        NodesGrp.append(e + 1)
        MatnrGrp.append(matnr[j:k])
        if verbose:
            fe_util.PrintElements(NodesGrp[-1], MatnrGrp[-1])

        # Plane.AddElements(e+1,matnr[j:k],mats,coords,bcon)

    for Plane, nodenrs, matnrs in zip(PlaneGrp, NodesGrp, MatnrGrp):
        Plane.AddElements(nodenrs, matnrs, mats, coords, bcon)

    # Create load vectors
    # Calpy allows for multiple load cases in a single analysis.
    # However, our script currently puts all loads together in a single
    # load case. So the processing hereafter is rather simple, especially
    # since Calpy provides a function to assemble a single concentrated
    # load into the load vector. We initialize the load vector to zeros
    # and then add all the concentrated loads from the properties database.
    # A single concentrated load consists of 6 components, corresponding
    # to the 6 DOFs of a node.
    #
    # AssembleVector takes 3 arguments: the global vector in which to
    # assemble a nodal vector (length ndof), the nodal vector values
    # (length 6), and a list of indices specifying the positions of the
    # nodal DOFs in the global vector.
    # Beware: The function does not change the global vector, but merely
    # returns the value after assembling.
    # Also notice that the indexing inside the bcon array uses numpy
    # convention (starting at 0), thus no adding 1 is needed!
    print "Assembling Concentrated Loads"
    calpyModel.nloads = 1
    f = zeros((calpyModel.ndof, calpyModel.nloads), float)
    for p in PDB.getProp("n", attr=["cload"]):
        if p.set is None:
            nodeset = range(calpyModel.nnodes)
        else:
            nodeset = p.set
        F = [0.0, 0.0]
        for i, v in p.cload:
            if i in [0, 1]:
                F[i] = v
        for n in nodeset:
            f[:, 0] = fe_util.AssembleVector(f[:, 0], F, bcon[n])

    print "Assembling distributed loads"
    # This is a bit more complex. See Calpy for details
    # We first generate the input data in a string, then read them with the
    # calpy femodel.ReadBoundaryLoads function and finally assemble them with
    # plane.addBoundaryLoads. We have to this operation per element group.
    # The group number is stored in the property record.
    ngroups = model.ngroups()
    s = [""] * ngroups
    nb = [0] * ngroups
    loadcase = 1
    for p in PDB.getProp("e", attr=["eload"]):
        xload = yload = 0.0
        if p.label == "x":
            xload = p.value
        elif p.label == "y":
            yload = p.value
        # Because of the way we constructed the database, the set will
        # contain only one element, but let's loop over it anyway in case
        # one day we make the storage more effective
        # Also, remember calpy numbers are +1 !
        g = p.group
        print "Group %s" % g
        for e in p.set:
            s[g] += "%s %s %s %s %s\n" % (e + 1, p.edge + 1, loadcase, xload, yload)
            nb[g] += 1
    # print s,nb
    for nbi, si, nodes, matnr, Plane in zip(nb, s, NodesGrp, MatnrGrp, PlaneGrp):
        if nbi > 0:
            idloads, dloads = fe_util.ReadBoundaryLoads(nbi, calpyModel.ndim, si)
            # print idloads,dloads
            Plane.AddBoundaryLoads(f, calpyModel, idloads, dloads, nodes, matnr, coords, bcon, mats)

    if verbose:
        print "Calpy.Loads"
        print f

    ############ Create global stiffness matrix ##########
    s = calpyModel.ZeroStiffnessMatrix(0)
    for elgrp in PlaneGrp:
        s = elgrp.Assemble(s, mats, calpyModel)
    # print "The complete stiffness matrix"
    # print s

    ############ Solve the system of equations ##########
    v = calpyModel.SolveSystem(s, f)
    print "Calpy analysis has finished --- Runtime was %s seconds." % (time.clock() - starttime)
    displ = fe_util.selectDisplacements(v, bcon)
    if verbose:
        print "Displacements", displ

    if flavia:
        flavia.WriteMeshFile(jobname, "Quadrilateral", model.nnodel, coord, nodes, matnr)
        res = flavia.ResultsFile(jobname)

    # compute stresses
    for l in range(calpyModel.nloads):

        print "Results for load case %d" % (l + 1)
        print "Displacements"
        aprint(displ[:, :, l], header=["x", "y"], numbering=True)

        if flavia:
            flavia.WriteResultsHeader(res, '"Displacement" "Elastic Analysis"', l + 1, "Vector OnNodes")
            flavia.WriteResults(res, displ[:, :, l])

        stresn = count = None
        i = 0
        for e, P in zip(model.elems, PlaneGrp):
            i += 1
            # P.debug = 1
            stresg = P.StressGP(v[:, l], mats)
            if verbose:
                print "elem group %d" % i
                print "GP Stress\n", stresg

            strese = P.GP2Nodes(stresg)
            if verbose:
                print "Nodal Element Stress\n", strese

            # print "Nodes",e+1
            stresn, count = P.NodalAcc(e + 1, strese, nnod=calpyModel.nnodes, nodata=stresn, nodn=count)
            # print stresn,count

        # print stresn.shape
        # print count.shape
        # print "TOTAL",stresn,count
        stresn /= count.reshape(-1, 1)
        # print "AVG",stresn
        if verbose:
            print "Averaged Nodal Stress\n"
            aprint(stresn, header=["sxx", "syy", "sxy"], numbering=True)

        if flavia:
            flavia.WriteResultsHeader(res, '"Stress" "Elastic Analysis"', l + 1, "Matrix OnNodes")
            flavia.WriteResults(res, stresn)

    DB = FeResult()
    DB.nodes = model.coords
    DB.nnodes = model.coords.shape[0]
    DB.nodid = arange(DB.nnodes)
    DB.elems = dict(enumerate(model.elems))
    DB.nelems = model.celems[-1]
    DB.Finalize()
    DB.data_size["S"] = 3
    # print DB.elems
    for lc in range(calpyModel.nloads):
        DB.Increment(lc, 0)
        d = zeros((calpyModel.nnodes, 3))
        d[:, :2] = displ[:, :, lc]
        DB.R["U"] = d
        DB.R["S"] = stresn
    postproc_menu.setDB(DB)
    name = feresult_name.next()
    export({name: DB})
    showInfo("The results have been exported as %s\nYou can now use the postproc menu to display results" % name)
Ejemplo n.º 4
0
def runCalpyAnalysis(jobname=None,verbose=False,flavia=False):
    """Create data for Calpy analysis module and run Calpy on the data.

    While we could write an analysis file in the Calpy format and then
    run the Calpy program on it (like we did with Abaqus), we can (and do)
    take another road here: Calpy has a Python/numpy interface, allowing
    us to directly present the numerical data in arrays to the analysis
    module.
    It is supposed that the Finite Element model has been created and
    exported under the name 'fe_model'.
    """

    ############################
    # Load the needed calpy modules    
    from plugins import calpy_itf
    calpy_itf.check()

    ## # Load development version
    #import sys
    #sys.path.insert(0,'/home/bene/prj/calpy')
    #print sys.path

    import calpy
    reload(calpy)
    print(calpy.__path__)
    
    calpy.options.optimize=True
    from calpy import femodel,fe_util,plane
    from calpy.arrayprint import aprint
    ############################

    checkWorkdir()

    if model is None:
        warn()
        return

    if jobname is None:
        # ask job name from user
        res = askItems([('JobName',feresult_name.peek()),('Verbose Mode',False)])
        if res:
            jobname = res['JobName']
            verbose = res['Verbose Mode']

    if not jobname:
        print("No Job Name: bailing out")
        return
   
    # OK, start calpy
    print("Starting the Calpy analysis module --- this might take some time")
    pf.app.processEvents()
    starttime = time.clock()

    calpyModel = femodel.FeModel(2,"elast","Plane_Stress")
    calpyModel.nnodes = model.coords.shape[0]
    calpyModel.nelems = model.celems[-1]
    print([ e.shape for e in model.elems ])
    nplex = [ e.shape[1] for e in model.elems ]
    if min(nplex) != max(nplex):
        warning("All parts should have same element type")
        return
    
    calpyModel.nnodel = nplex[0]

    # 2D model in calpy needs 2D coordinates
    coords = model.coords[:,:2]
    if verbose:
        fe_util.PrintNodes(coords)

    # Boundary conditions
    bcon = zeros((calpyModel.nnodes,2),dtype=int32)
    bcon[:,2:6] = 1 # leave only ux and uy
    for p in PDB.getProp(kind='n',attr=['bound']):
        bnd = where(p.bound)[0]
        if p.set is None:
            nod = arange(calpyModel.nnodes)
        else:
            nod = array(p.set)
        for i in bnd:
            bcon[p.set,i] = 1
    fe_util.NumberEquations(bcon)
    if verbose:
        fe_util.PrintDofs(bcon,header=['ux','uy'])

    # The number of free DOFs remaining
    calpyModel.ndof = bcon.max()
    print("Number of DOF's: %s" % calpyModel.ndof)

    
    # We extract the materials/sections from the property database
    secprops = PDB.getProp(kind='e',attr=['section'])
    
    # E, nu, thickness, rho
    mats = array([[mat.young_modulus,
                   mat.poisson_ratio,
                   mat.thickness,
                   0.0,      # rho was not defined in material
                   ] for mat in secprops]) 
    calpyModel.nmats = mats.shape[0]
    if verbose:
        fe_util.PrintMats(mats,header=['E','nu','thick','rho'])

   
    ########### Find number of load cases ############
    calpyModel.nloads = nsteps
    calpyModel.PrintModelData()
    ngp = 2
    nzem = 3
    calpyModel.banded = True


    # Create element definitions:
    # In calpy, each element is represented by nnod + 1 integer numbers:
    #    matnr,  node1, node2, .... 
    # Also notice that Calpy numbering starts at 1, not at 0 as customary
    # in pyFormex; therefore we add 1 to elems.
    matnr = zeros(calpyModel.nelems,dtype=int32)
    for i,mat in enumerate(secprops):  # proces in same order as above!
        matnr[mat.set] = i+1

    NodesGrp = []
    MatnrGrp = []
    PlaneGrp = []

    for i,e in enumerate(model.elems):
        j,k = model.celems[i:i+2]
        Plane = plane.Quad("part-%s" % i,[ngp,ngp],calpyModel)
        Plane.debug = 0
        PlaneGrp.append(Plane)
        NodesGrp.append(e+1)
        MatnrGrp.append(matnr[j:k])
        if verbose:
            fe_util.PrintElements(NodesGrp[-1],MatnrGrp[-1])

        #Plane.AddElements(e+1,matnr[j:k],mats,coords,bcon)
        
    for Plane,nodenrs,matnrs in zip(PlaneGrp,NodesGrp,MatnrGrp):
        Plane.AddElements(nodenrs,matnrs,mats,coords,bcon)

    # Create load vectors
    # Calpy allows for multiple load cases in a single analysis.
    # However, our script currently puts all loads together in a single
    # load case. So the processing hereafter is rather simple, especially
    # since Calpy provides a function to assemble a single concentrated
    # load into the load vector. We initialize the load vector to zeros
    # and then add all the concentrated loads from the properties database.
    # A single concentrated load consists of 6 components, corresponding
    # to the 6 DOFs of a node.
    #
    # AssembleVector takes 3 arguments: the global vector in which to
    # assemble a nodal vector (length ndof), the nodal vector values
    # (length 6), and a list of indices specifying the positions of the
    # nodal DOFs in the global vector.
    # Beware: The function does not change the global vector, but merely
    # returns the value after assembling.
    # Also notice that the indexing inside the bcon array uses numpy
    # convention (starting at 0), thus no adding 1 is needed!
    print("Assembling Concentrated Loads")
    f = zeros((calpyModel.ndof,calpyModel.nloads),float)
    for p in PDB.getProp('n',attr=['cload']):
        lc = loadcaseFromTag(p)-1  # calpy loadcases start from 0
        if p.set is None:
            nodeset = range(calpyModel.nnodes)
        else:
            nodeset = p.set
        F = [0.0,0.0]
        for i,v in p.cload:
            if i in [0,1]:
                F[i] = v
        for n in nodeset:
            f[:,lc] = fe_util.AssembleVector(f[:,lc],F,bcon[n])

    print("Assembling distributed loads")
    # This is a bit more complex. See Calpy for details
    # We first generate the input data in a string, then read them with the
    # calpy femodel.ReadBoundaryLoads function and finally assemble them with
    # plane.addBoundaryLoads. We have to do this operation per element group.
    # The group number is stored in the property record.
    ngroups = model.ngroups()
    s = [ "" ] * ngroups
    nb = [ 0 ] * ngroups
    for p in PDB.getProp('e',attr=['eload']):
        lc = loadcaseFromTag(p)-1  # calpy loadcases start from 0
        xload = yload = 0.
        if p.label == 'x':
            xload = p.value
        elif p.label == 'y':
            yload = p.value
        # Because of the way we constructed the database, the set will
        # contain only one element, but let's loop over it anyway in case
        # one day we make the storage more effective
        # Also, remember calpy numbers are +1 !
        g = p.group
        print("Group %s" % g)
        for e in p.set:
            s[g] += "%s %s %s %s %s\n" % (e+1,p.edge+1,lc,xload,yload)
            nb[g] += 1
    #print s,nb
    for nbi,si,nodes,matnr,Plane in zip(nb,s,NodesGrp,MatnrGrp,PlaneGrp):
        if nbi > 0:
            idloads,dloads = fe_util.ReadBoundaryLoads(nbi,calpyModel.ndim,si)
            #print idloads,dloads
            Plane.AddBoundaryLoads(f,calpyModel,idloads,dloads,nodes,matnr,coords,bcon,mats)
    
    if verbose:
        print("Calpy.Loads")
        print(f)

    ############ Create global stiffness matrix ##########
    s = calpyModel.ZeroStiffnessMatrix(0)
    for elgrp in PlaneGrp:
        s = elgrp.Assemble(s,mats,calpyModel)
    # print "The complete stiffness matrix"
    # print s

    ############ Solve the system of equations ##########
    v = calpyModel.SolveSystem(s,f)
    print("Calpy analysis has finished --- Runtime was %s seconds." % (time.clock()-starttime))
    displ = fe_util.selectDisplacements (v,bcon)
    if verbose:
        print("Displacements",displ)

    if flavia:
        flavia.WriteMeshFile(jobname,"Quadrilateral",model.nnodel,coord,nodes,matnr)
        res=flavia.ResultsFile(jobname)
        
    # compute stresses
    for lc in range(calpyModel.nloads):
        
        print("Results for load case %d" %(lc+1))
        print("Displacements")
        aprint(displ[:,:,lc],header=['x','y'],numbering=True)

        if flavia:
            flavia.WriteResultsHeader(res,'"Displacement" "Elastic Analysis"',lc+1,'Vector OnNodes')
            flavia.WriteResults(res,displ[:,:,lc])
            
        stresn = count = None
        i = 0
        for e,P in zip(model.elems,PlaneGrp):
            i += 1
            #P.debug = 1
            stresg = P.StressGP (v[:,lc],mats)
            if verbose:
                print("elem group %d" % i)
                print("GP Stress\n", stresg)
            
            strese = P.GP2Nodes(stresg)
            if verbose:
                print("Nodal Element Stress\n", strese)

            #print "Nodes",e+1
            stresn,count = P.NodalAcc(e+1,strese,nnod=calpyModel.nnodes,nodata=stresn,nodn=count)
            #print stresn,count
            
        #print stresn.shape
        #print count.shape
        #print "TOTAL",stresn,count
        stresn /= count.reshape(-1,1)
        #print "AVG",stresn
        if verbose:
            print("Averaged Nodal Stress\n")
            aprint(stresn,header=['sxx','syy','sxy'],numbering=True)
                
        if flavia:
            flavia.WriteResultsHeader(res,'"Stress" "Elastic Analysis"',lc+1,'Matrix OnNodes')
            flavia.WriteResults(res,stresn)

    
    DB = FeResult()
    DB.nodes = model.coords
    DB.nnodes = model.coords.shape[0]
    DB.nodid = arange(DB.nnodes)
    DB.elems = dict(enumerate(model.elems))
    DB.nelems = model.celems[-1]
    DB.Finalize()
    DB.datasize['S'] = 3
    #print DB.elems
    for lc in range(calpyModel.nloads):
        DB.Increment(lc,0)
        d = zeros((calpyModel.nnodes,3))
        d[:,:2] = displ[:,:,lc]
        DB.R['U'] = d
        DB.R['S'] = stresn
    postproc_menu.setDB(DB)
    name = feresult_name.next()
    export({name:DB})

    print("STEPS:",DB.getSteps())
    print("INCS:",DB.getIncs(DB.getSteps()[0]))

    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()