Source code for plugins.flavia

#
##
##  SPDX-FileCopyrightText: © 2007-2023 Benedict Verhegghe <bverheg@gmail.com>
##  SPDX-License-Identifier: GPL-3.0-or-later
##
##  This file is part of pyFormex 3.4  (Thu Nov 16 18:07:39 CET 2023)
##  pyFormex is a tool for generating, manipulating and transforming 3D
##  geometrical models by sequences of mathematical operations.
##  Home page: https://pyformex.org
##  Project page: https://savannah.nongnu.org/projects/pyformex/
##  Development: https://gitlab.com/bverheg/pyformex
##  Distributed under the GNU General Public License version 3 or later.
##
##  This program is free software: you can redistribute it and/or modify
##  it under the terms of the GNU General Public License as published by
##  the Free Software Foundation, either version 3 of the License, or
##  (at your option) any later version.
##
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  GNU General Public License for more details.
##
##  You should have received a copy of the GNU General Public License
##  along with this program.  If not, see http://www.gnu.org/licenses/.
##

"""
Interface with flavia FE result files.

(C) 2010 Benedict Verhegghe.
"""
import shlex

import numpy as np

import pyformex.arraytools as at
from pyformex.plugins.fe import Model
from pyformex.plugins.fe_post import FeResult


element_type_translation = {
    'quadrilateral': {
        4: 'quad4',
        8: 'quad8',
        9: 'quad9',
    },
}
element_results_count = {
    'vector': {
        2: 2,
        3: 3,
    },
    'matrix': {
        2: 3,
        3: 6,
    },
}

######################### functions #############################


[docs]def readMesh(fn): """Read a flavia mesh file. Returns a list of Meshes if successful. """ fil = open(fn, 'r') meshes = [] for line in fil: if line.startswith('#'): continue elif line.startswith('Mesh'): s = shlex.split(line.lower()) s = dict(zip(s[0::2], s[1::2])) print(s) ndim = int(s['dimension']) nplex = int(s['nnode']) eltype = element_type_translation[s['elemtype']][nplex] print("eltype = %s, ndim = %s" % (eltype, ndim)) elif line.startswith('Coordinates'): coords = readCoords(fil, ndim) print("Coords %s" % str(coords.shape)) elif line.startswith('Elements'): elems, props = readElems(fil, nplex) print("Elements %s %s" % (elems.shape, props.shape)) meshes.append((elems, props)) else: print(line) elems, props = [m[0] for m in meshes], [m[1] for m in meshes] maxnod = max([e.max() for e in elems]) coords = coords[:maxnod+1] return coords, elems, props, ndim
[docs]def readCoords(fil, ndim): """Read a set of coordinates from a flavia file""" ncoords = 100 coords = np.zeros((ncoords, 3), dtype=at.Float) for line in fil: if line.startswith('End Coordinates'): break else: s = line.split() i = int(s[0]) x = [float(v) for v in s[1:]] while i >= ncoords: coords = at.growAxis(coords, ncoords, axis=0, fill=0.0) ncoords = coords.shape[0] coords[i-1, :ndim] = x return coords
[docs]def readElems(fil, nplex): """Read a set of coordinates from a flavia file""" nelems = 100 elems = np.zeros((nelems, nplex), dtype=at.Int) props = np.zeros((nelems), dtype=at.Int) for line in fil: if line.startswith('End Elements'): break else: s = line.split() i = int(s[0]) e = [int(v) for v in s[1:nplex+1]] p = int(s[nplex+1]) while i >= nelems: elems = at.growAxis(elems, nelems, axis=0, fill=0) props = at.growAxis(props, nelems, axis=0, fill=0) nelems = elems.shape[0] elems[i-1] = e props[i-1] = p defined = elems.sum(axis=1) > 0 return elems[defined]-1, props[defined]
[docs]def readResults(fn, nnodes, ndim): """Read a flavia results file for an ndim mesh. """ fil = open(fn, 'r') results = {} for line in fil: if line.startswith('#'): continue elif line.startswith('Result'): s = shlex.split(line.lower()) name = s[1] restype = s[4] domain = s[5] print(domain) if domain != 'onnodes': print("Currently only results on nodes can be read") print("Skipping %s %s" % (name, domain)) nres = 0 continue nres = element_results_count[restype][ndim] elif line.startswith('Values'): if nres > 0: result = readResult(fil, nnodes, nres) print(name) results[name] = result else: print(line) return results
[docs]def readResult(fil, nvalues, nres): """Read a set of results from a flavia file""" values = np.zeros((nvalues, nres), dtype=at.Float) for line in fil: if line.startswith('End Values'): break else: s = line.split() i = int(s[0]) x = [float(v) for v in s[1:]] values[i-1] = x return values
[docs]def createFeResult(model, results): """Create an FeResult from meshes and results""" DB = FeResult() DB.nodes = model.coords DB.nnodes = model.coords.shape[0] DB.nodid = np.arange(DB.nnodes) DB.elems = dict(enumerate(model.elems)) DB.nelems = model.celems[-1] DB.Finalize() ndisp = results['displacement'].shape[1] nstrs = results['stress'].shape[1] DB.datasize['U'] = ndisp DB.datasize['S'] = nstrs for lc in range(1): # currently only 1 step DB.Increment(lc, 0) DB.R['U'] = results['displacement'] DB.R['S'] = results['stress'] return DB
[docs]def readFlavia(meshfile, resfile): """Read flavia results files Currently we only read matching pairs of meshfile,resfile files. """ if meshfile: coords, elems, props, ndim = readMesh(meshfile) if resfile: R = readResults(resfile, coords.shape[0], ndim) M = Model(coords, elems) DB = createFeResult(M, R) DB.printSteps() return DB
if __name__ == '__draw__': from pyformex.gui.draw import chdir, Path, draw chdir('/home/bene/prj/pyformex') name = 'FeResult-001' meshfile = Path(name+'.flavia.msh') resfile = meshfile.with_suffix('.res') M = readMesh(meshfile) print(M.coords.shape, M.elems.shape) print(M.coords, M.elems) draw(M) R = readResults(resfile, M) DB = createFeResult(M, R) DB.printSteps() print(DB.R) print(DB.datasize) DB1 = FeResult() print(DB1.datasize) for key in ['U0', 'U1', 'U2', 'U3']: v = DB.getres(key) if v is not None: print("%s: %s" % (key, v.shape)) # End