Skip to content
This repository has been archived by the owner on Feb 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #7 from KyPy/master
Browse files Browse the repository at this point in the history
Update: meshmodes, nonlinear material, gradient plotting
  • Loading branch information
spacether committed Jul 6, 2015
2 parents ac5ee3c + 93e9b7f commit 44b3513
Show file tree
Hide file tree
Showing 5 changed files with 378 additions and 48 deletions.
128 changes: 107 additions & 21 deletions pycalculix/feamodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,22 @@ def set_ediv(self, items, ediv):
items = self.get_items(items)
for line in items:
line.set_ediv(ediv)

def set_esize(self, items, esize):
"""Sets the element size on the passed line.
Args:
items (str or SignLine or SignArc or list): lines or points to set esize on
- str: 'L0'
- list of str ['L0', 'L1', 'P3']
- list of SignLine or SignArc part.bottom or part.hole[-1]
esize (float): size of the mesh elements on the line
"""
items = self.get_items(items)
for item in items:
item.set_esize(esize)

def set_units(self, dist_unit='m', cfswitch=False):
"""Sets the units that will be displayed when plotting.
Expand Down Expand Up @@ -1424,7 +1440,7 @@ def __read_inp(self, fname):
L = line.split(',')
L = [int(a.strip()) for a in L]
enum = L[0]
nlist = [N.idget(a) for a in L[1:]]
nlist = [Dict_NodeIDs[a] for a in L[1:]]
e = mesh.Element(enum, etype, nlist)
faces = e.faces
E.append(e)
Expand Down Expand Up @@ -1477,7 +1493,7 @@ def __read_inp(self, fname):
sets[set_type][set_name] = []
mode = 'set'
f.close()

# loop through sets and remove empty sets
# store sets to delete
todel = []
Expand Down Expand Up @@ -1569,30 +1585,78 @@ def __read_inp(self, fname):
print('Nodes: %i' % len(N))
print('Done reading Calculix/Abaqus .inp file')

def mesh(self, fineness=1.0, mesher='gmsh'):
def mesh(self, size=1.0, meshmode='fineness', mesher='gmsh'):
"""Meshes all parts.
Args:
fineness (float): 0.0001 - 1.0, how fine the mesh is.
- Low numbers are very fine, higher numbers are coarser.
size (float):
- if meshmode == 'fineness' (default):
- mesh size is adapted to geometry size
- set size = 0.0001 - 1.0, to define how fine the mesh is.
- Low numbers are very fine, higher numbers are coarser.
- if meshmode == 'esize':
- element size is kept constant
- choose it depending on geometry size
- it should be reduced e.g. at arcs with small radius, by calling line.esize function
meshmode (str):
- 'fineness': adapt mesh size to geometry
- 'esize': keep explicitly defined element size
meshmode is changed to 'esize' is used if esize property is set to points or lines
mesher (str): the mesher to use
- 'gmsh': mesh with Gmsh, this is reccomended, it allows holes
- 'cgx': mesh with Calculix cgx, it doesn't allow holes
"""


#check if element size is set to points and change meshmode if necessary
for pt in self.points:
if pt.esize != None:
if meshmode=='fineness': print('meshmode is changed to esize, because elementsize was defined on points!')
meshmode = 'esize'


#if meshmode esize is chosen: ediv's on lines and arcs are transformed to element sizes on start and end point
if meshmode == 'esize':
for line in self.lines:
if line.ediv != None:
line.pt(0).set_esize(line.length()/line.ediv)
line.pt(1).set_esize(line.length()/line.ediv)


if mesher == 'gmsh':
self.__mesh_gmsh(fineness)
self.__mesh_gmsh(size, meshmode)
elif mesher == 'cgx':
self.__mesh_cgx(fineness)
self.__mesh_cgx(size)

def __mesh_gmsh(self, fineness):
def __mesh_gmsh(self, size, meshmode):
"""Meshes all parts using the Gmsh mesher.
Args:
fineness (float): 0.0001 - 1.0, how fine the mesh is.
Low numbers are very fine, higher numbers are coarser.
size (float):
- if meshmode == 'fineness' (default):
- mesh size is adapted to geometry size
- set size = 0.0001 - 1.0, to define how fine the mesh is.
- Low numbers are very fine, higher numbers are coarser.
- if meshmode == 'esize':
- element size is kept constant
- choose it depending on geometry size
meshmode (str):
- 'fineness': adapt mesh size to geometry
- 'esize': keep explicitly defined element size
"""
geo = []
ids = {}
Expand All @@ -1602,6 +1666,15 @@ def __mesh_gmsh(self, fineness):
# write all points
for pt in self.points:
txtline = 'Point(%i) = {%f, %f, %f};' % (pt.id, pt.x, pt.y, 0.0)

if meshmode == 'esize':
#add element size to points
if pt.esize == None:
txtline = txtline.replace('}', ', %f}' % (size if self.eshape=='tri' else size*2.))
#txtline = txtline.replace('}', ', %f}' % (size))
else:
txtline = txtline.replace('}', ', %f}' % (pt.esize if self.eshape=='tri' else pt.esize*2.))
#txtline = txtline.replace('}', ', %f}' % (pt.esize))
geo.append(txtline)

# start storing an index number
Expand All @@ -1622,7 +1695,7 @@ def __mesh_gmsh(self, fineness):
geo.append(txtline)

# set division if we have it
if line.ediv != None:
if line.ediv != None and meshmode=='fineness':
ndiv = line.ediv+1
esize = line.length()/line.ediv
if self.eshape == 'quad':
Expand Down Expand Up @@ -1690,8 +1763,8 @@ def __mesh_gmsh(self, fineness):
geo.append(txtline)

# set the meshing options
geo.append('Mesh.CharacteristicLengthFactor = '
+str(fineness)+'; //mesh fineness')
if meshmode == 'fineness':
geo.append('Mesh.CharacteristicLengthFactor = '+str(size)+'; //mesh fineness')
geo.append('Mesh.RecombinationAlgorithm = 1; //blossom')

if self.eshape == 'quad':
Expand Down Expand Up @@ -1740,13 +1813,26 @@ def __mesh_gmsh(self, fineness):
# read in the calculix mesh
self.__read_inp(self.fname+'.inp')

def __mesh_cgx(self, fineness):
def __mesh_cgx(self, size, meshmode):
"""Meshes all parts using the Calculix cgx mesher.
Args:
fineness (float): 0.0001 - 1.0, how fine the mesh is.
Low numbers are very fine, higher numbers are coarser.
size (float):
- if meshmode == 'fineness' (default):
- mesh size is adapted to geometry size
- set size = 0.0001 - 1.0, to define how fine the mesh is.
- Low numbers are very fine, higher numbers are coarser.
- if meshmode == 'esize': NOT TESTED WITH CGX
- element size is kept constant
- choose it depending on geometry size
meshmode (str):
- 'fineness': adapt mesh size to geometry
- 'esize': keep explicitly defined element size NOT TESTED WITH CGX
"""
fbd = []
comps = []
Expand All @@ -1770,8 +1856,8 @@ def __mesh_cgx(self, fineness):
cgx_elements['quad2plstrain'] = 'qu8e'
cgx_elements['quad1plstrain'] = 'qu4e'

num = 1.0/fineness
emult = int(round(num)) # this converts fineness to mesh multiplier
num = 1.0/size
emult = int(round(num)) # this converts size to mesh multiplier

# write all points
for point in self.points:
Expand Down
48 changes: 45 additions & 3 deletions pycalculix/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def __init__(self, x, y, z=0):
self.lines = []
self.arc_center = False
self.on_part = True
self.esize = None
base_classes.Idobj.__init__(self)

def get_name(self):
Expand Down Expand Up @@ -258,6 +259,10 @@ def __str__(self):
"""Returns string listing object type, id number, and coordinates"""
val = 'Point %s, (x, y)=(%.3f, %.3f)' % (self.get_name(), self.x, self.y)
return val

def set_esize(self, size):
self.esize = size



class Line(base_classes.Idobj):
Expand Down Expand Up @@ -352,6 +357,15 @@ def set_ediv(self, ediv):
ediv (int): number of required elements on this line
"""
self.ediv = ediv

