Skip to content

Commit

Permalink
Resolve "Extend Gmsh-Reader to multiple surfaces"
Browse files Browse the repository at this point in the history
  • Loading branch information
aseibold committed Apr 8, 2020
1 parent 424edd9 commit 8ea00bc
Show file tree
Hide file tree
Showing 6 changed files with 489 additions and 16 deletions.
120 changes: 119 additions & 1 deletion amfe/component/partitioner.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import pandas as pd
from copy import deepcopy
from amfe.mesh import Mesh
from amfe.tools import invert_dictionary_with_iterables


class PartitionerBase:
Expand Down Expand Up @@ -49,7 +50,32 @@ class PartitionedMeshComponentSeparator(PartitionedComponentSeparator):
"""
def __init__(self):
super().__init__()


def set_partition_tags_by_group(self, mesh, group_subname='surface'):
"""
Resets partition tags in a mesh such that each combination of previous partition-id and tag-type-value is
unique. Hence for example no partition is on two different surfaces any more, as it might result from the
partitioning algorithm.
Parameters
----------
mesh : Mesh
mesh-object with partitions
group_subname : str
keyword, that shall be searched in the group-names
Returns
-------
None
"""
elements_by_tags = self._select_element_subset_by_group(mesh, group_subname)

elements_by_partition_ids = self._get_element_subset_by_partition_ids(mesh)

partition_map = self._create_new_partition_map(mesh, elements_by_tags, elements_by_partition_ids)

mesh.el_df = self._update_elements_with_new_partition_ids(mesh.el_df, partition_map, mesh.nodes_df)

def separate_partitioned_component(self, component):
"""
Seperates a component, which has a mesh, into several components of the same type. Hence its mesh has to be
Expand Down Expand Up @@ -204,3 +230,95 @@ def _assign_materials_to_new_component(new_component, old_component, old_materia
common_full_ele = np.intersect1d(full_mat_ele, full_phys_ele)
assign_eleids = np.intersect1d(common_full_ele, new_component.mesh.el_df.index)
new_component.assign_material(material, assign_eleids, phys, '_eleids')

@staticmethod
def _select_element_subset_by_group(mesh, group_subname):
subgroups = dict()

group_names = tuple(mesh.groups.keys())
for group in group_names:
if group_subname in group:
ele_ids = mesh.get_elementids_by_groups((group,))
if len(ele_ids) is not 0:
subgroups[group] = ele_ids

return subgroups

@staticmethod
def _get_element_subset_by_partition_ids(mesh):
partitions_old_list = mesh.get_uniques_by_tag('partition_id')
partition_id_2_eleids_old = dict()
for part_id in partitions_old_list:
partition_id_2_eleids_old[part_id] = mesh.get_elementids_by_tags('partition_id', part_id)

return partition_id_2_eleids_old

@staticmethod
def _create_new_partition_map(mesh, element_set_1, element_set_2):
partition_id = 1
partition_map = dict()
eles_that_have_partition_id = np.array([])

for group_id, group_eles in element_set_1.items():
for part_id, part_eles in element_set_2.items():
new_eles = np.intersect1d(group_eles, part_eles)
if new_eles.size is not 0:
partition_map[partition_id] = new_eles
eles_that_have_partition_id = np.append(eles_that_have_partition_id, new_eles)
partition_id += 1

eles_without_partition = np.setdiff1d(mesh.el_df.index.values, eles_that_have_partition_id)
if eles_without_partition.size is not 0:
for eleid in eles_without_partition:
nodeids = mesh.get_nodeids_by_elementids(eleid)
match_found = False
for part_id, part_eles in partition_map.items():
for part_ele in part_eles:
other_ele_nodeids = mesh.get_nodeids_by_elementids(part_ele)
if np.intersect1d(nodeids, other_ele_nodeids).size > 1:
partition_map[part_id] = np.append(partition_map[part_id], eleid)
match_found = True
break
if match_found:
break

return partition_map

@staticmethod
def _update_elements_with_new_partition_ids(el_df, partition_map, nodes_df):
ele2partition_dict = invert_dictionary_with_iterables(partition_map)
ele2partition_map = pd.DataFrame.from_dict(ele2partition_dict, orient='index')
el_df['partition_id'] = ele2partition_map

def check_neighbor(element1, element2):
is_neighbor = False
if element1['partition_id'] is not element2['partition_id']:
for node1 in element1['connectivity']:
for node2 in element2['connectivity']:
if np.isclose(nodes_df.loc[node1].to_numpy(), nodes_df.loc[node2].to_numpy()).all():
is_neighbor = True
break
if is_neighbor:
break
return is_neighbor

for eleid, element in el_df.iterrows():
no_of_partitions = 1
partition_neighbors = tuple()
for other_eleid, other_element in el_df.iterrows():
if other_eleid is not eleid and other_element['partition_id'] not in partition_neighbors and \
check_neighbor(element, other_element):
partition_neighbors += (other_element['partition_id'],)
no_of_partitions += len(partition_neighbors)
if len(partition_neighbors) is 0:
partition_neighbors = None
elif len(partition_neighbors) is 1:
partition_neighbors = partition_neighbors[0]
else:
partition_neighbors = list(partition_neighbors)
partition_neighbors.sort()
partition_neighbors = tuple(partition_neighbors)
el_df.at[eleid, 'partitions_neighbors'] = partition_neighbors
el_df.at[eleid, 'no_of_mesh_partitions'] = no_of_partitions

return el_df
2 changes: 2 additions & 0 deletions docs/release/1.1.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ amfe.assembly improvements
amfe.component improvements
---------------------------

- Partitioner redefines partition-ids of a mesh, such that unique combinations of tags and partition-ids are new
partition-ids, e.g. combination of manual partitioning with surface-groups and automatic partitions
- Added str-method to component

amfe.constraint improvements
Expand Down
14 changes: 0 additions & 14 deletions results/001_videos/convert_video.sh

This file was deleted.

96 changes: 96 additions & 0 deletions tests/meshes/3_surfaces_2_partitions_mesh.msh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
$MeshFormat
2.2 0 8
$EndMeshFormat
$PhysicalNames
5
1 8 "x_dirichlet-line"
1 9 "x_neumann"
2 5 "surface_left"
2 6 "surface_right"
2 7 "surface_top"
$EndPhysicalNames
$Nodes
31
1 0 0 0
2 0 5 0
3 5 5 0
4 5 0 0
5 10 0 0
6 10 5 0
7 0 10 0
8 10 10 0
9 2.499999999996199 0 0
10 5 2.499999999996199 0
11 2.5 5 0
12 0 2.5 0
13 7.176360840382222 0 0
14 7.176360840382227 5 0
15 5 2.5 0
16 2.499999999996199 5 0
17 7.176360840382222 5 0
18 5 10 0
19 0 7.176360840382227 0
20 2.5 2.5 0
21 1.2499999999981 1.25 0
22 1.25 3.75 0
23 3.7499999999981 1.2499999999981 0
24 3.750000000001901 3.749999999998099 0
25 8.22303669484285 2.552255592639131 0
26 6.540735812640291 1.811426457748249 0
27 6.3023563126068 3.480526007198198 0
28 2.842729718643214 7.449413862174849 0
29 6.088180420191112 7.499999999999999 0
30 8.316135315143335 6.875 0
31 1.335682429659853 6.156443675639268 0
$EndNodes
$Elements
48
1 1 4 8 4 1 2 2 12
2 1 4 8 4 1 2 12 1
3 1 4 9 6 1 1 5 6
4 1 4 9 11 1 2 6 8
5 1 4 8 13 1 2 7 19
6 1 4 8 13 1 2 19 2
7 2 4 5 1 1 1 24 23 10
8 2 5 5 1 2 1 -2 20 23 24
9 2 4 5 1 1 1 4 23 9
10 2 4 5 1 1 1 3 24 10
11 2 5 5 1 2 1 -2 9 23 20
12 2 5 5 1 2 1 -2 9 20 21
13 2 5 5 1 2 2 -1 1 21 12
14 2 5 5 1 2 2 -1 12 21 20
15 2 5 5 1 2 1 -2 11 20 24
16 2 5 5 1 2 2 -1 11 22 20
17 2 5 5 1 2 2 -1 12 20 22
18 2 5 5 1 2 1 -2 3 11 24
19 2 5 5 1 2 2 -1 2 22 11
20 2 4 5 1 1 2 2 12 22
21 2 4 5 1 1 1 4 10 23
22 2 5 5 1 2 1 -2 1 9 21
23 2 4 6 2 1 1 5 25 13
24 2 4 6 2 1 1 6 14 25
25 2 4 6 2 1 1 14 27 25
26 2 4 6 2 1 1 13 25 26
27 2 4 6 2 1 1 4 13 26
28 2 4 6 2 1 1 4 26 15
29 2 4 6 2 1 1 25 27 26
30 2 4 6 2 1 1 3 15 27
31 2 4 6 2 1 1 3 27 14
32 2 4 6 2 1 1 15 26 27
33 2 4 6 2 1 1 5 6 25
34 2 4 7 3 1 2 7 28 18
35 2 4 7 3 1 2 3 28 16
36 2 4 7 3 1 2 7 19 28
37 2 4 7 3 1 2 3 29 28
38 2 4 7 3 1 2 8 29 30
39 2 4 7 3 1 2 3 17 29
40 2 4 7 3 1 2 8 18 29
41 2 4 7 3 1 2 19 31 28
42 2 4 7 3 1 2 2 16 31
43 2 4 7 3 1 2 16 28 31
44 2 4 7 3 1 2 6 30 17
45 2 4 7 3 1 2 2 31 19
46 2 4 7 3 1 2 17 30 29
47 2 4 7 3 1 2 18 28 29
48 2 4 7 3 1 2 6 8 30
$EndElements
Loading

0 comments on commit 8ea00bc

Please sign in to comment.