示例#1
0
def writeTetMesh(fn, coords, elems):
    """Write a tetgen tetrahedral mesh model to .node and .ele files.

    The provided file name is either the .node or the .smesh filename,
    or else it is the basename where .node and .ele extensions will
    be appended.
    """
    writeNodes(utils.changeExt(fn, '.node', accept_ext=['.node', '.ele']), coords)
    writeTmesh(utils.changeExt(fn, '.ele', accept_ext=['.node', '.ele']), elems)
示例#2
0
def writeSurface(fn, coords, elems):
    """Write a tetgen surface model to .node and .smesh files.

    The provided file name is either the .node or the .smesh filename,
    or else it is the basename where .node and .smesh extensions will
    be appended.
    """
    writeNodes(utils.changeExt(fn, '.node', accept_ext=['.node', '.smesh']), coords)
    writeSmesh(utils.changeExt(fn, '.smesh', accept_ext=['.node', '.smesh']), elems)
示例#3
0
def read_gambit_neutral(fn):
    """Read a triangular surface mesh in Gambit neutral format.

    The .neu file nodes are numbered from 1!
    Returns a nodes,elems tuple.
    """
    scr = os.path.join(pf.cfg['bindir'], 'gambit-neu ')
    utils.command("%s '%s'" % (scr, fn))
    nodesf = utils.changeExt(fn, '.nodes')
    elemsf = utils.changeExt(fn, '.elems')
    nodes = np.fromfile(nodesf, sep=' ', dtype=at.Float).reshape((-1, 3))
    elems = np.fromfile(elemsf, sep=' ', dtype=np.int32).reshape((-1, 3))
    return nodes, elems - 1
示例#4
0
def read_gambit_neutral_hex(fn):
    """Read an hexahedral mesh in Gambit neutral format.

    The .neu file nodes are numbered from 1!
    Returns a nodes,elems tuple.
    """
    scr = os.path.join(pf.cfg['bindir'], 'gambit-neu-hex ')
    print("%s '%s'" % (scr, fn))
    utils.command("%s '%s'" % (scr, fn))
    nodesf = utils.changeExt(fn, '.nodes')
    elemsf = utils.changeExt(fn, '.elems')
    nodes = np.fromfile(nodesf, sep=' ', dtype=at.Float).reshape((-1, 3))
    elems = np.fromfile(elemsf, sep=' ', dtype=np.int32).reshape((-1, 8))
    elems = elems[:, (0, 1, 3, 2, 4, 5, 7, 6)]
    return nodes, elems - 1
示例#5
0
def readSurface(fn):
    """Read a tetgen surface from a .node/.face file pair.

    The given filename is either the .node or .face file.
    Returns a tuple of (nodes,elems).
    """
    nodeInfo = readNodeFile(utils.changeExt(fn, '.node'))
    nodes = nodeInfo[0]
    print("Read %s nodes" % nodes.shape[0])
    elemInfo = readFaceFile(utils.changeExt(fn, '.face'))
    elems = elemInfo[0]
    print("Read %s elems" % elems.shape[0])
    #if numbers[0] == 1:
    #    elems -= 1
    return nodes, elems
示例#6
0
    def export(self,body='',createdby=-1):
        """Finish the export by creating the html file.

        Parameters:

        - `body`: an HTML section to be put in the body
        - `createdby`: int. If not zero, a logo 'Created by pyFormex'
          will appear on the page. If > 0, it specifies the width of the
          logo field. If < 0, the logo will be displayed on its natural
          width.

        Returns the full path of the create html file.
        """
        if self.jsfile:
            htmlname = utils.changeExt(self.jsfile.name, '.html')
            self.jsfile.close()
            body = ''

            if createdby:
                if isinstance(createdby, int):
                    width = createdby
                else:
                    width = 0
                body += createdBy(width)

            if len(self.scenes) > 1:
                body += createSceneButtons(self.scenes)

            exported_webgl = createWebglHtml(
                htmlname,self.scripts,self.bgcolor,body,
                self.description,self.keywords,self.author,self.title)
            print("Exported WebGL model to %s" % exported_webgl)
            return exported_webgl
