This repository has been archived on 2023-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
foam-extend4.1-coherent-io/applications/utilities/mesh/generation/cfMesh/python/Salome/salomeTriSurf.py
2015-05-13 12:12:11 +01:00

363 lines
12 KiB
Python

#!python
# =============================================================================
# Python module for writing OpenFOAM feature edge and triSurface files from
# within Salome platform.
# Tested on Salome 7.4.0 and python 2.7 on 64-bit Windows
#
# Author: Ivor Clifford <ivor.clifford@psi.ch>
#
# =============================================================================
def foamHeader(className, objectName):
'''
Return the OpenFOAM file header block as a string.
'''
return '''/*--------------------------------*- C++ -*----------------------------------*\\
| ========= | |
| \\\\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\\\ / O peration | Version: 2.2.1 |
| \\\\ / A nd | Web: www.OpenFOAM.org |
| \\\\/ M anipulation | |
\\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class %s;
object %s;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
''' % (className, objectName)
class triSurf:
def __init__(self, object = None, allEdges = False):
'''
Construct from the supplied Salome mesh.
object - the mesh object (must be a triangular surface mesh). If no
object is supplied, the current Salome selection is used.
allEdges - If true, all edges on the mesh are included as feature
edges, otherwise only edges contained in groups are included
NOTE: All face groups are assumed to represent patches. No face subsets
are written. All edge groups are added as feature edge subsets. All point
groups are added as point subsets.
'''
# =============================================================================
# Initialize salome
import salome
import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
from operator import itemgetter
from collections import OrderedDict
import SMESH, SALOMEDS
# =============================================================================
# Get the Salome mesh object
if object is None:
selected = salome.sg.getAllSelected()
if len(selected) != 1:
raise RuntimeError('A single Salome mesh object must be selected.')
object = salome.myStudy.FindObjectID(selected[0]).GetObject()
try:
object.GetMesh()
except:
raise RuntimeError('Supplied object is not a Salome SMESH mesh.')
smesh = smeshBuilder.New(salome.myStudy)
mesh = smesh.Mesh(object)
print "Converting SMESH Mesh '%s'" % mesh.GetName()
# =============================================================================
# Get basic mesh info
nNodes = mesh.NbNodes()
nFaces = mesh.NbFaces()
nTris = mesh.NbTriangles()
nEdges = mesh.NbEdges()
nodeIds = mesh.GetNodesId()
faceIds = mesh.GetElementsByType(SMESH.FACE)
edgeIds = mesh.GetElementsByType(SMESH.EDGE)
# Check that mesh is strictly triangular
if nFaces != nTris:
raise RuntimeError('Mesh is not strictly triangular')
# Get patch and subset names & ids
# All SMESH.FACE groups are assumed to be patches
# All SMESH.EDGE groups are assumed to be feature subsets
# All SMESH.NODE groups are assumed to be point subsets
patches = OrderedDict()
pointSubsets = OrderedDict()
featureEdgeSubsets = OrderedDict()
for group in mesh.GetGroups():
if group.GetType() == SMESH.FACE:
patches[group.GetName()] = group.GetIDs()
elif group.GetType() == SMESH.EDGE:
featureEdgeSubsets[group.GetName()] = group.GetIDs()
elif group.GetType() == SMESH.NODE:
pointSubsets[group.GetName()] = group.GetIDs()
# =============================================================================
# Process faces and patches
# Get patchId for each face
lastPatchId = len(patches)
patchIds = [lastPatchId] * max(faceIds)
patchId = 0
for name, ids in patches.iteritems():
for faceId in ids:
if patchIds[faceId-1] == lastPatchId:
patchIds[faceId-1] = patchId
else:
print "Face %d is assigned to both groups %s and %s" % (faceId, name, patches.keys()[patchIds[faceId-1]])
raise RuntimeError('Groups of faces are not unique, i.e. they overlap.')
patchId += 1
# Compact and reorder patchIds to match faceIds
patchIds = [patchIds[faceId-1] for faceId in faceIds]
# Reorder faces by increasing group id
faceAndpatchIds = sorted(zip(faceIds, patchIds), key=itemgetter(1))
faceIds, patchIds = zip(*faceAndpatchIds)
# Add unused faces to the default patch
defaultFaces = [faceId for faceId, patchId in faceAndpatchIds if patchId == lastPatchId]
if len(defaultFaces) > 0:
patches['defaultFaces'] = defaultFaces
defaultFaces = None
# =============================================================================
# Process feature edges
if not allEdges:
edgeIds = []
for name, ids in featureEdgeSubsets.iteritems():
edgeIds += ids
edgeIds = list(set(edgeIds))
nEdges = len(edgeIds)
# Reverse mapping of edge ids since they aren't necessarily numbered 1..nEdges
if len(edgeIds):
edgeMap = [-1] * max(edgeIds)
else:
edgeMap = []
i=0
for edgeId in edgeIds:
edgeMap[edgeId-1] = i
i += 1
# =============================================================================
# Process nodes
# Reverse mapping of node ids since nodes aren't necessarily numbered 1..nNodes
nodeMap = [-1] * max(nodeIds)
i=0
for nodeId in nodeIds:
nodeMap[nodeId-1] = i
i += 1
# =============================================================================
self._mesh = mesh
self._nodeIds = nodeIds
self._edgeIds = edgeIds
self._faceIds = faceIds
self._nodeMap = nodeMap
self._edgeMap = edgeMap
self._faceMap = []
self._patches = patches
self._pointSubsets = pointSubsets
self._featureEdgeSubsets = featureEdgeSubsets
self._faceSubsets = {}
print 'Done'
def nNodes(self):
'''
Return the number of nodes
'''
return len(self._nodeIds)
def nEdges(self):
'''
Return the number of edges
'''
return len(self._edgeIds)
def nFacets(self):
'''
Return the number of triangular facets
'''
return len(self._faceIds)
def nPatches(self):
'''
Return the number of patches
'''
return len(self._patches)
def _writePatchDefs(self, f, typeName = 'wall'):
'''
Write the patch definitions to file as an OpenFOAM geometricSurfacePatchList.
NOTE: All patches are assumed to be walls.
'''
patches = self._patches
f.write('%d\n(\n' % len(patches))
for name in patches.iterkeys():
f.write('%s\t%s\n' % (name, typeName))
f.write(')\n')
def _writeNodes(self, f):
'''
Write the nodes to file as an OpenFOAM pointField.
'''
mesh = self._mesh
nodeIds = self._nodeIds
f.write('%d\n(\n' % len(nodeIds))
for x, y, z in [mesh.GetNodeXYZ(nodeId) for nodeId in nodeIds]:
f.write( '( %g %g %g )\n' % (x, y, z))
f.write(')\n')
def _writeFeatureEdges(self, f):
'''
Write the feature edges to file as an OpenFOAM edgeList.
'''
mesh = self._mesh
nodeMap = self._nodeMap
edgeIds = self._edgeIds
f.write('%d\n(\n' % len(edgeIds))
for edgeId in edgeIds:
nodes = mesh.GetElemNodes(edgeId)
f.write( '(' + ' '.join([str(nodeMap[nodeId-1]) for nodeId in nodes]) + ')\n')
f.write(')\n')
def _writeFacets(self, f):
'''
Write the facets to file as an OpenFOAM List of labelledTri.
'''
from itertools import chain
mesh = self._mesh
nodeMap = self._nodeMap
patches = self._patches
f.write('%d\n(\n' % sum([len(patch) for patch in patches.itervalues()]))
patchId = 0
for patchId, (patchName, faceIds) in enumerate(patches.iteritems()):
for faceId in faceIds:
nodes = mesh.GetElemNodes(faceId)
f.write( '((' + ' '.join([str(nodeMap[nodeId-1]) for nodeId in nodes]) + ') %d)\n' % patchId)
f.write(')\n')
def _writeSubsets(self, f, subsets, map, typeId):
'''
General function to write a subset to file as an OpenFOAM Map<meshSubset>.
'''
f.write('%d\n(\n' % len(subsets))
for name, ids in subsets.iteritems():
f.write('%s %s %d ( %s )\n' % (name, typeId, len(ids), ' '.join([str(map[id-1]) for id in ids])))
f.write(')\n')
def _writePointSubsets(self, f):
'''
Write the point subsets to file as and OpenFOAM Map<meshSubset>.
'''
self._writeSubsets(f, self._pointSubsets, self._nodeMap, '2')
def _writeFaceSubsets(self, f):
'''
Write the face subsets to file as and OpenFOAM Map<meshSubset>.
'''
self._writeSubsets(f, self._faceSubsets, self._faceMap, '4')
def _writeFeatureEdgeSubsets(self, f):
'''
Write the feature edge subsets to file as and OpenFOAM Map<meshSubset>.
'''
self._writeSubsets(f, self._featureEdgeSubsets, self._edgeMap, '8')
def writeEdgeMesh(self, fileName):
'''
Write to file as an OpenFOAM edgeMesh
fileName - The file name to write
'''
# Create file
f = open(fileName, 'wb') # NOTE: file opened as binary to ensure unix-style line breaks
# Write header
f.write(foamHeader('edgeMesh', self._mesh.GetName()))
self._writeNodes(f)
self._writeFeatureEdges(f)
f.close()
print 'edgeMesh written to %s' % fileName
def writeFtr(self, fileName):
'''
Write to file as an OpenFOAM cfMesh FTR file
fileName - the file name to write
'''
# Create file
f = open(fileName, 'wb') # NOTE: file opened as binary to ensure unix-style line breaks
self._writePatchDefs(f)
self._writeNodes(f)
self._writeFacets(f)
f.close()
print 'triSurf written to %s' % fileName
def writeFms(self, fileName):
'''
Write to file as an OpenFOAM cfMesh FMS file
fileName - the file name to write
'''
# Create file
f = open(fileName, 'wb') # NOTE: file opened as binary to ensure unix-style line breaks
self._writePatchDefs(f)
self._writeNodes(f)
self._writeFacets(f)
self._writeFeatureEdges(f)
self._writePointSubsets(f)
self._writeFaceSubsets(f)
self._writeFeatureEdgeSubsets(f)
f.close()
print 'triSurf written to %s' % fileName
if __name__ == '__main__':
import salome
salome.salome_init()
import SMESH, SALOMEDS