def set_esize(self, esize):
"""Sets the size of mesh elements on the line when meshing.
Args:
esize (float): size of mesh elements on this line
"""
for i in range(2):
self.pt(i).set_esize(esize)

def signed_copy(self, sign):
"""Returns a SignLine copy of this Line with the passed sign."""
Expand Down Expand Up @@ -675,7 +689,11 @@ def set_pt(self, index, point):
def set_ediv(self, ediv):
"""Applies the element divisions onto the parent line."""
self.line.set_ediv(ediv)


def set_esize(self, esize):
"""Applies the element size onto the parent line."""
self.line.set_esize(esize)

def set_lineloop(self, lineloop):
"""Sets the parent LineLoop"""
# this is needed to cascade set ediv up to FEA model and down onto
Expand Down Expand Up @@ -869,15 +887,25 @@ def save_to_points(self):
"""This stores this line in the line's child points."""
for point in self.allpoints:
point.save_line(self)

def set_ediv(self, ediv):
"""Sets the number of element divisions on the arc when meshing.
Args:
ediv (int): number of required elements on this arc
"""
self.ediv = ediv

def set_esize(self, esize):
"""Sets the size of mesh elements on the arc when meshing.
Args:
esize (float): size of mesh elements on this arc
"""

for i in range(2):
self.pt(i).set_esize(esize)

def signed_copy(self, sign):
"""Returns a SignArc instance of this Arc with the passed sign."""
return SignArc(self, sign)
Expand Down Expand Up @@ -1256,6 +1284,10 @@ def set_pt(self, ind, point):
def set_ediv(self, ediv):
"""Apply the element divisions onto the parent line."""
self.line.set_ediv(ediv)

def set_esize(self, esize):
"""Applies the element size onto the parent line."""
self.line.set_esize(esize)

def set_lineloop(self, lineloop):
"""Sets the parent LineLoop"""
Expand Down Expand Up @@ -1657,7 +1689,7 @@ class Area(base_classes.Idobj):
signlines (list): list of signed lines or arcs that define the area
lines (list): a list of all the lines that make the area, includes hole
lines
point (list): a list of all points making the area, excludes arc centers
points (list): a list of all points making the area, excludes arc centers
allpoints (list): a list of all points, includes arc centers
holepoints (list): a list of hole points, excludes arc centers
matl (Matl): the material fo the area
Expand Down Expand Up @@ -1983,6 +2015,16 @@ def set_etype(self, etype):
"""
self.etype = etype
self.set_child_ccxtypes()

def set_esize(self, esize):
"""Sets the size of mesh elements on the area when meshing.
Args:
esize (float): size of mesh elements on this area
"""
#size if set if no mesh size on points is peresent
for p in self.points:
p.set_esize(esize)

def update(self, line_list):
"""Updates the area's external lines to the passed list.
Expand Down
Loading

0 comments on commit 44b3513

Please sign in to comment.