示例#7
0
    def start_js(self,name):
        """Export the start of the js file.

        Parameters:

        - `name`: string: the name of the model that will be shown
          by default when displaying the webgl html page

        This function should only be executed once, before any
        other export functions. It is called automatically by
        the first call to exportScene.
        """
        jsname = utils.changeExt(self.name, '.js')
        print("Exporting WebGL script to %s" % os.path.abspath(jsname))
        if self.urlprefix:
            jsurl = self.urlprefix + jsname
            print("Include it in the .html page as '%s'" % jsurl)
        else:
            jsurl = jsname
        self.scripts.append(jsurl)

        self.jsfile = open(jsname, 'w')
        s = "// Script generated by %s\n" % pf.fullVersion()
        if self.jsheader:
            s += str(self.jsheader)
        s += """
var the_renderer;
var the_controls;

window.onload = function() {
show%s();
}
"""% name
        self.jsfile.write(s)
示例#8
0
def readSmeshFile(fn):
    """Read a tetgen .smesh file.

    Returns an array of triangle elements.
    """
    fil = open(fn, 'r')

    # node section.
    line = skipComments(fil)
    npts, ndim, nattr, nbmark = getInts(line, 4)
    if npts > 0:
        nodeInfo = readNodesBlock(fil, npts, ndim, nattr, nbmark)
    else:
        # corresponding .node file
        nodeInfo = readNodeFile(utils.changeExt(fn, '.node'))

    # facet section
    line = skipComments(fil)
    nelems, nbmark = getInts(line, 2)
    facetInfo = readSmeshFacetsBlock(fil, nelems, nbmark)

    nodenrs = nodeInfo[1]
    if nodenrs.min() == 1 and nodenrs.max()==nodenrs.size:
        elems = facetInfo[0]
        for e in elems:
            elems[e] -= 1

    # We currently do not read the holes and attributes

    return nodeInfo[0], facetInfo[0]
示例#9
0
def tetMesh(surfacefile,quality=False,volume=None,outputdir=None):
    """Create a tetrahedral mesh inside a surface

    - `surfacefile`: a file representing a surface. It can be an .off or
      .stl file (or other?)
    - `quality`: if True, the output will be a quality mesh
      The circumradius-to-shortest-edge ratio can be constrained by
      specifying a float value for quality (default is 2.0)
    - `volume`: float: applies a maximum tetrahedron volume constraint
    - `outputdir`: if specified, the results will be placed in this directory.
      The default is to place the results in the same directory as the input
      file.

    If the creation of the tetrahedral model is succesful, the results are
    read back using readTetgen and returned.
    """
    options = ''
    if quality is True:
        options += 'q'
    elif isinstance(quality, float):
        options += 'q%f' % quality
    if volume is not None:
        options += 'a%f' % volume
    if outputdir is None:
        d = os.path.dirname(surfacefile)
    tgt = os.path.join(d, os.path.basename(surfacefile))
    print(surfacefile, tgt)
    if not os.path.exists(tgt):
        os.symlink(surfacefile, tgt)
    runTetgen(tgt, options)
    fn = utils.changeExt(tgt, '1.ele')
    res = readTetgen(fn)
    return res
示例#10
0
def readTetgen(fn):
    """Read and draw a tetgen file.

    This is an experimental function for the geometry import menu.
    """
    res = {}
    base, ext = os.path.splitext(fn)
    if ext == '.node':
        nodes = readNodeFile(fn)[0]
        res['tetgen'+ext] = nodes
    elif ext in [ '.ele', '.face' ]:
        nodes, nodenrs = readNodeFile(utils.changeExt(fn, '.node'))[:2]
        if ext == '.ele':
            elems = readEleFile(fn)[0]
        elif ext == '.face':
            elems = readFaceFile(fn)[0]
        if nodenrs.min() == 1 and nodenrs.max()==nodenrs.size:
            elems = elems-1
        M = Mesh(nodes, elems, eltype=elems.eltype)
        res['tetgen'+ext] = M

    elif ext == '.smesh':
        nodes, elems = readSmeshFile(fn)
        ML = [ Mesh(nodes, elems[e]) for e in elems ]
        res = dict([('Mesh-%s'%M.nplex(), M) for M in ML])

    elif ext == '.poly':
        nodes, elems = readPolyFile(fn)
        ML = [ Mesh(nodes, elems[e]) for e in elems ]
        res = dict([('Mesh-%s'%M.nplex(), M) for M in ML])

    return res
