Skip to content

Commit

Permalink
Added pre-defined sets for faces, edges and vertices of RVE
Browse files Browse the repository at this point in the history
  • Loading branch information
AHartmaier committed Jul 14, 2024
1 parent fe5eece commit a69b73b
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/kanapy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ def write_abq(self, nodes=None, file=None, path='./', voxel_dict=None, grain_dic
units=units, gb_area=faces,
dual_phase=dual_phase,
ialloy=ialloy, grain_phase_dict=grpd,
thermal=thermal)
thermal=thermal, periodic=self.rve.periodic)
# if orientation exists and ialloy is defined also write material file with Euler angles
if not (self.mesh.grain_ori_dict is None or ialloy is None):
writeAbaqusMat(ialloy, self.mesh.grain_ori_dict,
Expand Down
129 changes: 129 additions & 0 deletions src/kanapy/initializations.py
Original file line number Diff line number Diff line change
Expand Up @@ -611,3 +611,132 @@ def set_stats(grains, ar=None, omega=None, deq_min=None, deq_max=None,
json.dump(ms_stats, outfile, indent=2)

return ms_stats


class NodeSets(object):
def __init__(self, nodes):
self.F0yz = [] # left nodes
self.F1yz = [] # right nodes
self.Fx0z = [] # bottom nodes
self.Fx1z = [] # top nodes
self.Fxy0 = [] # rear nodes
self.Fxy1 = [] # front nodes
self.surfSet = [] # nodes on any surface
maxX = max(nodes[:, 0])
minX = min(nodes[:, 0])
maxY = max(nodes[:, 1])
minY = min(nodes[:, 1])
maxZ = max(nodes[:, 2])
minZ = min(nodes[:, 2])
# select all nodes on a surface and assign to face
for i, coord in enumerate(nodes):
surface = False
if np.isclose(coord[0], maxX):
surface = True
self.F1yz.append(i)
if np.isclose(coord[0], minX):
surface = True
self.F0yz.append(i)
if np.isclose(coord[1], maxY):
surface = True
self.Fx1z.append(i)
if np.isclose(coord[1], minY):
surface = True
self.Fx0z.append(i)
if np.isclose(coord[2], maxZ):
surface = True
self.Fxy1.append(i)
if np.isclose(coord[2], minZ):
surface = True
self.Fxy0.append(i)
if surface:
self.surfSet.append(i)

# Find edges
# top front edge
E_T1 = np.intersect1d(self.Fxy1, self.Fx1z)
self.Ex11 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 0], E_T1)
# top back edge
E_T3 = np.intersect1d(self.Fxy0, self.Fx1z)
self.Ex10 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 0], E_T3)
# top left edge
E_T4 = np.intersect1d(self.F0yz, self.Fx1z)
self.E01z = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 2], E_T4)
# top right edge
E_T2 = np.intersect1d(self.F1yz, self.Fx1z)
self.E11z = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 2], E_T2)
# bottom front edge
E_B1 = np.intersect1d(self.Fxy1, self.Fx0z)
self.Ex01 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 0], E_B1)
# bottom back edge
E_B3 = np.intersect1d(self.Fxy0, self.Fx0z)
self.Ex00 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 0], E_B3)
# bottom left edge
E_B4 = np.intersect1d(self.F0yz, self.Fx0z)
self.E00z = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 2], E_B4)
# bottom right edge
E_B2 = np.intersect1d(self.F1yz, self.Fx0z)
self.E10z = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 2], E_B2)
# left front edge
E_M1 = np.intersect1d(self.F0yz, self.Fxy1)
self.E0y1 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 1], E_M1)
# right front edge
E_M2 = np.intersect1d(self.Fxy1, self.F1yz)
self.E1y1 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 1], E_M2)
# left rear edge
E_M4 = np.intersect1d(self.Fxy0, self.F0yz)
self.E0y0 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 1], E_M4)
# right rear edge
E_M3 = np.intersect1d(self.Fxy0, self.F1yz)
self.E1y0 = self.CreatePeriodicEdgeSets(self.surfSet, nodes[self.surfSet, 1], E_M3)

# find VERTICES
self.V001 = np.intersect1d(self.Ex01, self.E00z)[0] # V1
self.V101 = np.intersect1d(self.Ex01, self.E10z)[0] # V2
self.V000 = np.intersect1d(self.Ex00, self.E00z)[0] # H1
self.V100 = np.intersect1d(self.E10z, self.Ex00)[0] # H2
self.V111 = np.intersect1d(self.Ex11, self.E11z)[0] # V3
self.V110 = np.intersect1d(self.E11z, self.Ex10)[0] # H3
self.V011 = np.intersect1d(self.Ex11, self.E01z)[0] # V4
self.V010 = np.intersect1d(self.Ex10, self.E01z)[0] # H4

