# *************************************************************************** # * Copyright (c) 2018 - FreeCAD Developers * # * Author: Bernd Hahnebach * # * * # * This file is part of the FreeCAD CAx development system. * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * # * the License, or (at your option) any later version. * # * for detail see the LICENCE text file. * # * * # * FreeCAD is distributed in the hope that it will be useful, * # * but WITHOUT ANY WARRANTY; without even the implied warranty of * # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * # * GNU Library General Public License for more details. * # * * # * You should have received a copy of the GNU Library General Public * # * License along with FreeCAD; if not, write to the Free Software * # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * # * USA * # * * # ***************************************************************************/ import Fem import FreeCAD import unittest from . import utilstest as testtools from .utilstest import fcc_print from os.path import join class TestMeshCommon(unittest.TestCase): fcc_print('import TestMeshCommon') # ******************************************************************************************** def setUp( self ): # setUp is executed before every test # setting up a document to hold the tests self.doc_name = self.__class__.__name__ if FreeCAD.ActiveDocument: if FreeCAD.ActiveDocument.Name != self.doc_name: FreeCAD.newDocument(self.doc_name) else: FreeCAD.newDocument(self.doc_name) FreeCAD.setActiveDocument(self.doc_name) self.active_doc = FreeCAD.ActiveDocument # ******************************************************************************************** def test_mesh_seg2_python( self ): seg2 = Fem.FemMesh() seg2.addNode(0, 0, 0, 1) seg2.addNode(2, 0, 0, 2) seg2.addNode(4, 0, 0, 3) seg2.addEdge([1, 2]) seg2.addEdge([2, 3], 2) node_data = [ seg2.NodeCount, seg2.Nodes ] edge_data = [ seg2.EdgeCount, seg2.Edges[0], seg2.getElementNodes(seg2.Edges[0]), seg2.Edges[1], seg2.getElementNodes(seg2.Edges[1]) ] expected_nodes = [ 3, { 1: FreeCAD.Vector(0.0, 0.0, 0.0), 2: FreeCAD.Vector(2.0, 0.0, 0.0), 3: FreeCAD.Vector(4.0, 0.0, 0.0) } ] expected_edges = [2, 1, (1, 2), 2, (2, 3)] self.assertEqual( node_data, expected_nodes, "Nodes of Python created seg2 element are unexpected" ) self.assertEqual( edge_data, expected_edges, "Edges of Python created seg2 element are unexpected" ) # ******************************************************************************************** def test_mesh_seg3_python( self ): seg3 = Fem.FemMesh() seg3.addNode(0, 0, 0, 1) seg3.addNode(1, 0, 0, 2) seg3.addNode(2, 0, 0, 3) seg3.addNode(3, 0, 0, 4) seg3.addNode(4, 0, 0, 5) seg3.addEdge([1, 3, 2]) seg3.addEdge([3, 5, 4], 2) node_data = [seg3.NodeCount, seg3.Nodes] edge_data = [ seg3.EdgeCount, seg3.Edges[0], seg3.getElementNodes(seg3.Edges[0]), seg3.Edges[1], seg3.getElementNodes(seg3.Edges[1]) ] expected_nodes = [ 5, { 1: FreeCAD.Vector(0.0, 0.0, 0.0), 2: FreeCAD.Vector(1.0, 0.0, 0.0), 3: FreeCAD.Vector(2.0, 0.0, 0.0), 4: FreeCAD.Vector(3.0, 0.0, 0.0), 5: FreeCAD.Vector(4.0, 0.0, 0.0) } ] expected_edges = [2, 1, (1, 3, 2), 2, (3, 5, 4)] self.assertEqual( node_data, expected_nodes, "Nodes of Python created seg3 element are unexpected" ) self.assertEqual( edge_data, expected_edges, "Edges of Python created seg3 element are unexpected" ) # ******************************************************************************************** def test_unv_save_load( self ): tetra10 = Fem.FemMesh() tetra10.addNode(6, 12, 18, 1) tetra10.addNode(0, 0, 18, 2) tetra10.addNode(12, 0, 18, 3) tetra10.addNode(6, 6, 0, 4) tetra10.addNode(3, 6, 18, 5) tetra10.addNode(6, 0, 18, 6) tetra10.addNode(9, 6, 18, 7) tetra10.addNode(6, 9, 9, 8) tetra10.addNode(3, 3, 9, 9) tetra10.addNode(9, 3, 9, 10) tetra10.addVolume([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) unv_file = testtools.get_fem_test_tmp_dir() + '/tetra10_mesh.unv' tetra10.write(unv_file) newmesh = Fem.read(unv_file) expected = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) self.assertEqual( newmesh.getElementNodes(1), expected, "Nodes order of quadratic volume element is unexpected" ) # ******************************************************************************************** def test_writeAbaqus_precision( self ): # https://forum.freecadweb.org/viewtopic.php?f=18&t=22759#p176669 # ccx reads only F20.0 (i. e. Fortran floating point field 20 chars wide) # thus precision is set to 13 in writeAbaqus seg2 = Fem.FemMesh() seg2.addNode(0, 0, 0, 1) seg2.addNode( # 3456789012345678901234567 -5000000000000000000.1, -1.123456789123456e-14, -0.1234567890123456789e-101, 2 ) seg2.addEdge([1, 2]) inp_file = testtools.get_fem_test_tmp_dir() + '/seg2_mesh.inp' seg2.writeABAQUS(inp_file, 1, False) read_file = open(inp_file, 'r') read_node_line = 'line was not found' for ln in read_file: ln = ln.strip() if ln.startswith('2, -5'): read_node_line = ln read_file.close() # 1234567 12345678901234567890 12345678901234567890 expected_win = '2, -5e+018, -1.123456789123e-014, -1.234567890123e-102' expected_lin = '2, -5e+18, -1.123456789123e-14, -1.234567890123e-102' expected = [expected_lin, expected_win] self.assertTrue( True if read_node_line in expected else False, "Problem in test_writeAbaqus_precision, \n{0}\n{1}".format( read_node_line, expected ) ) # ******************************************************************************************** def tearDown( self ): FreeCAD.closeDocument(self.doc_name) pass # ************************************************************************************************ class TestMeshEleTetra10(unittest.TestCase): fcc_print('import TestMeshEleTetra10') # ******************************************************************************************** def setUp( self ): # setUp is executed before every test # setting up a document to hold the tests self.doc_name = self.__class__.__name__ if FreeCAD.ActiveDocument: if FreeCAD.ActiveDocument.Name != self.doc_name: FreeCAD.newDocument(self.doc_name) else: FreeCAD.newDocument(self.doc_name) FreeCAD.setActiveDocument(self.doc_name) self.active_doc = FreeCAD.ActiveDocument # more inits self.elem = 'tetra10' self.base_testfile = join( testtools.get_fem_test_home_dir(), 'mesh', (self.elem + '_mesh.') ) self.base_outfile = join( testtools.get_fem_test_tmp_dir(), (self.elem + '_mesh.') ) # 10 node tetrahedron --> tetra10 femmesh = Fem.FemMesh() femmesh.addNode(6, 12, 18, 1) femmesh.addNode(0, 0, 18, 2) femmesh.addNode(12, 0, 18, 3) femmesh.addNode(6, 6, 0, 4) femmesh.addNode(3, 6, 18, 5) femmesh.addNode(6, 0, 18, 6) femmesh.addNode(9, 6, 18, 7) femmesh.addNode(6, 9, 9, 8) femmesh.addNode(3, 3, 9, 9) femmesh.addNode(9, 3, 9, 10) femmesh.addVolume([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) self.femmesh = femmesh self.expected_nodes = { 'count': 10, 'nodes': { 1: FreeCAD.Vector(6.0, 12.0, 18.0), 2: FreeCAD.Vector(0.0, 0.0, 18.0), 3: FreeCAD.Vector(12.0, 0.0, 18.0), 4: FreeCAD.Vector(6.0, 6.0, 0.0), 5: FreeCAD.Vector(3.0, 6.0, 18.0), 6: FreeCAD.Vector(6.0, 0.0, 18.0), 7: FreeCAD.Vector(9.0, 6.0, 18.0), 8: FreeCAD.Vector(6.0, 9.0, 9.0), 9: FreeCAD.Vector(3.0, 3.0, 9.0), 10: FreeCAD.Vector(9.0, 3.0, 9.0), } } self.expected_elem = { 'volcount': 1, 'tetcount': 1, 'volumes': [1, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)] } ''' fcc_print('\n') fcc_print(expected_nodes) fcc_print(expected_elem) fcc_print('\n') ''' # ******************************************************************************************** def get_file_paths( self, file_extension ): outfile = self.base_outfile + file_extension testfile = self.base_testfile + file_extension # fcc_print(outfile) # fcc_print(testfile) return (outfile, testfile) # ******************************************************************************************** def compare_mesh_files( self, femmesh_testfile, femmesh_outfile, filetyp ): # ''' fcc_print([ femmesh_testfile.Volumes[0], femmesh_testfile.getElementNodes(femmesh_outfile.Volumes[0]) ]) # ''' # test reading the test mesh self.assertEqual( femmesh_testfile.Nodes, self.expected_nodes['nodes'], "Test reading {} mesh to {} file failed. Nodes are different.\n".format( self.elem, filetyp ) ) self.assertEqual( [ femmesh_testfile.Volumes[0], femmesh_testfile.getElementNodes(femmesh_outfile.Volumes[0]) ], self.expected_elem['volumes'], "Test reading {} mesh to {} file failed. Volumes are different.\n".format( self.elem, filetyp ) ) # test reading the written mesh self.assertEqual( femmesh_outfile.Nodes, self.expected_nodes['nodes'], "Test reading {} mesh to {} file failed. Nodes are different.\n".format( self.elem, filetyp ) ) self.assertEqual( [ femmesh_outfile.Volumes[0], femmesh_outfile.getElementNodes(femmesh_outfile.Volumes[0]) ], self.expected_elem['volumes'], "Test reading {} mesh to {} file failed. Volumes are different.\n".format( self.elem, filetyp ) ) # test if both are equal self.assertEqual( femmesh_outfile.Nodes, femmesh_testfile.Nodes, "Test reading {} mesh to {} file failed. Nodes are different.\n".format( self.elem, filetyp ) ) self.assertEqual( femmesh_outfile.Volumes, femmesh_testfile.Volumes, "Test reading {} mesh to {} file failed. Volumes are different.\n".format( self.elem, filetyp ) ) # ******************************************************************************************** def test_tetra10_create( self ): # tetra10 element: creating by Python node_data = { 'count': self.femmesh.NodeCount, 'nodes': self.femmesh.Nodes } elem_data = { 'volcount': self.femmesh.VolumeCount, 'tetcount': self.femmesh.TetraCount, 'volumes': [ self.femmesh.Volumes[0], self.femmesh.getElementNodes(self.femmesh.Volumes[0]) ] } self.assertEqual( node_data, self.expected_nodes, "Nodes of Python created " + self.elem + "mesh element are unexpected" ) self.assertEqual( elem_data, self.expected_elem, "Elements of Python created " + self.elem + "mesh element are unexpected" ) ''' obj = doc.addObject("Fem::FemMeshObject" , elem) obj.FemMesh = femmesh obj.Placement.Base = (30,50,0) obj.ViewObject.DisplayMode = "Faces, Wireframe & Nodes" ''' # ******************************************************************************************** def test_tetra10_inp( self ): # tetra10 element: reading from and writing to inp mesh file format file_extension = 'inp' outfile, testfile = self.get_file_paths(file_extension) self.femmesh.writeABAQUS(outfile, 1, False) # write the mesh femmesh_outfile = Fem.read(outfile) # read the mesh from written mesh femmesh_testfile = Fem.read(testfile) # read the mesh from test mesh self.compare_mesh_files( femmesh_testfile, femmesh_outfile, file_extension ) # ******************************************************************************************** def test_tetra10_unv( self ): # tetra10 element: reading from and writing to unv mesh file format file_extension = 'unv' outfile, testfile = self.get_file_paths(file_extension) self.femmesh.write(outfile) # write the mesh femmesh_outfile = Fem.read(outfile) # read the mesh from written mesh femmesh_testfile = Fem.read(testfile) # read the mesh from test mesh self.compare_mesh_files( femmesh_testfile, femmesh_outfile, file_extension ) # ******************************************************************************************** def test_tetra10_vkt( self ): # tetra10 element: reading from and writing to unv mesh file format file_extension = 'vtk' outfile, testfile = self.get_file_paths(file_extension) if "BUILD_FEM_VTK" in FreeCAD.__cmake__: self.femmesh.write(outfile) # write the mesh femmesh_outfile = Fem.read(outfile) # read the mesh from written mesh femmesh_testfile = Fem.read(testfile) # read the mesh from test mesh self.compare_mesh_files( femmesh_testfile, femmesh_outfile, file_extension ) else: fcc_print('FEM_VTK post processing is disabled.') # ******************************************************************************************** def test_tetra10_yml( self ): # tetra10 element: reading from and writing to yaml/json mesh file format file_extension = 'yml' outfile, testfile = self.get_file_paths(file_extension) # TODO: implement yaml/json mesh reader writer method calls in C++ # self.femmesh.write(outfile) # write the mesh # femmesh_testfile = Fem.read(outfile) # read the mesh from written mesh # femmesh_outfile = Fem.read(testfile) # read the mesh from test mesh # directly use Python methods to read and write files from feminout.importYamlJsonMesh import write write(outfile, self.femmesh) from feminout.importYamlJsonMesh import read femmesh_testfile = read(outfile) femmesh_outfile = read(testfile) self.compare_mesh_files( femmesh_testfile, femmesh_outfile, file_extension ) # ******************************************************************************************** def test_tetra10_z88( self ): # tetra10 element: reading from and writing to z88 mesh file format file_extension = 'z88' outfile, testfile = self.get_file_paths(file_extension) self.femmesh.write(outfile) # write the mesh femmesh_testfile = Fem.read(outfile) # read the mesh from written mesh femmesh_outfile = Fem.read(testfile) # read the mesh from test mesh self.compare_mesh_files( femmesh_testfile, femmesh_outfile, file_extension ) # ******************************************************************************************** def tearDown( self ): # clearance, is executed after every test FreeCAD.closeDocument(self.doc_name) pass