示例#11
0
def submitToCluster(filename=None):
    """Submit an Abaqus job to the cluster."""
    if not filename:
        filename = askFilename(pf.cfg['workdir'], filter="Abaqus input files (*.inp)", exist=True)
    if filename:
        jobname = os.path.basename(filename)[:-4]
        dirname = os.path.dirname(filename)
        add_all = jobname == dirname
        res = askItems([
            _I('jobname', jobname, text='Cluster job name/directory'),
            _I('add_all', add_all, text='Include all the files in the input directory',tooltip='If unchecked, only the jobname.inp and jobname.request files comprise the job'),
            _I('ncpus', 4, text='Number of cpus', min=1, max=1024),
            _I('abqver', 'default', text='Abaqus Version', choices=pf.cfg['jobs/abqver']),
            _I('postabq', False, text='Run postabq on the results?'),
            ])
        if res:
            reqtxt = 'cpus=%s\n' % res['ncpus']
            reqtxt += 'abqver=%s\n' % res['abqver']
            if res['postabq']:
                reqtxt += 'postproc=postabq\n'
            host = pf.cfg.get('jobs/host', 'bumpfs')
            reqdir = pf.cfg.get('jobs/inputdir', 'bumper/requests')

            filereq = utils.changeExt(filename,'.request')
            with open(filereq,'w') as fil:
                fil.write(reqtxt)

            srcdir = os.path.dirname(filename)
            tgtdir = "%s:%s/%s" % (host, reqdir,jobname)
            if res['add_all']:
                include = []
            else:
                include = ['*.inp']
            submitJob(srcdir,tgtdir,include=include)
示例#12
0
def importFlavia(fn=None):
    """Import a flavia file and select it as the current results.

    Flavia files are the postprocessing format used by GiD pre- and
    postprocessor, and can also be written by the FE program calix.
    There usually are two files named 'BASE.flavia.msh' and 'BASE.flavia.res'
    which hold the FE mesh and results, respectively.

    This functions asks the user to select a flavia file (either mesh or
    results), will then read both the mesh and corrseponding results files,
    and store the results in a FeResult instance, which will be set as the
    current results database for the postprocessing menu.
    """
    from pyformex.plugins.flavia import readFlavia
    if fn is None:
        fn = askFilename(pf.cfg['workdir'], ['flavia', 'all'])
    if fn:
        chdir(fn)
        if fn.endswith('.msh'):
            meshfile = fn
            resfile = utils.changeExt(fn, 'res')
        else:
            resfile = fn
            meshfile = utils.changeExt(fn, 'msh')

        db = readFlavia(meshfile, resfile)
        if not isinstance(db, FeResult):
            warning(
                "!Something went wrong during the import of the flavia database %s"
                % fn)
            return

        ### ok: export and select the DB
        name = os.path.splitext(os.path.basename(fn))[0].replace('.flavia', '')
        export({name: db})
        db.printSteps()
        print(db.R)
        print(db.datasize)

        selection.set([name])
        selectDB(db)
示例#13
0
def importCalculix(fn=None):
    """Import a CalculiX results file and select it as the current results.

    CalculiX result files are the .dat files resulting from a run of the
    ccx program with an .inp file as input. This function will need both
    files and supposes that the names are the same except for the extension.

    If no file name is specified, the user is asked to select one (either the
    .inp or .dat file), will then read both the mesh and corresponding results
    files, and store the results in a FeResult instance, which will be set as
    the current results database for the postprocessing menu.
    """
    from pyformex.plugins import ccxdat
    from pyformex.fileread import readInpFile
    #from plugins.fe import Model
    if fn is None:
        fn = askFilename(pf.cfg['workdir'], 'ccx')
    if fn:
        chdir(fn)
        if fn.endswith('.inp'):
            meshfile = fn
            resfile = utils.changeExt(fn, 'dat')
        else:
            resfile = fn
            meshfile = utils.changeExt(fn, 'inp')

        parts = readInpFile(meshfile)
        print(type(parts))
        print(parts.keys())
        meshes = parts.values()[0]
        print(type(meshes))
        #fem = Model(meshes=meshes,fuse=False)
        DB = ccxdat.createResultDB(meshes)
        ngp = 8
        ccxdat.readResults(resfile, DB, DB.nnodes, DB.nelems, ngp)
        DB.printSteps()
        name = 'FeResult-%s' % meshfile[:-4]
        export({name: DB})
        selection.set([name])
        selectDB(DB)