# CORNERNODES = [self.V000, self.V100, self.V010, self.V001, self.V011, self.V101, self.V110, self.V111]

def CreatePeriodicNodeSets(self, Nodes, sortCoord1, sortCoord2, NodeSet):
# Creates a List of Sorted Nodes with respect to sortCoord1 and sortCoord2 for faces
# Input: Nodeset of surface nodes
import operator
startList = []
sortedList = []
for number in NodeSet:
startList.append([number, sortCoord1[Nodes.index(number)], sortCoord2[Nodes.index(number)]])
startList.sort(key=operator.itemgetter(1, 2))
for item in range(len(startList)):
sortedList.append(startList[item][0])

return sortedList


def CreatePeriodicEdgeSets(self, Nodes, sortCoord, NodeSet):
# Creates a List of Sorted Nodes with respect to sortCoord for edges
import operator
startList = []
sortedList = []
for number in NodeSet:
startList.append([number, sortCoord[Nodes.index(number)]])
startList.sort(key=operator.itemgetter(1))
for item in range(len(startList)):
sortedList.append(startList[item][0])

return sortedList

def RemoveItemInList(self, NodeList, ReplaceNodeList):
# remove set of nodes from list
for item in ReplaceNodeList:
try:
NodeList.remove(item)
except ValueError:
pass

return NodeList

67 changes: 61 additions & 6 deletions src/kanapy/input_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def read_dump(file):

def export2abaqus(nodes, file, grain_dict, voxel_dict, units='mm',
gb_area=None, dual_phase=False, thermal=False,
ialloy=None, grain_phase_dict=None):
ialloy=None, grain_phase_dict=None, periodic=False):
r"""
Creates an ABAQUS input file with microstructure morphology information
in the form of nodes, elements and element sets. If "dual_phase" is true,
Expand All @@ -134,19 +134,27 @@ def export2abaqus(nodes, file, grain_dict, voxel_dict, units='mm',
.. note:: The nodal coordinates are written out in units of 1 mm or 1 :math:`\mu` m scale, as requested by the
user in the input file.
"""
from kanapy.initializations import NodeSets

def write_node_set(name, nset):
f.write(name)
for i, val in enumerate(nset[:-1], start=1):
if i % 16 == 0:
f.write(f'{val+1}\n')
else:
f.write(f'{val+1}, ')
f.write(f'{nset[-1]+1}\n')

def write_grain_sets():
# Create element sets for grains
for k, v in grain_dict.items():
f.write('*ELSET, ELSET=GRAIN{0}_SET\n'.format(k))
for enum, el in enumerate(v, 1):
for enum, el in enumerate(v[:-2], start=1):
if enum % 16 != 0:
if enum == len(v):
f.write('%d\n' % el)
else:
f.write('%d, ' % el)
f.write('%d, ' % el)
else:
f.write('%d\n' % el)
f.write('%d\n' % v[-1])
# Create sections
for k in grain_dict.keys():
if grain_phase_dict is None or grain_phase_dict[k] < nall:
Expand Down Expand Up @@ -207,6 +215,9 @@ def write_phase_sets():
else:
raise ValueError(f'Units must be either "mm" or "um", not "{0}"'
.format(units))
nsets = NodeSets(nodes)
if periodic:
p_eqs = None

