mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2025-01-26 21:40:33 +05:00
424 lines
11 KiB
Python
424 lines
11 KiB
Python
# Copyright (C) 2016-2021 EDF R&D
|
|
#
|
|
# This library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
#
|
|
# This library 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
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this library; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
|
|
#
|
|
|
|
#import sys
|
|
#sys.path.append('/home/I60976/00_PROJETS/2015_INTEGRATION_ZCRACKS/zcracks_salome/zcracks')
|
|
|
|
import numpy, subprocess, sys
|
|
from os import remove, getpid, path, environ
|
|
from .output import message
|
|
|
|
def calcCoordVectors(normalIN, directionIN):
|
|
V3TEMP=numpy.cross(normalIN,directionIN)
|
|
directionTEMP=numpy.cross(V3TEMP,normalIN)
|
|
|
|
normalOUT=numpy.array(normalIN)/numpy.linalg.norm(normalIN)
|
|
directionOUT=numpy.array(directionTEMP)/numpy.linalg.norm(directionTEMP)
|
|
V3OUT=numpy.array(V3TEMP)/numpy.linalg.norm(V3TEMP)
|
|
return(normalOUT, directionOUT, V3OUT)
|
|
|
|
|
|
def testStrictRange(x, inf=0.0, sup=False):
|
|
test=False
|
|
c1=(isinstance(x, list))
|
|
if c1:
|
|
c2=(len(x)==1)
|
|
if c2:
|
|
c3=(isinstance(x[0], type(inf)))
|
|
if c3:
|
|
c4=(x[0]>inf)
|
|
c5=True
|
|
if sup!=False:
|
|
c5=(x[0]<sup)
|
|
if c4 and c5:
|
|
test=True
|
|
return(test)
|
|
|
|
def test3dVector(x):
|
|
test=False
|
|
c1=(isinstance(x, list))
|
|
if c1:
|
|
c2=(len(x)==3)
|
|
if c2:
|
|
c3=(isinstance(x[0], float))
|
|
c4=(isinstance(x[1], float))
|
|
c5=(isinstance(x[2], float))
|
|
if c3 and c4 and c5:
|
|
test=True
|
|
return(test)
|
|
|
|
def testRange(x, inf=0.0, sup=False):
|
|
test=False
|
|
c1=(isinstance(x, list))
|
|
if c1:
|
|
c2=(len(x)==1)
|
|
if c2:
|
|
c3=(isinstance(x[0], type(inf)))
|
|
if c3:
|
|
c4=(x[0]>=inf)
|
|
c5=True
|
|
if sup!=False:
|
|
c5=(x[0]<=sup)
|
|
if c4 and c5:
|
|
test=True
|
|
return(test)
|
|
|
|
def check(data):
|
|
OK=True
|
|
|
|
test=False
|
|
c1=(data['crackedName']!='')
|
|
if c1:
|
|
test=True
|
|
if not test:
|
|
message('E','Invalid Cracked name',goOn=True)
|
|
OK=False
|
|
|
|
test=False
|
|
c1=path.isfile(data['saneName'])
|
|
if c1:
|
|
c2=(data['saneName']!=data['crackedName'])
|
|
if c2:
|
|
test=True
|
|
else:
|
|
message('E','sane mesh and cracked mesh are identical',goOn=True)
|
|
OK=False
|
|
if not test:
|
|
message('E','Bad sane mesh file',goOn=True)
|
|
OK=False
|
|
|
|
test=testStrictRange(data['minSize'])
|
|
if not test:
|
|
message('E','invalid min size',goOn=True)
|
|
OK=False
|
|
|
|
test=testStrictRange(data['maxSize'])
|
|
if not test:
|
|
message('E','invalid max size',goOn=True)
|
|
OK=False
|
|
|
|
if OK:
|
|
test=(data['maxSize'][0]>=data['minSize'][0])
|
|
if not test:
|
|
message('E','min size greater than max size',goOn=True)
|
|
OK=False
|
|
|
|
test=testStrictRange(data['extractLength'])
|
|
if not test:
|
|
message('E','invalid extract length',goOn=True)
|
|
OK=False
|
|
|
|
test=testRange(data['gradation'], inf=1.0)
|
|
if not test:
|
|
message('E','invalid Gradation',goOn=True)
|
|
OK=False
|
|
|
|
test=testRange(data['layers'], inf=1)
|
|
if not test:
|
|
message('E','invalid layers',goOn=True)
|
|
OK=False
|
|
|
|
test=testRange(data['iterations'], inf=1)
|
|
if not test:
|
|
message('E','invalid iterations',goOn=True)
|
|
OK=False
|
|
return(OK)
|
|
|
|
|
|
def calcElemSize(A, R):
|
|
x=R*(1.-numpy.cos(A/2.))
|
|
h=R*numpy.sin(A/2.)
|
|
return(x, h)
|
|
|
|
def meshCrack(geomObject, minSize, maxSize, chordal, dim):
|
|
import salome
|
|
|
|
salome.salome_init()
|
|
|
|
import SMESH, SALOMEDS
|
|
from salome.smesh import smeshBuilder
|
|
smesh = smeshBuilder.New()
|
|
Maillage = smesh.Mesh(geomObject)
|
|
|
|
if dim==3:
|
|
MG_CADSurf = Maillage.Triangle(algo=smeshBuilder.MG_CADSurf)
|
|
MG_CADSurf_Parameters = MG_CADSurf.Parameters()
|
|
MG_CADSurf_Parameters.SetPhysicalMesh( 0 )
|
|
MG_CADSurf_Parameters.SetGeometricMesh( 1 )
|
|
MG_CADSurf_Parameters.SetMinSize( minSize )
|
|
MG_CADSurf_Parameters.SetMaxSize( maxSize )
|
|
MG_CADSurf_Parameters.SetChordalError( chordal )
|
|
|
|
elif dim==2:
|
|
Regular_1D = Maillage.Segment()
|
|
Adaptive = Regular_1D.Adaptive(minSize,maxSize,chordal)
|
|
NETGEN_2D_ONLY = Maillage.Triangle(algo=smeshBuilder.NETGEN_2D)
|
|
else:
|
|
message('E',"error in mesh dimension",goOn=True)
|
|
|
|
isDone = Maillage.Compute()
|
|
|
|
#crack1 = Maillage.CreateEmptyGroup( SMESH.NODE, 'crack' )
|
|
#nbAdd = crack1.AddFrom( Maillage.GetMesh() )
|
|
#crack2 = Maillage.CreateEmptyGroup( SMESH.NODE, 'surface' )
|
|
#nbAdd = crack2.AddFrom( Maillage.GetMesh() )
|
|
|
|
return(Maillage)
|
|
|
|
def extendElsets(meshFile, outFile=None):
|
|
|
|
if outFile==None: outFile=meshFile
|
|
|
|
if not path.isfile(meshFile):
|
|
message('E','Mesh med file is not valid')
|
|
return('error')
|
|
|
|
import SMESH, salome
|
|
#salome.salome_init()
|
|
from salome.smesh import smeshBuilder
|
|
smesh = smeshBuilder.New()
|
|
|
|
([mesh], status) = smesh.CreateMeshesFromMED(meshFile)
|
|
|
|
if mesh.NbVolumes()>0:
|
|
case2D=False
|
|
mesh.Reorient2DBy3D( [ mesh ], mesh, 1 )
|
|
else:
|
|
case2D=True
|
|
|
|
mesh=cleanGroups(mesh)
|
|
|
|
# Node color status
|
|
nodeList=mesh.GetNodesId()
|
|
volElemList=mesh.GetElementsByType(SMESH.VOLUME)
|
|
surfElemList=mesh.GetElementsByType(SMESH.FACE)
|
|
edgeElemList=mesh.GetElementsByType(SMESH.EDGE)
|
|
colorList=[-1]*len(nodeList)
|
|
|
|
case2D=True
|
|
for group in mesh.GetGroups():
|
|
if group.GetType()==SMESH.VOLUME and group.GetName()[:5]=='sides' : case2D=False
|
|
|
|
sides=[]
|
|
for group in mesh.GetGroups():
|
|
if case2D:
|
|
if group.GetType()==SMESH.FACE and group.GetName()[:5]=='sides':
|
|
sides.append(group)
|
|
else:
|
|
if group.GetType()==SMESH.VOLUME and group.GetName()[:5]=='sides':
|
|
sides.append(group)
|
|
|
|
sortedSides=[None]*len(sides)
|
|
for group in sides:
|
|
N=group.GetName().replace('sides','').replace('_bset','').replace(' ','')
|
|
N=int(N)
|
|
sortedSides[N]=group
|
|
|
|
elems=group.GetIDs()
|
|
for elemId in elems:
|
|
for elemNodeId in mesh.GetElemNodes(elemId) :
|
|
colorList[elemNodeId-1]=N
|
|
#print colorList
|
|
|
|
crackOnly=True
|
|
for iN in range(len(sides)/2):
|
|
side0=sortedSides[2*iN]
|
|
side1=sortedSides[2*iN+1]
|
|
elemsOfside0=side0.GetIDs()
|
|
elemsOfside1=side1.GetIDs()
|
|
NodesOfside0=[]
|
|
NodesOfside1=[]
|
|
for elem in elemsOfside0: NodesOfside0+=mesh.GetElemNodes(elem)
|
|
for elem in elemsOfside1: NodesOfside1+=mesh.GetElemNodes(elem)
|
|
front=set(NodesOfside0).intersection(set(NodesOfside1))
|
|
if len(front)==0: crackOnly=False
|
|
|
|
if crackOnly:
|
|
mesh.ExportMED(outFile)
|
|
return('crack')
|
|
|
|
# Propagates color using elem connectivity
|
|
# Always propagates max color
|
|
|
|
#elemToTreat=volElemList
|
|
|
|
#while len(elemToTreat)>0 :
|
|
#print len(elemToTreat)
|
|
#for elemId in elemToTreat:
|
|
#minColor=sys.maxint
|
|
#maxColor=-sys.maxint
|
|
#for elemNodeId in mesh.GetElemNodes(elemId) :
|
|
#nodeColor=colorList[elemNodeId-1]
|
|
#if nodeColor<minColor : minColor=nodeColor
|
|
#if nodeColor>maxColor : maxColor=nodeColor
|
|
#if minColor!=maxColor :
|
|
#elemToTreat.remove(elemId)
|
|
#for elemNodeId in mesh.GetElemNodes(elemId) :
|
|
#colorList[elemNodeId-1]=maxColor
|
|
|
|
ifChanged=True
|
|
if case2D:
|
|
elemList=[surfElemList,edgeElemList]
|
|
grElemList=[[],[]]
|
|
else:
|
|
elemList=[volElemList,surfElemList,edgeElemList]
|
|
grElemList=[[],[],[]]
|
|
|
|
while ifChanged :
|
|
ifChanged=False
|
|
for elemId in elemList[0]:
|
|
minColor=sys.maxsize
|
|
maxColor=-sys.maxsize
|
|
for elemNodeId in mesh.GetElemNodes(elemId) :
|
|
nodeColor=colorList[elemNodeId-1]
|
|
if nodeColor<minColor : minColor=nodeColor
|
|
if nodeColor>maxColor : maxColor=nodeColor
|
|
if minColor!=maxColor :
|
|
ifChanged = True
|
|
for elemNodeId in mesh.GetElemNodes(elemId) :
|
|
colorList[elemNodeId-1]=maxColor
|
|
|
|
for l in grElemList:
|
|
for x in range(len(sides)):
|
|
l.append([])
|
|
|
|
for N, el in enumerate(elemList):
|
|
for elemId in el:
|
|
elemNodesId=mesh.GetElemNodes(elemId)
|
|
elemColor=colorList[elemNodesId[0]-1]
|
|
if elemColor>=0:
|
|
grElemList[N][elemColor].append(elemId)
|
|
|
|
#for elemId in surfElemList:
|
|
#elemNodesId=mesh.GetElemNodes(elemId)
|
|
#elemColor=colorList[elemNodesId[0]-1]
|
|
#if elemColor>=0:
|
|
#selem[elemColor].append(elemId)
|
|
|
|
for n in range(len(sides)):
|
|
if case2D:
|
|
mesh.MakeGroupByIds('Extended_side%d' %n ,SMESH.FACE,grElemList[0][n])
|
|
mesh.MakeGroupByIds('Extended_side%d' %n ,SMESH.EDGE,grElemList[1][n])
|
|
else:
|
|
mesh.MakeGroupByIds('Extended_side%d' %n ,SMESH.VOLUME,grElemList[0][n])
|
|
mesh.MakeGroupByIds('Extended_side%d' %n ,SMESH.FACE,grElemList[1][n])
|
|
mesh.MakeGroupByIds('Extended_side%d' %n ,SMESH.EDGE,grElemList[2][n])
|
|
|
|
if outFile==None: outFile=meshFile
|
|
mesh.ExportMED(outFile)
|
|
return(True)
|
|
|
|
|
|
def cleanGroups(mesh):
|
|
import SMESH
|
|
for group in mesh.GetGroups():
|
|
if '_bset' in group.GetName():
|
|
group.SetName(group.GetName().replace('_bset',''))
|
|
|
|
if group.GetType()==SMESH.NODE:
|
|
if group.GetName() in ['SURFACE','lip','SFRONT_NODES','FRONT']: mesh.RemoveGroup(group)
|
|
|
|
#elif group.GetType()==SMESH.EDGE:
|
|
|
|
elif group.GetType()==SMESH.FACE:
|
|
if group.GetName() in ['SURFACE','Nlip']:
|
|
mesh.RemoveGroup(group)
|
|
|
|
elif group.GetType()==SMESH.VOLUME:
|
|
if (group.GetName() in ['ELSET0','AUTO']) or (group.GetName()[:4] in ['SIDE']) :
|
|
mesh.RemoveGroup(group)
|
|
|
|
return(mesh)
|
|
|
|
|
|
def getMaxAspectRatio(tmpdir):
|
|
logFile=path.join(tmpdir,'MESHING_OUTPUT')
|
|
print(logFile)
|
|
if not path.isfile(logFile): return(-1)
|
|
|
|
import re
|
|
f = open(logFile, "r")
|
|
for line in f:
|
|
if re.search("WORST ELEMENT QUALITY", line): maxAR=line
|
|
|
|
f.close()
|
|
for r in [' ','WORSTELEMENTQUALITY','\n']: maxAR=maxAR.replace(r,'')
|
|
return(float(maxAR))
|
|
|
|
|
|
|
|
|
|
def removeFromSessionPath(envVar, patern):
|
|
if not isinstance(patern, list): patern=[patern]
|
|
if not isinstance(envVar, list): envVar=[envVar]
|
|
|
|
for env in envVar:
|
|
path=environ[env]
|
|
listPath=path.split(':')
|
|
for p in listPath:
|
|
for pat in patern:
|
|
if pat in p:
|
|
path=path.replace(p,'')
|
|
path.replace('::',':')
|
|
environ[env]=path
|
|
|
|
|
|
#def isPlane(geomObject, eps=1.e-9):
|
|
#import salome
|
|
#salome.salome_init()
|
|
#theStudy = salome.myStudy
|
|
|
|
#import salome_notebook
|
|
#notebook = salome_notebook.NoteBook(theStudy)
|
|
|
|
#import GEOM
|
|
#from salome.geom import geomBuilder
|
|
#geompy = geomBuilder.New(theStudy)
|
|
|
|
#Vs=geompy.SubShapeAll(geomObject, geompy.ShapeType["VERTEX"])
|
|
#if len(Vs)<=3:
|
|
#return(True)
|
|
#elif len(Vs)>3:
|
|
#P0=numpy.array(geompy.GetPosition(Vs[0])[:3])
|
|
#P1=numpy.array(geompy.GetPosition(Vs[1])[:3])
|
|
#P2=numpy.array(geompy.GetPosition(Vs[2])[:3])
|
|
#V01=P1-P0
|
|
#V02=P2-P0
|
|
#V12=P2-P1
|
|
#norm01=numpy.linalg.norm(V01)
|
|
#norm02=numpy.linalg.norm(V02)
|
|
#norm12=numpy.linalg.norm(V12)
|
|
#if (norm01<eps) or (norm02<eps) or (norm12<eps):
|
|
#print 'error'
|
|
#return(False)
|
|
#else:
|
|
#N=numpy.cross(V01,V02)
|
|
#N=N/numpy.linalg.norm(N)
|
|
#maxDist=0.
|
|
#for P in Vs[3:]:
|
|
#Pi=numpy.array(geompy.GetPosition(P)[:3])
|
|
#V=Pi-P0
|
|
#d=numpy.dot(V,N)
|
|
#maxDist=numpy.max([maxDist,numpy.abs(d)])
|
|
#else:
|
|
#print 'error'
|
|
#return(False)
|
|
|
|
#return(maxDist<eps)
|