"""This module stores base classes and functions.
Attributes:
RESFILEDS (dict): stores results fields under results type
key (str):
- 'displ': displacement
- 'stress': stress
- 'strain': strain
- 'force': force
value (list):
- 'displ' = 'ux','uy','uz','utot'
- 'stress' = 'Sx','Sy','Sz','Sxy','Syz','Szx','Seqv','S1','S2','S3'
- 'strain' = 'ex','ey','ez','exy','eyz','ezx','eeqv','e1','e2','e3'
- 'force' = 'fx','fy','fz'
FIELDTYPE (dict): the inverse dict of RESFIELDS
For example: key 'ux' --> value: 'displ'
"""
from math import ceil
from . import environment
RESFIELDS = {}
RESFIELDS['displ'] = 'ux,uy,uz,utot'.split(',')
RESFIELDS['stress'] = 'Sx,Sy,Sz,Sxy,Syz,Szx,Seqv,S1,S2,S3'.split(',')
RESFIELDS['strain'] = 'ex,ey,ez,exy,eyz,ezx,eeqv,e1,e2,e3'.split(',')
RESFIELDS['force'] = 'fx,fy,fz'.split(',')
#FIELDTYPE is a dict that inverts the RESFIELDS dictionary mapping.
FIELDTYPE = {}
for (k, v) in RESFIELDS.items():
for vi in v:
FIELDTYPE[vi] = k
[docs]class Idobj(object):
"""Makes an object that stores an id number.
This is a base class for nodes, lines, areas etc.
Attributes:
id (int): the unique id number for the item
"""
def __init__(self):
self.id = -1
[docs] def set_id(self, id):
"""Sets the id number """
self.id = id
def __hash__(self):
"""Sets the hash of the item to the id number.
This allows one to make sets of these items.
"""
return self.id
[docs]def plot_finish(plt, fname, display):
"""Display and or save plot."""
if fname != '':
# save the image
fname += '.png'
if environment.DPI != None:
plt.savefig(fname, dpi=environment.DPI, bbox_inches='tight')
else:
plt.savefig(fname, bbox_inches='tight')
print('File %s was saved.' % fname)
if display:
plt.tight_layout()
plt.show()
# remove all figures
plt.close()
[docs]def plot_set_bounds(plt, axials, radials):
"""Sets the axial and radial bounds of the shown plot."""
vert = max(radials) - min(radials)
horiz = max(axials) - min(axials)
vadder = (vert)/5
hadder = (horiz)/5
(vmax, vmin) = (max(radials)+vadder, min(radials)-vadder)
(hmax, hmin) = (max(axials)+hadder, min(axials)-hadder)
plt.xlim(hmin, hmax)
plt.ylim(vmin, vmax)
[docs]class Itemlist(list):
"""Makes a custom list used to store lists of non-mesh items.
non-mesh items = Point, Line, Arc, Area, Part, Components, Loads
This class allows us to automatically assign id numbers to items in the
list. Thes id numbers are needed when we send geometry out for meshing.
All instances of this class start as empty lists.
"""
def __init__(self):
super().__init__() # these lists start empty
[docs] def get_ids(self):
"""Returns a list of ids. Loops through all items in self."""
return [a.id for a in self]
[docs] def get_next_id(self):
"""Returns the next unused id."""
ids = self.get_ids()
minid = 0
if len(ids) == 0:
return minid # list is empty so return the minid number
else:
ids = sorted(ids)
maxid = ids[-1]
unused = list(set(list(range(minid, maxid+2))) - set(ids))
return unused[0] # return first available id number
[docs] def append(self, item):
"""Adds an item to the list and sets the item's id.
Args:
item (Point or Line or Arc or Area or Part): item to add to the list
"""
idnum = self.get_next_id()
item.set_id(idnum)
super().append(item)
return item
[docs]class Meshlist(list):
"""Makes a custom list used to store lists of nodes and elements.
All instances of this class start as empty lists.
"""
def __init__(self):
list.__init__([])
[docs] def get_minid(self):
"""Returns the min id number in the list."""
ids = [x.id for x in self]
return min(ids)
[docs] def get_maxid(self):
"""Returns the max id number in the list."""
ids = [x.id for x in self]
return max(ids)
[docs] def idget(self, idnum):
"""Returns an item with the passed id number.
Args:
idnum (int): passed id number, we want the item that has this
Returns:
item or None: returns item if found, None if not found
"""
for item in self:
if item.id == idnum:
return item
#print ('ID %i was not found!' % (idnum))
return None
[docs] def set_minid(self, val):
"""Sets the min id to the passed val.
Args:
val (int): New min id number in the list
"""
print('Re-indexing elements to min element number of: %i' % val)
print('Old min:%i max:%i' % (self.get_minid(), self.get_maxid()))
minid = self.get_minid()
offset = minid - val
for item in self:
item.id -= offset
print('New min:%i max:%i' % (self.get_minid(), self.get_maxid()))
[docs]def chunk_list(inlist, size):
"""Returns a list of lists where each list <= size length.
Splits inlist into list of lists where each child list len <= size.
Args:
inlist (list): list that we want cut into smaller lists
size (int): max length of small lists returned
Returns:
res (list of lists): list of list where each child list <= size length
"""
res = []
numlists = ceil(len(inlist)/size)
for ind in range(numlists):
res.append(inlist[ind*size:(ind+1)*size])
return res
[docs]def listify(items):
"""Returns a list of items. If items is an object it puts it in a list.
If a list is passed, it returns the list without changing it.
If an object is passed, it returns a list with the object in it.
Args:
items (object or list): item or list to convert to a list
"""
if not isinstance(items, list):
items = [items]
return items