示例#14
0
def readPolyFile(fn):
    """Read a tetgen .poly file.

    Returns an array of triangle elements.
    """
    fil = open(fn, 'r')

    # node section.
    line = skipComments(fil)
    npts, ndim, nattr, nbmark = getInts(line, 4)
    if npts > 0:
        nodeInfo = readNodesBlock(fil, npts, ndim, nattr, nbmark)
    else:
        # corresponding .node file
        nodeInfo = readNodeFile(utils.changeExt(fn, '.node'))

    # facet section
    line = skipComments(fil)
    nelems, nbmark = getInts(line, 2)
    facetInfo = readFacetsBlock(fil, nelems, nbmark)
    print("NEXT LINE:")
    print(line)
    return nodeInfo[0], facetinfo[0]
示例#15
0
def createMultiWebGL():
    """Creates a multimodel WebGL from single WebGL models"""
    from pyformex.gui.draw import askFilename, askNewFilename, ack, showHTML
    models = askFilename(filter=['html','js'],multi=True)
    if not models:
        return
    combined = askNewFilename(filter=['html','js'],caption="Enter name of the combined model")
    if not combined:
        return
    fout = open(utils.changeExt(combined,'js'),'w')

    print("""// Script generated by %s
var the_renderer;
var the_menu;
window.onload = function() {
show%s()
}
""" % (pf.fullVersion(),utils.projectName(models[0])),file=fout)

    body = createdBy()
    body += "<div style='position:absolute;top:150px;left:10px;'>"
    for model in models:
        name = utils.projectName(model)
        body += "<button onclick='show%s()'>Show %s</button><br />" % (name,name)
        print('',file=fout)
        print("show%s = function() {" % name,file=fout)
        fn = utils.changeExt(model,'js')
        f = open(fn,'r')
        s = f.readlines()
        f.close()
        while len(s) > 0:
            line = s.pop(0)
            if line.startswith("window.onload = function"):
                break
        line = s.pop(0)
        if line.startswith("var r = new X.renderer3D"):
            print("""if (the_menu != null) the_menu.destroy();
if (the_renderer != null) the_renderer.destroy();
the_renderer = new X.renderer3D();
var r = the_renderer;
""",file=fout)
        else:
            raise ValueError("Invalid WebGL script %s" % fn)

        while len(s) > 0:
            line = s.pop(0)
            print(line,file=fout)
            if line.startswith("var gui = new dat.GUI"):
                print("the_menu = gui;",file=fout)
    fout.close()
    body += "</div>"

    fn = createWebglHtml(
        utils.changeExt(combined,'html'),
        scripts=[
            pf.cfg['webgl/script'],
            pf.cfg['webgl/guiscript'],
            utils.changeExt(combined,'js')
            ],
        body=body
        )

    if ack("Show the scene in your browser?"):
        showHTML(fn)
