From a4316faa8eb28db6c930ed255160c8ab64d423d9 Mon Sep 17 00:00:00 2001 From: joha2 Date: Sat, 31 Mar 2018 18:03:38 +0200 Subject: [PATCH] FEM: Fenics mesh issue #0003038: xml import fixed --- src/Mod/Fem/feminout/importFenicsMesh.py | 3 +++ src/Mod/Fem/feminout/readFenicsXML.py | 28 +++++++++++++++++++----- src/Mod/Fem/feminout/writeFenicsXML.py | 17 ++++++++++++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/Mod/Fem/feminout/importFenicsMesh.py b/src/Mod/Fem/feminout/importFenicsMesh.py index 41a6e78697..fe5315940a 100644 --- a/src/Mod/Fem/feminout/importFenicsMesh.py +++ b/src/Mod/Fem/feminout/importFenicsMesh.py @@ -150,6 +150,9 @@ def export(objectslist, fileString): if fileString != "": fileName, fileExtension = os.path.splitext(fileString) if fileExtension.lower() == '.xml': + FreeCAD.Console.PrintWarning("XML is not designed to save higher order elements.\n") + FreeCAD.Console.PrintWarning("Reducing order for second order mesh.\n") + FreeCAD.Console.PrintWarning("Tri6 -> Tri3, Tet10 -> Tet4, etc.\n") writeFenicsXML.write_fenics_mesh_xml(obj, fileString) elif fileExtension.lower() == '.xdmf': if importToolsFem.get_FemMeshObjectMeshGroups(obj) is not (): diff --git a/src/Mod/Fem/feminout/readFenicsXML.py b/src/Mod/Fem/feminout/readFenicsXML.py index 41d1bf5a0e..ae2ecfba2f 100644 --- a/src/Mod/Fem/feminout/readFenicsXML.py +++ b/src/Mod/Fem/feminout/readFenicsXML.py @@ -61,6 +61,8 @@ def read_fenics_mesh_xml(xmlfilename): print("Mesh dimension: %d" % (dim,)) print("Mesh cell type: %s" % (cell_type,)) + # every cell type contains a dict with key=dimension and value=number + cells_parts_dim = {'point': {0: 1}, 'interval': {0: 2, 1: 1}, 'triangle': {0: 3, 1: 3, 2: 1}, @@ -178,6 +180,10 @@ def read_fenics_mesh_xml(xmlfilename): 'hexahedron': ['quadrilateral', 'interval'], 'quadrilateral': ['interval']} + # generate cell list from file + # read vertex list from cells + # generate lower dimensional objects in mesh from cell + for (cell_index, cell) in list(cell_dict.items()): cell_lower_dims = lower_dims_dict[cell_type] element_counter[cell_type] += 1 @@ -189,18 +195,25 @@ def read_fenics_mesh_xml(xmlfilename): vertextuple, element_counter[ld]) - length_counter = len(nodes) + length_counter = len(nodes) # maintain distinct counting values + # print("nodes") + # print("len & len counter", length_counter) for (key, val_dict) in list(element_dict.items()): # to ensure distinct indices for FreeCAD + # print('key: ', key) for (vkey, it) in list(val_dict.items()): - val_dict[vkey] = it + length_counter - length_counter += len(val_dict) + val_dict[vkey] = it + length_counter # maintain distinct element numbers + len_val_dict = len(val_dict) + if len_val_dict > 0: + length_counter += len_val_dict + 1 # only if preceeding list is not empty + # print('len: ', len_val_dict) + # print('lencounter: ', length_counter) # inverse of the dict (dict[key] = val -> dict[val] = key) element_dict[key] = invertdict(val_dict) - correct_volume_det(element_dict) + correct_volume_det(element_dict) # corrects negative determinants - return element_dict + return element_dict # returns complete element dictionary nodes = {} element_dict = {} @@ -219,6 +232,11 @@ def read_fenics_mesh_xml(xmlfilename): print("Mesh found") (nodes, cells_dict, cell_type, dim) = read_mesh_block(find_mesh) element_dict = generate_lower_dimensional_structures(nodes, cells_dict, cell_type, dim) + print("Show min max element dict") + for (elm, numbers) in list(element_dict.items()): + lst = sorted(list(numbers.items()), key=lambda x: x[0]) + if lst != []: + print(elm, " min: ", lst[0], " max: ", lst[-1]) else: print("No mesh found") diff --git a/src/Mod/Fem/feminout/writeFenicsXML.py b/src/Mod/Fem/feminout/writeFenicsXML.py index a2ea4b78e1..c432b89495 100644 --- a/src/Mod/Fem/feminout/writeFenicsXML.py +++ b/src/Mod/Fem/feminout/writeFenicsXML.py @@ -40,7 +40,9 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile): vertices to be exported. (For second order elements, we have to delete the mid element nodes.) """ - # TODO: check for second order elements (what to do? deny export or reduce element order?) + # TODO: check for second order elements + # (reduce element order would be ok - all elements have at least the first + # necessary nodes) FreeCAD_to_Fenics_dict = { "Triangle": "triangle", @@ -53,6 +55,15 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile): "Polygon": "unknown", "Polyhedron": "unknown", "Prism": "unknown", "Pyramid": "unknown", } + + XML_Number_of_Nodes_dict = { + "point": 1, + "interval": 2, + "triangle": 3, + "quadrilateral": 4, + "tetrahedron": 4, + "hexahedron": 8 + } print("Converting " + fem_mesh_obj.Label + " to fenics XML File") print("Dimension of mesh: %d" % (get_FemMeshObjectDimension(fem_mesh_obj),)) @@ -62,6 +73,7 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile): celltype_in_mesh = get_MaxDimElementFromList(elements_in_mesh) (num_cells, cellname_fc, dim_cell) = celltype_in_mesh cellname_fenics = FreeCAD_to_Fenics_dict[cellname_fc] + num_verts_cell = XML_Number_of_Nodes_dict[cellname_fenics] print("Celltype in mesh -> %s and its Fenics name: %s" % (str(celltype_in_mesh), cellname_fenics)) root = ET.Element("dolfin", dolfin="http://fenicsproject.org") @@ -90,7 +102,8 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile): cell_args = {} for (vi, ni) in enumerate(nodeindices): - cell_args["v" + str(vi)] = str(ni - 1) + if vi < num_verts_cell: # XML only supports first order meshs + cell_args["v" + str(vi)] = str(ni - 1) # generate as many v entries in dict as nodes are listed in cell (works only for first order elements) ET.SubElement(cells, cellname_fenics, index=str(fen_ind), **cell_args)