with open(file, 'w') as f:
f.write('** Input file generated by kanapy\n')
Expand Down Expand Up @@ -275,6 +286,49 @@ def write_phase_sets():
f.write('**\n')
f.write('*Instance, name=PART-1-1, part=PART-1\n')
f.write('*End Instance\n')
f.write('**\n')
f.write('** DEFINE NODE SETS\n')
f.write('** 1. VERTICES\n')
f.write(f'*Nset, nset=V000, instance=PART-1-1\n')
f.write(f'{nsets.V000+1}\n')
f.write(f'*Nset, nset=V001, instance=PART-1-1\n')
f.write(f'{nsets.V001+1}\n')
f.write(f'*Nset, nset=V010, instance=PART-1-1\n')
f.write(f'{nsets.V010+1}\n')
f.write(f'*Nset, nset=V100, instance=PART-1-1\n')
f.write(f'{nsets.V100+1}\n')
f.write(f'*Nset, nset=V011, instance=PART-1-1\n')
f.write(f'{nsets.V011+1}\n')
f.write(f'*Nset, nset=V101, instance=PART-1-1\n')
f.write(f'{nsets.V101+1}\n')
f.write(f'*Nset, nset=V110, instance=PART-1-1\n')
f.write(f'{nsets.V110+1}\n')
f.write(f'*Nset, nset=V111, instance=PART-1-1\n')
f.write(f'{nsets.V111+1}\n')
f.write('*Nset, nset=Vertices, instance=PART-1-1\n')
f.write(f'{nsets.V000+1}, {nsets.V100+1}, {nsets.V010+1}, {nsets.V001+1}, {nsets.V011+1}, '
f'{nsets.V101+1}, {nsets.V110+1}, {nsets.V111+1}\n')
f.write('** 2. EDGES\n')
write_node_set('*Nset, nset=Ex00, instance=PART-1-1\n', nsets.Ex00)
write_node_set('*Nset, nset=Ex01, instance=PART-1-1\n', nsets.Ex01)
write_node_set('*Nset, nset=Ex10, instance=PART-1-1\n', nsets.Ex10)
write_node_set('*Nset, nset=Ex11, instance=PART-1-1\n', nsets.Ex11)
write_node_set('*Nset, nset=E0y0, instance=PART-1-1\n', nsets.E0y0)
write_node_set('*Nset, nset=E0y1, instance=PART-1-1\n', nsets.E0y1)
write_node_set('*Nset, nset=E1y0, instance=PART-1-1\n', nsets.E1y0)
write_node_set('*Nset, nset=E1y1, instance=PART-1-1\n', nsets.E1y1)
write_node_set('*Nset, nset=E00z, instance=PART-1-1\n', nsets.E00z)
write_node_set('*Nset, nset=E01z, instance=PART-1-1\n', nsets.E01z)
write_node_set('*Nset, nset=E10z, instance=PART-1-1\n', nsets.E10z)
write_node_set('*Nset, nset=E11z, instance=PART-1-1\n', nsets.E11z)
f.write('** 3. FACES\n')
write_node_set(f'*Nset, nset=Fxy0, instance=PART-1-1\n', nsets.Fxy0)
write_node_set(f'*Nset, nset=Fxy1, instance=PART-1-1\n', nsets.Fxy1)
write_node_set(f'*Nset, nset=Fx0z, instance=PART-1-1\n', nsets.Fx0z)
write_node_set(f'*Nset, nset=Fx1z, instance=PART-1-1\n', nsets.Fx1z)
write_node_set(f'*Nset, nset=F0yz, instance=PART-1-1\n', nsets.F0yz)
write_node_set(f'*Nset, nset=F1yz, instance=PART-1-1\n', nsets.F1yz)
f.write('**\n')
f.write('*End Assembly\n')
f.write('**\n')
f.write('**\n')
Expand All @@ -296,6 +350,7 @@ def write_phase_sets():
f.write('**\n')
f.write('*Include, input={}mat.inp\n'.format(file[0:-8]))
f.write('**\n')
f.write('**Include, input=REM_PART.inp\n') # prepare include for BC and step definitions
print('---->DONE!\n')
return

Expand Down
5 changes: 3 additions & 2 deletions tests/test_input_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def test_read_dump(temp_dump):

def test_export_abaqus():

nodes = [[1., 0., 1.], [1., 0., 0.], [0., 0., 0.], [0., 0., 1.], [1., 1., 1.], [1., 1., 0.], [0., 1., 0.],
nodes = np.array(
[[1., 0., 1.], [1., 0., 0.], [0., 0., 0.], [0., 0., 1.], [1., 1., 1.], [1., 1., 0.], [0., 1., 0.],
[0., 1., 1.], [2., 0., 1.], [2., 0., 0.], [2., 1., 1.], [2., 1., 0.], [3., 0., 1.], [3., 0., 0.],
[3., 1., 1.], [3., 1., 0.], [1., 2., 1.], [1., 2., 0.], [0., 2., 0.], [0., 2., 1.], [2., 2., 1.],
[2., 2., 0.], [3., 2., 1.], [3., 2., 0.], [1., 3., 1.], [1., 3., 0.], [0., 3., 0.], [0., 3., 1.],
Expand All @@ -74,7 +75,7 @@ def test_export_abaqus():
[2., 2., 2.], [3., 2., 2.], [1., 3., 2.], [0., 3., 2.], [2., 3., 2.], [3., 3., 2.], [1., 0., 3.],
[0., 0., 3.], [1., 1., 3.], [0., 1., 3.], [2., 0., 3.], [2., 1., 3.], [3., 0., 3.], [3., 1., 3.],
[1., 2., 3.], [0., 2., 3.], [2., 2., 3.], [3., 2., 3.], [1., 3., 3.], [0., 3., 3.], [2., 3., 3.],
[3., 3., 3.]]
[3., 3., 3.]])

ed = {1: [1, 2, 3, 4, 5, 6, 7, 8], 2: [9, 10, 2, 1, 11, 12, 6, 5], 3: [13, 14, 10, 9, 15, 16, 12, 11],
4: [5, 6, 7, 8, 17, 18, 19, 20], 5: [11, 12, 6, 5, 21, 22, 18, 17], 6: [15, 16, 12, 11, 23, 24, 22, 21],
Expand Down

0 comments on commit a69b73b

Please sign in to comment.