示例#16
0
def createCalixInput():
    """Write the Calix input file."""

    checkWorkdir()
    if not checkModel():
        return

    # ask job name from user
    res = askItems([
        _I('jobname', feresult_name.next(), text='Job Name'),
        _I('header', 'A Calix example', text='Header Text'),
        _I(
            'zem',
            '3',
            text='ZEM control',
            itemtype='radio',
            choices=['0', '3', '6'],
        ),
    ])
    if not res:
        return

    jobname = res['jobname']
    header = res['header']
    nzem = int(res['zem'])
    if not jobname:
        print("No Job Name: writing to sys.stdout")
        jobname = None

    filnam = jobname + '.dta'
    print("Writing calix data file %s in %s" % (filnam, os.getcwd()))
    fil = open(filnam, 'w')

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

    # Get materials
    secprops = PDB.getProp(kind='e', attr=['section'])
    print(secprops)
    # need E, nu, thickness, rho
    mats = array([[
        sec.young_modulus,
        sec.poisson_ratio,
        sec.thickness,
        sec.density,
    ] for sec in secprops])
    matnr = zeros(nelems, dtype=int32)
    for i, mat in enumerate(secprops):  # proces in same order as above!
        matnr[mat.set] = i + 1
    print(matnr)
    nmats = mats.shape[0]

    # Header
    fil.write("""; calix data file generated by %s
; jobname=%s
start: %s
;use cmdlog 'calix.log'
;use for messages cmdlog
file open 'femodel.tmp' write da 1
yes cmdlog
;yes debug
use for cmdlog output
femodel elast stress 2
use for cmdlog cmdlog
;-----------------------------------------
; Aantal knopen:   %s
; Aantal elementen:   %s
; Aantal materialen:     %s
; Aantal belastingsgevallen: %s
""" % (pf.Version(), jobname, header, nnodes, nelems, nmats, nsteps))
    # Nodal coordinates
    fil.write(""";-----------------------------------------
; Knopen
;--------
nodes coord %s 1
""" % nnodes)
    fil.write('\n'.join([
        "%5i%10.2f%10.2f" % (i, x[0], x[1])
        for i, x in zip(arange(nnodes) + 1, model.coords)
    ]))
    fil.write('\n\n')
    # Boundary conditions
    fil.write(""";-----------------------------------------
; Verhinderde verplaatsingen
;-------------------------
bound bcon
plane
""")
    for p in PDB.getProp(kind='n', attr=['bound']):
        bnd = "%5i" + "%5i" * 2 % (p.bound[0], p.bound[1])
        if p.set is None:
            nod = arange(model.nnodes)
        else:
            nod = array(p.set)
        fil.write('\n'.join([bnd % i for i in nod + 1]))
        fil.write('\n')
    fil.write('\n')
    fil.write("""print bcon 3
                           $$$$$$$$$$$$$$$$$$$$$$$
                           $$      D O F S      $$
                           $$$$$$$$$$$$$$$$$$$$$$$
""")

    # Materials
    fil.write(""";-----------------------------------------
; Materialen
;-----------
array mat    %s 4
""" % len(mats))
    print(mats)
    fil.write('\n'.join(["%.4e " * 4 % tuple(m) for m in mats]))
    fil.write('\n\n')
    fil.write("""print mat 3
                           $$$$$$$$$$$$$$$$$$$$$$$
                           $$ M A T E R I A L S $$
                           $$$$$$$$$$$$$$$$$$$$$$$
""")

    # Elements
    for igrp, grp in enumerate(model.elems):
        nelems, nplex = grp.shape
        fil.write(""";-----------------------------------------
; Elementen
;----------
elements elems-%s matnr-%s  %s %s 1
""" % (igrp, igrp, nplex, nelems))
        fil.write('\n'.join([
            "%5i" * (nplex + 2) % tuple([i, 1] + e.tolist())
            for i, e in zip(arange(nelems) + 1, grp + 1)
        ]))
        fil.write('\n\n')
        fil.write("""plane plane-%s coord bcon elems-%s matnr-%s 2 2
""" % (igrp, igrp, igrp))

    #########################
    # Nodal Loads
    cloads = [p for p in PDB.getProp('n', attr=['cload'])]
    fil.write("""text 3 1
                           $$$$$$$$$$$$$$$$$$$$
                           $$  NODAL  LOADS  $$
                           $$$$$$$$$$$$$$$$$$$$
loads f bcon 1
""")
    if len(cloads) > 0:
        for p in cloads:
            loadcase = loadcaseFromTag(p)
            if p.set is None:
                nodeset = arange(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
            fil.write(''.join([
                "%5i%5i%10.2f%10.2f\n" % (n + 1, loadcase, F[0], F[1])
                for n in nodeset
            ]))
    fil.write('\n')

    #########################
    # Distributed loads
    eloads = [p for p in PDB.getProp('e', attr=['eload'])]
    if len(eloads) > 0:
        fil.write("""text 4 1
                           $$$$$$$$$$$$$$$$$$$$$$$$$$
                           $$  BOUNDARY  ELEMENTS  $$
                           $$$$$$$$$$$$$$$$$$$$$$$$$$
   elem  loadnr  localnodes
""")
        # get the data from database, group by group
        for igrp in range(len(model.elems)):
            geloads = [p for p in eloads if p.group == igrp]
            neloads = len(geloads)
            loaddata = []
            fil.write("array randen integer   %s 4 0 1\n" % neloads)
            i = 1
            for p in geloads:
                loadcase = loadcaseFromTag(p)
                xload = yload = 0.
                if p.label == 'x':
                    xload = p.value
                elif p.label == 'y':
                    yload = p.value
                # Save the load data for later
                loaddata.append((i, loadcase, xload, yload))
                # 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
                for e in p.set:
                    fil.write(("%5s" * 4 + "\n") % (e + 1, i, p.edge + 1,
                                                    (p.edge + 1) % 4 + 1))
                i += 1
            fil.write("""print randen
tran randen tranden
boundary  rand-%s coord bcon elems-%s matnr-%s tranden 1
""" % ((igrp, ) * 3))
            fil.write("""text 3 1
                           $$$$$$$$$$$$$$$$$$$$$$$
                           $$  BOUNDARY  LOADS  $$
                           $$$$$$$$$$$$$$$$$$$$$$$
loadvec boundary rand-%s f 1
""" % igrp)
            for eload in loaddata:
                fil.write("%5s%5s%10s%10s\n" % eload)
            fil.write('\n')

    #########################
    # Print total load vector
    fil.write("""
print f 3
                           $$$$$$$$$$$$$$$$$$$$
                           $$  LOAD  VECTOR  $$
                           $$$$$$$$$$$$$$$$$$$$
;
""")
    # Assemble
    for igrp in range(len(model.elems)):
        fil.write("assemble plane-%s mat s 0 0 0 %s\n" % (igrp, nzem))

    # Solve and output
    fil.write(""";------------------------------------------------solve+output
flavia mesh '%s.flavia.msh' %s
flavia nodes coord
""" % (jobname, nplex))
    for igrp in range(len(model.elems)):
        fil.write("flavia elems elems-%s matnr-%s %s\n" % (igrp, igrp, nplex))
    fil.write("flavia results '%s.flavia.res'\n" % jobname)
    fil.write("""
solbnd s f
delete s
text named 1
"Displacement" "Elastic Analysis"
text typed 1
Vector OnNodes
text names 1
"Stress" "Elastic Analysis"
text types 1
Matrix OnNodes
intvar set 1 1
loop 1
  displ f bcon displ $1 1
  tran displ disp
  flavia result named typed disp $1
""")
    for igrp in range(len(model.elems)):
        fil.write("""
  stress plane-%s mat f stresg $1 1
  gp2nod plane-%s stresg strese 0 1
  nodavg plane-%s elems-%s strese stren nval 1
  tran stren stre
  flavia result names types stre $1
""" % ((igrp, ) * 4))
    fil.write("""
  intvar add 1 1
next
stop
""")

    # Done: Close data file
    fil.close()
    showFile(filnam, mono=True)

    if ack("Shall I run the Calix analysis?"):
        # Run the analysis
        outfile = utils.changeExt(filnam, 'res')
        cmd = "calix %s %s" % (filnam, outfile)
        utils.command(cmd)
        showFile(outfile, mono=True)

        if ack("Shall I read the results for postprocessing?"):
            from pyformex.plugins import flavia
            meshfile = utils.changeExt(filnam, 'flavia.msh')
            resfile = utils.changeExt(filnam, 'flavia.res')
            DB = flavia.readFlavia(meshfile, resfile)
            postproc_menu.setDB(DB)
            export({name: 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()