# *************************************************************************** # * Copyright (c) 2015 - FreeCAD Developers * # * Author: Przemo Firszt * # * 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 from femtools import ccxtools import FreeCAD import ObjectsFem import unittest from . import utilstest as testtools from .utilstest import fcc_print from os.path import join class TestCcxTools(unittest.TestCase): fcc_print('import TestCcxTools') # ******************************************************************************************** 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.mesh_name = 'Mesh' self.temp_dir = testtools.get_fem_test_tmp_dir() self.test_file_dir = join( testtools.get_fem_test_home_dir(), 'ccx' ) # ******************************************************************************************** def test_1_static_analysis( self ): fcc_print('--------------- Start of FEM tests ---------------') box = self.active_doc.addObject("Part::Box", "Box") fcc_print('Checking FEM new analysis...') analysis = ObjectsFem.makeAnalysis( self.active_doc, 'Analysis' ) self.assertTrue( analysis, "FemTest of new analysis failed" ) fcc_print('Checking FEM new solver...') solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiX' ) solver_object.AnalysisType = 'static' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = 'default' solver_object.IterationsControlParameterTimeUse = False solver_object.EigenmodesCount = 10 solver_object.EigenmodeHighLimit = 1000000.0 solver_object.EigenmodeLowLimit = 0.0 self.assertTrue( solver_object, "FemTest of new solver failed" ) analysis.addObject(solver_object) fcc_print('Checking FEM new material...') material_object = ObjectsFem.makeMaterialSolid( self.active_doc, 'MechanicalMaterial' ) mat = material_object.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" material_object.Material = mat self.assertTrue( material_object, "FemTest of new material failed" ) analysis.addObject(material_object) fcc_print('Checking FEM new fixed constraint...') fixed_constraint = self.active_doc.addObject( "Fem::ConstraintFixed", "FemConstraintFixed" ) fixed_constraint.References = [(box, "Face1")] self.assertTrue( fixed_constraint, "FemTest of new fixed constraint failed" ) analysis.addObject(fixed_constraint) fcc_print('Checking FEM new force constraint...') force_constraint = self.active_doc.addObject( "Fem::ConstraintForce", "FemConstraintForce" ) force_constraint.References = [(box, "Face6")] force_constraint.Force = 40000.0 force_constraint.Direction = (box, ["Edge5"]) self.active_doc.recompute() force_constraint.Reversed = True self.active_doc.recompute() self.assertTrue( force_constraint, "FemTest of new force constraint failed" ) analysis.addObject(force_constraint) fcc_print('Checking FEM new pressure constraint...') pressure_constraint = self.active_doc.addObject( "Fem::ConstraintPressure", "FemConstraintPressure" ) pressure_constraint.References = [(box, "Face2")] pressure_constraint.Pressure = 1000.0 pressure_constraint.Reversed = False self.assertTrue( pressure_constraint, "FemTest of new pressure constraint failed" ) analysis.addObject(pressure_constraint) fcc_print('Checking FEM new mesh...') from .testfiles.ccx.cube_mesh import create_nodes_cube from .testfiles.ccx.cube_mesh import create_elements_cube mesh = Fem.FemMesh() ret = create_nodes_cube(mesh) self.assertTrue( ret, "Import of mesh nodes failed" ) ret = create_elements_cube(mesh) self.assertTrue( ret, "Import of mesh volumes failed" ) mesh_object = self.active_doc.addObject( 'Fem::FemMeshObject', self.mesh_name ) mesh_object.FemMesh = mesh self.assertTrue( mesh, "FemTest of new mesh failed" ) analysis.addObject(mesh_object) self.active_doc.recompute() static_analysis_dir = testtools.get_unit_test_tmp_dir( self.temp_dir, 'FEM_ccx_static' ) fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True) fea.update_objects() fcc_print('Setting up working directory {}'.format(static_analysis_dir)) fea.setup_working_dir(static_analysis_dir) self.assertTrue( True if fea.working_dir == static_analysis_dir else False, "Setting working directory {} failed".format(static_analysis_dir) ) fcc_print('Checking FEM inp file prerequisites for static analysis...') error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format(error) ) static_base_name = 'cube_static' inpfile_given = join(self.test_file_dir, (static_base_name + '.inp')) inpfile_totest = join(static_analysis_dir, (self.mesh_name + '.inp')) fcc_print('Checking FEM inp file write...') fcc_print('Writing {} for static analysis'.format(inpfile_totest)) error = fea.write_inp_file() self.assertFalse( error, "Writing failed" ) fcc_print('Comparing {} to {}'.format(inpfile_given, inpfile_totest)) ret = testtools.compare_inp_files(inpfile_given, inpfile_totest) self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret) ) fcc_print( 'Setting up working directory to {} in order to read simulated calculations' .format(self.test_file_dir) ) fea.setup_working_dir(self.test_file_dir) fcc_print(fea.working_dir) fcc_print(self.test_file_dir) self.assertTrue( True if fea.working_dir == self.test_file_dir else False, "Setting working directory {} failed".format(self.test_file_dir) ) fcc_print('Setting base name to read test {}.frd file...'.format('cube_static')) fea.set_base_name(static_base_name) self.assertTrue( True if fea.base_name == static_base_name else False, "Setting base name to {} failed".format(static_base_name) ) fcc_print('Setting inp file name to read test {}.frd file...'.format('cube_static')) fea.set_inp_file_name() self.assertTrue( True if fea.inp_file_name == inpfile_given else False, "Setting inp file name to {} failed".format(inpfile_given) ) fcc_print('Checking FEM frd file read from static analysis...') fea.load_results() self.assertTrue( fea.results_present, "Cannot read results from {}.frd frd file".format(fea.base_name) ) fcc_print('Reading stats from result object for static analysis...') static_expected_values = join(self.test_file_dir, "cube_static_expected_values") ret = testtools.compare_stats( fea, static_expected_values, 'CalculiX_static_results' ) self.assertFalse( ret, "Invalid results read from .frd file" ) static_save_fc_file = static_analysis_dir + static_base_name + '.FCStd' fcc_print('Save FreeCAD file for static analysis to {}...'.format(static_save_fc_file)) self.active_doc.saveAs(static_save_fc_file) fcc_print('--------------- End of FEM tests static and analysis ---------------') # ******************************************************************************************** def test_2_static_multiple_material( self ): fcc_print('--------------- Start of FEM ccxtools multiple material test ---------------') # create a CompSolid of two Boxes extract the CompSolid # we are able to remesh if needed boxlow = self.active_doc.addObject("Part::Box", "BoxLower") boxupp = self.active_doc.addObject("Part::Box", "BoxUpper") boxupp.Placement.Base = (0, 0, 10) # for BooleanFragments Occt >=6.9 is needed ''' import BOPTools.SplitFeatures bf = BOPTools.SplitFeatures.makeBooleanFragments(name='BooleanFragments') bf.Objects = [boxlow, boxupp] bf.Mode = "CompSolid" self.active_doc.recompute() bf.Proxy.execute(bf) bf.purgeTouched() for obj in bf.ViewObject.Proxy.claimChildren(): obj.ViewObject.hide() self.active_doc.recompute() import CompoundTools.CompoundFilter cf = CompoundTools.CompoundFilter.makeCompoundFilter(name='MultiMatCompSolid') cf.Base = bf cf.FilterType = 'window-volume' cf.Proxy.execute(cf) cf.purgeTouched() cf.Base.ViewObject.hide() ''' self.active_doc.recompute() if FreeCAD.GuiUp: import FreeCADGui FreeCADGui.ActiveDocument.activeView().viewAxonometric() FreeCADGui.SendMsgToActiveView("ViewFit") analysis = ObjectsFem.makeAnalysis( self.active_doc, 'Analysis' ) solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiXccxTools' ) solver_object.AnalysisType = 'static' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = 'default' solver_object.IterationsControlParameterTimeUse = False analysis.addObject(solver_object) material_object_low = ObjectsFem.makeMaterialSolid( self.active_doc, 'MechanicalMaterialLow' ) mat = material_object_low.Material mat['Name'] = "Aluminium-Generic" mat['YoungsModulus'] = "70000 MPa" mat['PoissonRatio'] = "0.35" mat['Density'] = "2700 kg/m^3" material_object_low.Material = mat material_object_low.References = [(boxlow, 'Solid1')] analysis.addObject(material_object_low) material_object_upp = ObjectsFem.makeMaterialSolid( self.active_doc, 'MechanicalMaterialUpp' ) mat = material_object_upp.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7980 kg/m^3" material_object_upp.Material = mat material_object_upp.References = [(boxupp, 'Solid1')] analysis.addObject(material_object_upp) fixed_constraint = self.active_doc.addObject( "Fem::ConstraintFixed", "ConstraintFixed" ) # fixed_constraint.References = [(cf, "Face3")] fixed_constraint.References = [(boxlow, "Face5")] analysis.addObject(fixed_constraint) pressure_constraint = self.active_doc.addObject( "Fem::ConstraintPressure", "ConstraintPressure" ) # pressure_constraint.References = [(cf, "Face9")] pressure_constraint.References = [(boxupp, "Face6")] pressure_constraint.Pressure = 1000.0 pressure_constraint.Reversed = False analysis.addObject(pressure_constraint) mesh = Fem.FemMesh() import femtest.testfiles.ccx.multimat_mesh as multimatmesh multimatmesh.create_nodes(mesh) multimatmesh.create_elements(mesh) mesh_object = self.active_doc.addObject('Fem::FemMeshObject', self.mesh_name) mesh_object.FemMesh = mesh analysis.addObject(mesh_object) self.active_doc.recompute() static_multiplemat_dir = testtools.get_unit_test_tmp_dir( self.temp_dir, 'FEM_ccx_multimat/' ) fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True) fea.update_objects() fea.setup_working_dir(static_multiplemat_dir) fcc_print('Checking FEM inp file prerequisites for ccxtools multimat analysis...') error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format(error) ) static_base_name = 'multimat' inpfile_given = join(self.test_file_dir, (static_base_name + '.inp')) inpfile_totest = join(static_multiplemat_dir, (self.mesh_name + '.inp')) fcc_print('Checking FEM inp file write...') fcc_print('Writing {} for static multiple material'.format(inpfile_totest)) error = fea.write_inp_file() self.assertFalse( error, "Writing failed" ) fcc_print('Comparing {} to {}'.format(inpfile_given, inpfile_totest)) ret = testtools.compare_inp_files(inpfile_given, inpfile_totest) self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret) ) static_save_fc_file = static_multiplemat_dir + static_base_name + '.FCStd' fcc_print('Save FreeCAD file for static analysis to {}...'.format(static_save_fc_file)) self.active_doc.saveAs(static_save_fc_file) fcc_print('--------------- End of FEM ccxtools multiple material test ---------------') # ******************************************************************************************** def test_3_freq_analysis( self ): fcc_print('--------------- Start of FEM tests ---------------') self.active_doc.addObject("Part::Box", "Box") fcc_print('Checking FEM new analysis...') analysis = ObjectsFem.makeAnalysis( self.active_doc, 'Analysis' ) self.assertTrue( analysis, "FemTest of new analysis failed" ) fcc_print('Checking FEM new solver...') solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiX' ) solver_object.AnalysisType = 'frequency' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = 'default' solver_object.IterationsControlParameterTimeUse = False solver_object.EigenmodesCount = 10 solver_object.EigenmodeHighLimit = 1000000.0 solver_object.EigenmodeLowLimit = 0.01 self.assertTrue( solver_object, "FemTest of new solver failed" ) analysis.addObject(solver_object) fcc_print('Checking FEM new material...') material_object = ObjectsFem.makeMaterialSolid( self.active_doc, 'MechanicalMaterial' ) mat = material_object.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" material_object.Material = mat self.assertTrue( material_object, "FemTest of new material failed" ) analysis.addObject(material_object) fcc_print('Checking FEM new mesh...') from .testfiles.ccx.cube_mesh import create_nodes_cube from .testfiles.ccx.cube_mesh import create_elements_cube mesh = Fem.FemMesh() ret = create_nodes_cube(mesh) self.assertTrue(ret, "Import of mesh nodes failed") ret = create_elements_cube(mesh) self.assertTrue(ret, "Import of mesh volumes failed") mesh_object = self.active_doc.addObject( 'Fem::FemMeshObject', self.mesh_name ) mesh_object.FemMesh = mesh self.assertTrue(mesh, "FemTest of new mesh failed") analysis.addObject(mesh_object) self.active_doc.recompute() frequency_analysis_dir = testtools.get_unit_test_tmp_dir( self.temp_dir, 'FEM_ccx_frequency' ) fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True) fea.update_objects() fcc_print('Setting up working directory {}'.format(frequency_analysis_dir)) fea.setup_working_dir(frequency_analysis_dir) self.assertTrue( True if fea.working_dir == frequency_analysis_dir else False, "Setting working directory {} failed".format(frequency_analysis_dir) ) fcc_print('Checking FEM inp file prerequisites for frequency analysis...') error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format(error) ) frequency_base_name = 'cube_frequency' inpfile_given = join(self.test_file_dir, (frequency_base_name + '.inp')) inpfile_totest = join(frequency_analysis_dir, (self.mesh_name + '.inp')) fcc_print('Checking FEM inp file write...') fcc_print('Writing {} for frequency analysis'.format(inpfile_totest)) error = fea.write_inp_file() self.assertFalse( error, "Writing failed" ) fcc_print('Comparing {} to {}'.format(inpfile_given, inpfile_totest)) ret = testtools.compare_inp_files(inpfile_given, inpfile_totest) self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret) ) fcc_print( 'Setting up working directory to {} in order to read simulated calculations'. format(self.test_file_dir) ) fea.setup_working_dir(self.test_file_dir) self.assertTrue( True if fea.working_dir == self.test_file_dir else False, "Setting working directory {} failed".format(self.test_file_dir) ) fcc_print('Setting base name to read test {}.frd file...'.format(frequency_base_name)) fea.set_base_name(frequency_base_name) self.assertTrue( True if fea.base_name == frequency_base_name else False, "Setting base name to {} failed".format(frequency_base_name) ) fcc_print('Setting inp file name to read test {}.frd file...'.format('cube_frequency')) fea.set_inp_file_name() self.assertTrue( True if fea.inp_file_name == inpfile_given else False, "Setting inp file name to {} failed".format(inpfile_given) ) fcc_print('Checking FEM frd file read from frequency analysis...') fea.load_results() self.assertTrue( fea.results_present, "Cannot read results from {}.frd frd file".format(fea.base_name) ) fcc_print('Reading stats from result object for frequency analysis...') frequency_expected_values = join(self.test_file_dir, "cube_frequency_expected_values") ret = testtools.compare_stats( fea, frequency_expected_values, 'CalculiX_frequency_mode_1_results' ) self.assertFalse( ret, "Invalid results read from .frd file" ) frequency_save_fc_file = frequency_analysis_dir + frequency_base_name + '.FCStd' fcc_print( 'Save FreeCAD file for frequency analysis to {}...' .format(frequency_save_fc_file) ) self.active_doc.saveAs(frequency_save_fc_file) fcc_print('--------------- End of FEM tests frequency analysis ---------------') # ******************************************************************************************** def test_4_thermomech_analysis( self ): fcc_print('--------------- Start of FEM tests ---------------') box = self.active_doc.addObject("Part::Box", "Box") box.Height = 25.4 box.Width = 25.4 box.Length = 203.2 fcc_print('Checking FEM new analysis...') analysis = ObjectsFem.makeAnalysis( self.active_doc, 'Analysis' ) self.assertTrue( analysis, "FemTest of new analysis failed" ) fcc_print('Checking FEM new solver...') solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiX' ) solver_object.AnalysisType = 'thermomech' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = True solver_object.MatrixSolverType = 'default' solver_object.IterationsThermoMechMaximum = 2000 solver_object.IterationsControlParameterTimeUse = True self.assertTrue( solver_object, "FemTest of new solver failed" ) analysis.addObject(solver_object) fcc_print('Checking FEM new material...') material_object = ObjectsFem.makeMaterialSolid( self.active_doc, 'MechanicalMaterial' ) mat = material_object.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" mat['ThermalConductivity'] = "43.27 W/m/K" # SvdW: Change to Ansys model values mat['ThermalExpansionCoefficient'] = "12 um/m/K" mat['SpecificHeat'] = "500 J/kg/K" # SvdW: Change to Ansys model values material_object.Material = mat self.assertTrue( material_object, "FemTest of new material failed" ) analysis.addObject(material_object) fcc_print('Checking FEM new fixed constraint...') fixed_constraint = self.active_doc.addObject( "Fem::ConstraintFixed", "FemConstraintFixed" ) fixed_constraint.References = [(box, "Face1")] self.assertTrue( fixed_constraint, "FemTest of new fixed constraint failed" ) analysis.addObject(fixed_constraint) fcc_print('Checking FEM new initial temperature constraint...') initialtemperature_constraint = self.active_doc.addObject( "Fem::ConstraintInitialTemperature", "FemConstraintInitialTemperature" ) initialtemperature_constraint.initialTemperature = 300.0 self.assertTrue( initialtemperature_constraint, "FemTest of new initial temperature constraint failed" ) analysis.addObject(initialtemperature_constraint) fcc_print('Checking FEM new temperature constraint...') temperature_constraint = self.active_doc.addObject( "Fem::ConstraintTemperature", "FemConstraintTemperature" ) temperature_constraint.References = [(box, "Face1")] temperature_constraint.Temperature = 310.93 self.assertTrue( temperature_constraint, "FemTest of new temperature constraint failed" ) analysis.addObject(temperature_constraint) fcc_print('Checking FEM new heatflux constraint...') heatflux_constraint = self.active_doc.addObject( "Fem::ConstraintHeatflux", "FemConstraintHeatflux" ) heatflux_constraint.References = [ (box, "Face3"), (box, "Face4"), (box, "Face5"), (box, "Face6") ] heatflux_constraint.AmbientTemp = 255.3722 heatflux_constraint.FilmCoef = 5.678 self.assertTrue( heatflux_constraint, "FemTest of new heatflux constraint failed" ) analysis.addObject(heatflux_constraint) fcc_print('Checking FEM new mesh...') from .testfiles.ccx.spine_mesh import create_nodes_spine from .testfiles.ccx.spine_mesh import create_elements_spine mesh = Fem.FemMesh() ret = create_nodes_spine(mesh) self.assertTrue( ret, "Import of mesh nodes failed" ) ret = create_elements_spine(mesh) self.assertTrue( ret, "Import of mesh volumes failed" ) mesh_object = self.active_doc.addObject( 'Fem::FemMeshObject', self.mesh_name ) mesh_object.FemMesh = mesh self.assertTrue( mesh, "FemTest of new mesh failed" ) analysis.addObject(mesh_object) self.active_doc.recompute() thermomech_analysis_dir = testtools.get_unit_test_tmp_dir( self.temp_dir, 'FEM_ccx_thermomech' ) fea = ccxtools.FemToolsCcx(analysis, test_mode=True) fea.update_objects() fcc_print('Setting up working directory {}'.format(thermomech_analysis_dir)) fea.setup_working_dir(thermomech_analysis_dir) self.assertTrue( True if fea.working_dir == thermomech_analysis_dir else False, "Setting working directory {} failed".format(thermomech_analysis_dir) ) fcc_print('Checking FEM inp file prerequisites for thermo-mechanical analysis...') error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format(error) ) thermomech_base_name = 'spine_thermomech' inpfile_given = join(self.test_file_dir, (thermomech_base_name + '.inp')) inpfile_totest = join(thermomech_analysis_dir, (self.mesh_name + '.inp')) fcc_print('Checking FEM inp file write...') fcc_print('Writing {} for thermomech analysis'.format(inpfile_totest)) error = fea.write_inp_file() self.assertFalse( error, "Writing failed" ) fcc_print('Comparing {} to {}'.format(inpfile_given, inpfile_totest)) ret = testtools.compare_inp_files(inpfile_given, inpfile_totest) self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret) ) fcc_print( 'Setting up working directory to {} in order to read simulated calculations' .format(self.test_file_dir) ) fea.setup_working_dir(self.test_file_dir) self.assertTrue( True if fea.working_dir == self.test_file_dir else False, "Setting working directory {} failed".format(self.test_file_dir) ) fcc_print('Setting base name to read test {}.frd file...'.format('spine_thermomech')) fea.set_base_name(thermomech_base_name) self.assertTrue( True if fea.base_name == thermomech_base_name else False, "Setting base name to {} failed".format(thermomech_base_name) ) fcc_print('Setting inp file name to read test {}.frd file...'.format('spine_thermomech')) fea.set_inp_file_name() self.assertTrue( True if fea.inp_file_name == inpfile_given else False, "Setting inp file name to {} failed".format(inpfile_given) ) fcc_print('Checking FEM frd file read from thermomech analysis...') fea.load_results() self.assertTrue( fea.results_present, "Cannot read results from {}.frd frd file".format(fea.base_name) ) fcc_print('Reading stats from result object for thermomech analysis...') thermomech_expected_values = join( self.test_file_dir, "spine_thermomech_expected_values" ) ret = testtools.compare_stats( fea, thermomech_expected_values, 'CalculiX_thermomech_results' ) self.assertFalse( ret, "Invalid results read from .frd file" ) thermomech_save_fc_file = thermomech_analysis_dir + thermomech_base_name + '.FCStd' fcc_print( 'Save FreeCAD file for thermomech analysis to {}...' .format(thermomech_save_fc_file) ) self.active_doc.saveAs(thermomech_save_fc_file) fcc_print('--------------- End of FEM tests thermomech analysis ---------------') # ******************************************************************************************** def test_5_Flow1D_thermomech_analysis( self ): fcc_print('--------------- Start of 1D Flow FEM tests ---------------') p1 = FreeCAD.Vector(0, 0, 50) p2 = FreeCAD.Vector(0, 0, -50) p3 = FreeCAD.Vector(0, 0, -4300) p4 = FreeCAD.Vector(4950, 0, -4300) p5 = FreeCAD.Vector(5000, 0, -4300) p6 = FreeCAD.Vector(8535.53, 0, -7835.53) p7 = FreeCAD.Vector(8569.88, 0, -7870.88) p8 = FreeCAD.Vector(12105.41, 0, -11406.41) p9 = FreeCAD.Vector(12140.76, 0, -11441.76) p10 = FreeCAD.Vector(13908.53, 0, -13209.53) p11 = FreeCAD.Vector(13943.88, 0, -13244.88) p12 = FreeCAD.Vector(15046.97, 0, -14347.97) p13 = FreeCAD.Vector(15046.97, 0, -7947.97) p14 = FreeCAD.Vector(15046.97, 0, -7847.97) p15 = FreeCAD.Vector(0, 0, 0) p16 = FreeCAD.Vector(0, 0, -2175) p17 = FreeCAD.Vector(2475, 0, -4300) p18 = FreeCAD.Vector(4975, 0, -4300) p19 = FreeCAD.Vector(6767.765, 0, -6067.765) p20 = FreeCAD.Vector(8552.705, 0, -7853.205) p21 = FreeCAD.Vector(10337.645, 0, -9638.645) p22 = FreeCAD.Vector(12123.085, 0, -11424.085) p23 = FreeCAD.Vector(13024.645, 0, -12325.645) p24 = FreeCAD.Vector(13926.205, 0, -13227.205) p25 = FreeCAD.Vector(14495.425, 0, -13796.425) p26 = FreeCAD.Vector(15046.97, 0, -11147.97) p27 = FreeCAD.Vector(15046.97, 0, -7897.97) points = [ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27 ] from Draft import makeWire line = makeWire( points, closed=False, face=False, support=None ) fcc_print('Checking FEM new analysis...') analysis = ObjectsFem.makeAnalysis( self.active_doc, 'Analysis' ) self.assertTrue(analysis, "FemTest of new analysis failed") fcc_print('Checking FEM new solver...') solver_object = ObjectsFem.makeSolverCalculixCcxTools( self.active_doc, 'CalculiX' ) solver_object.AnalysisType = 'thermomech' solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = True solver_object.MatrixSolverType = 'default' solver_object.IterationsThermoMechMaximum = 2000 solver_object.IterationsControlParameterTimeUse = False self.assertTrue( solver_object, "FemTest of new solver failed" ) analysis.addObject(solver_object) fcc_print('Checking FEM new material...') material_object = ObjectsFem.makeMaterialFluid( self.active_doc, 'FluidMaterial' ) mat = material_object.Material mat['Name'] = "Water" mat['Density'] = "998 kg/m^3" mat['SpecificHeat'] = "4.182 J/kg/K" mat['DynamicViscosity'] = "1.003e-3 kg/m/s" mat['VolumetricThermalExpansionCoefficient'] = "2.07e-4 m/m/K" mat['ThermalConductivity'] = "0.591 W/m/K" material_object.Material = mat self.assertTrue( material_object, "FemTest of new material failed" ) analysis.addObject(material_object) fcc_print('Checking FEM Flow1D inlet constraint...') Flow1d_inlet = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_inlet.SectionType = 'Liquid' Flow1d_inlet.LiquidSectionType = 'PIPE INLET' Flow1d_inlet.InletPressure = 0.1 Flow1d_inlet.References = [(line, "Edge1")] self.assertTrue( Flow1d_inlet, "FemTest of new Flow1D inlet constraint failed" ) analysis.addObject(Flow1d_inlet) fcc_print('Checking FEM new Flow1D entrance constraint...') Flow1d_entrance = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_entrance.SectionType = 'Liquid' Flow1d_entrance.LiquidSectionType = 'PIPE ENTRANCE' Flow1d_entrance.EntrancePipeArea = 31416.00 Flow1d_entrance.EntranceArea = 25133.00 Flow1d_entrance.References = [(line, "Edge2")] self.assertTrue( Flow1d_entrance, "FemTest of new Flow1D entrance constraint failed" ) analysis.addObject(Flow1d_entrance) fcc_print('Checking FEM new Flow1D manning constraint...') Flow1d_manning = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_manning.SectionType = 'Liquid' Flow1d_manning.LiquidSectionType = 'PIPE MANNING' Flow1d_manning.ManningArea = 31416 Flow1d_manning.ManningRadius = 50 Flow1d_manning.ManningCoefficient = 0.002 Flow1d_manning.References = [(line, "Edge3"), (line, "Edge5")] self.assertTrue( Flow1d_manning, "FemTest of new Flow1D manning constraint failed" ) analysis.addObject(Flow1d_manning) fcc_print('Checking FEM new Flow1D bend constraint...') Flow1d_bend = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_bend.SectionType = 'Liquid' Flow1d_bend.LiquidSectionType = 'PIPE BEND' Flow1d_bend.BendPipeArea = 31416 Flow1d_bend.BendRadiusDiameter = 1.5 Flow1d_bend.BendAngle = 45 Flow1d_bend.BendLossCoefficient = 0.4 Flow1d_bend.References = [(line, "Edge4")] self.assertTrue( Flow1d_bend, "FemTest of new Flow1D bend constraint failed" ) analysis.addObject(Flow1d_bend) fcc_print('Checking FEM new Flow1D enlargement constraint...') Flow1d_enlargement = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_enlargement.SectionType = 'Liquid' Flow1d_enlargement.LiquidSectionType = 'PIPE ENLARGEMENT' Flow1d_enlargement.EnlargeArea1 = 31416.00 Flow1d_enlargement.EnlargeArea2 = 70686.00 Flow1d_enlargement.References = [(line, "Edge6")] self.assertTrue( Flow1d_enlargement, "FemTest of new Flow1D enlargement constraint failed" ) analysis.addObject(Flow1d_enlargement) fcc_print('Checking FEM new Flow1D manning constraint...') Flow1d_manning1 = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_manning1.SectionType = 'Liquid' Flow1d_manning1.LiquidSectionType = 'PIPE MANNING' Flow1d_manning1.ManningArea = 70686.00 Flow1d_manning1.ManningRadius = 75 Flow1d_manning1.ManningCoefficient = 0.002 Flow1d_manning1.References = [(line, "Edge7")] self.assertTrue( Flow1d_manning1, "FemTest of new Flow1D manning constraint failed" ) analysis.addObject(Flow1d_manning1) fcc_print('Checking FEM new Flow1D contraction constraint...') Flow1d_contraction = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_contraction.SectionType = 'Liquid' Flow1d_contraction.LiquidSectionType = 'PIPE CONTRACTION' Flow1d_contraction.ContractArea1 = 70686 Flow1d_contraction.ContractArea2 = 17671 Flow1d_contraction.References = [(line, "Edge8")] self.assertTrue( Flow1d_contraction, "FemTest of new Flow1D contraction constraint failed" ) analysis.addObject(Flow1d_contraction) fcc_print('Checking FEM new Flow1D manning constraint...') Flow1d_manning2 = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_manning2.SectionType = 'Liquid' Flow1d_manning2.LiquidSectionType = 'PIPE MANNING' Flow1d_manning2.ManningArea = 17671.00 Flow1d_manning2.ManningRadius = 37.5 Flow1d_manning2.ManningCoefficient = 0.002 Flow1d_manning2.References = [(line, "Edge11"), (line, "Edge9")] self.assertTrue( Flow1d_manning2, "FemTest of new Flow1D manning constraint failed" ) analysis.addObject(Flow1d_manning2) fcc_print('Checking FEM new Flow1D gate valve constraint...') Flow1d_gate_valve = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_gate_valve.SectionType = 'Liquid' Flow1d_gate_valve.LiquidSectionType = 'PIPE GATE VALVE' Flow1d_gate_valve.GateValvePipeArea = 17671 Flow1d_gate_valve.GateValveClosingCoeff = 0.5 Flow1d_gate_valve.References = [(line, "Edge10")] self.assertTrue( Flow1d_gate_valve, "FemTest of new Flow1D gate valve constraint failed" ) analysis.addObject(Flow1d_gate_valve) fcc_print('Checking FEM new Flow1D enlargement constraint...') Flow1d_enlargement1 = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_enlargement1.SectionType = 'Liquid' Flow1d_enlargement1.LiquidSectionType = 'PIPE ENLARGEMENT' Flow1d_enlargement1.EnlargeArea1 = 17671 Flow1d_enlargement1.EnlargeArea2 = 1e12 Flow1d_enlargement1.References = [(line, "Edge12")] self.assertTrue( Flow1d_enlargement1, "FemTest of new Flow1D enlargement constraint failed" ) analysis.addObject(Flow1d_enlargement1) fcc_print('Checking FEM Flow1D outlet constraint...') Flow1d_outlet = ObjectsFem.makeElementFluid1D( self.active_doc, "ElementFluid1D" ) Flow1d_outlet.SectionType = 'Liquid' Flow1d_outlet.LiquidSectionType = 'PIPE OUTLET' Flow1d_outlet.OutletPressure = 0.1 Flow1d_outlet.References = [(line, "Edge13")] self.assertTrue( Flow1d_outlet, "FemTest of new Flow1D inlet constraint failed" ) analysis.addObject(Flow1d_outlet) fcc_print('Checking FEM self weight constraint...') Flow1d_self_weight = ObjectsFem.makeConstraintSelfWeight( self.active_doc, "ConstraintSelfWeight" ) Flow1d_self_weight.Gravity_x = 0.0 Flow1d_self_weight.Gravity_y = 0.0 Flow1d_self_weight.Gravity_z = -1.0 self.assertTrue( Flow1d_outlet, "FemTest of new Flow1D self weight constraint failed" ) analysis.addObject(Flow1d_self_weight) fcc_print('Checking FEM new mesh...') from .testfiles.ccx.Flow1D_mesh import create_nodes_Flow1D from .testfiles.ccx.Flow1D_mesh import create_elements_Flow1D mesh = Fem.FemMesh() ret = create_nodes_Flow1D(mesh) self.assertTrue(ret, "Import of mesh nodes failed") ret = create_elements_Flow1D(mesh) self.assertTrue(ret, "Import of mesh volumes failed") mesh_object = self.active_doc.addObject( 'Fem::FemMeshObject', self.mesh_name ) mesh_object.FemMesh = mesh self.assertTrue(mesh, "FemTest of new mesh failed") analysis.addObject(mesh_object) self.active_doc.recompute() Flow1D_thermomech_analysis_dir = testtools.get_unit_test_tmp_dir( self.temp_dir, 'FEM_ccx_Flow1D_thermomech' ) fea = ccxtools.FemToolsCcx(analysis, test_mode=True) fea.update_objects() fcc_print('Setting up working directory {}'.format(Flow1D_thermomech_analysis_dir)) fea.setup_working_dir(Flow1D_thermomech_analysis_dir) self.assertTrue( True if fea.working_dir == Flow1D_thermomech_analysis_dir else False, "Setting working directory {} failed".format(Flow1D_thermomech_analysis_dir) ) fcc_print('Checking FEM inp file prerequisites for thermo-mechanical analysis...') error = fea.check_prerequisites() self.assertFalse( error, "ccxtools check_prerequisites returned error message: {}".format(error) ) Flow1D_thermomech_base_name = 'Flow1D_thermomech' inpfile_given = join(self.test_file_dir, (Flow1D_thermomech_base_name + '.inp')) inpfile_totest = join(Flow1D_thermomech_analysis_dir, (self.mesh_name + '.inp')) fcc_print('Checking FEM inp file write...') fcc_print('Writing {} for thermomech analysis'.format(inpfile_totest)) error = fea.write_inp_file() self.assertFalse( error, "Writing failed" ) fcc_print('Comparing {} to {}'.format(inpfile_given, inpfile_totest)) ret = testtools.compare_inp_files(inpfile_given, inpfile_totest) self.assertFalse( ret, "ccxtools write_inp_file test failed.\n{}".format(ret) ) fcc_print( 'Setting up working directory to {} in order to read simulated calculations' .format(self.test_file_dir) ) fea.setup_working_dir(self.test_file_dir) self.assertTrue( True if fea.working_dir == self.test_file_dir else False, "Setting working directory {} failed".format(self.test_file_dir) ) fcc_print('Setting base name to read test {}.frd file...'.format('Flow1D_thermomech')) fea.set_base_name(Flow1D_thermomech_base_name) self.assertTrue( True if fea.base_name == Flow1D_thermomech_base_name else False, "Setting base name to {} failed".format(Flow1D_thermomech_base_name) ) fcc_print('Setting inp file name to read test {}.frd file...'.format('Flow1D_thermomech')) fea.set_inp_file_name() self.assertTrue( True if fea.inp_file_name == inpfile_given else False, "Setting inp file name to {} failed".format(inpfile_given) ) fcc_print('Checking FEM frd file read from Flow1D thermomech analysis...') fea.load_results() self.assertTrue( fea.results_present, "Cannot read results from {}.frd frd file".format(fea.base_name) ) fcc_print('Reading stats from result object for Flow1D thermomech analysis...') Flow1D_thermomech_expected_values = join( self.test_file_dir, "Flow1D_thermomech_expected_values" ) stat_types = [ "U1", "U2", "U3", "Uabs", "Sabs", "MaxPrin", "MidPrin", "MinPrin", "MaxShear", "Peeq", "Temp", "MFlow", "NPress" ] ret = testtools.compare_stats( fea, Flow1D_thermomech_expected_values, stat_types, 'CalculiX_thermomech_time_1_0_results') self.assertFalse( ret, "Invalid results read from .frd file" ) Flow1D_thermomech_save_fc_file = join( Flow1D_thermomech_analysis_dir, (Flow1D_thermomech_base_name + '.FCStd') ) fcc_print( 'Save FreeCAD file for thermomech analysis to {}...' .format(Flow1D_thermomech_save_fc_file) ) self.active_doc.saveAs(Flow1D_thermomech_save_fc_file) fcc_print('--------------- End of FEM tests FLow 1D thermomech analysis ---------------') # ******************************************************************************************** def tearDown( self ): # clearance, is executed after every test FreeCAD.closeDocument(self.doc_name) pass # ************************************************************************************************ def create_test_results(): import shutil import os import FemGui import femresult.resulttools as resulttools from femtools import ccxtools stat_types = [ "U1", "U2", "U3", "Uabs", "Sabs", "MaxPrin", "MidPrin", "MinPrin", "MaxShear", "Peeq", "Temp", "MFlow", "NPress" ] temp_dir = testtools.get_fem_test_tmp_dir() static_analysis_dir = temp_dir + 'FEM_ccx_static/' frequency_analysis_dir = temp_dir + 'FEM_ccx_frequency/' thermomech_analysis_dir = temp_dir + 'FEM_ccx_thermomech/' Flow1D_thermomech_analysis_dir = temp_dir + 'FEM_ccx_Flow1D_thermomech/' # run all unit tests from this module import Test import sys current_module = sys.modules[__name__] Test.runTestsFromModule(current_module) # static cube FreeCAD.open(static_analysis_dir + 'cube_static.FCStd') FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) fea = ccxtools.FemToolsCcx() fea.update_objects() print("create static result files") fea.reset_all() fea.run() fea.load_results() stats_static = [] for s in stat_types: statval = resulttools.get_stats( FreeCAD.ActiveDocument.getObject('CalculiX_static_results'), s ) stats_static.append( "{0}: ({1:.14g}, {2:.14g}, {3:.14g})\n" .format(s, statval[0], statval[1], statval[2]) ) static_expected_values_file = join( static_analysis_dir, 'cube_static_expected_values' ) f = open(static_expected_values_file, 'w') for s in stats_static: f.write(s) f.close() frd_result_file = os.path.splitext(fea.inp_file_name)[0] + '.frd' dat_result_file = os.path.splitext(fea.inp_file_name)[0] + '.dat' frd_static_test_result_file = static_analysis_dir + 'cube_static.frd' dat_static_test_result_file = static_analysis_dir + 'cube_static.dat' shutil.copyfile(frd_result_file, frd_static_test_result_file) shutil.copyfile(dat_result_file, dat_static_test_result_file) # frequency cube FreeCAD.open(frequency_analysis_dir + 'cube_frequency.FCStd') FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) fea = ccxtools.FemToolsCcx() fea.update_objects() print("create frequency result files") fea.reset_all() fea.solver.EigenmodesCount = 1 # we should only have one result object fea.run() fea.load_results() stats_frequency = [] for s in stat_types: statval = resulttools.get_stats( FreeCAD.ActiveDocument.getObject('CalculiX_frequency_mode_1_results'), s ) stats_frequency.append( "{0}: ({1:.14g}, {2:.14g}, {3:.14g})\n" .format(s, statval[0], statval[1], statval[2]) ) frequency_expected_values_file = join( frequency_analysis_dir, 'cube_frequency_expected_values' ) f = open(frequency_expected_values_file, 'w') for s in stats_frequency: f.write(s) f.close() frd_frequency_test_result_file = frequency_analysis_dir + 'cube_frequency.frd' dat_frequency_test_result_file = frequency_analysis_dir + 'cube_frequency.dat' shutil.copyfile(frd_result_file, frd_frequency_test_result_file) shutil.copyfile(dat_result_file, dat_frequency_test_result_file) # thermomech print("create thermomech result files") FreeCAD.open(thermomech_analysis_dir + 'spine_thermomech.FCStd') FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) fea = ccxtools.FemToolsCcx() fea.reset_all() fea.run() fea.load_results() stats_thermomech = [] for s in stat_types: statval = resulttools.get_stats( FreeCAD.ActiveDocument.getObject('CalculiX_thermomech_results'), s ) stats_thermomech.append( "{0}: ({1:.14g}, {2:.14g}, {3:.14g})\n" .format(s, statval[0], statval[1], statval[2]) ) thermomech_expected_values_file = join( thermomech_analysis_dir, 'spine_thermomech_expected_values' ) f = open(thermomech_expected_values_file, 'w') for s in stats_thermomech: f.write(s) f.close() frd_result_file = os.path.splitext(fea.inp_file_name)[0] + '.frd' dat_result_file = os.path.splitext(fea.inp_file_name)[0] + '.dat' frd_thermomech_test_result_file = thermomech_analysis_dir + 'spine_thermomech.frd' dat_thermomech_test_result_file = thermomech_analysis_dir + 'spine_thermomech.dat' shutil.copyfile(frd_result_file, frd_thermomech_test_result_file) shutil.copyfile(dat_result_file, dat_thermomech_test_result_file) print('Results copied to the appropriate FEM test dirs in: ' + temp_dir) # Flow1D print("create Flow1D result files") FreeCAD.open(Flow1D_thermomech_analysis_dir + 'Flow1D_thermomech.FCStd') FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) fea = ccxtools.FemToolsCcx() fea.reset_all() fea.run() fea.load_results() stats_flow1D = [] for s in stat_types: statval = resulttools.get_stats( FreeCAD.ActiveDocument.getObject('CalculiX_thermomech_time_1_0_results'), s ) stats_flow1D.append( "{0}: ({1:.14g}, {2:.14g}, {3:.14g})\n" .format(s, statval[0], statval[1], statval[2]) ) Flow1D_thermomech_expected_values_file = join( Flow1D_thermomech_analysis_dir, 'Flow1D_thermomech_expected_values' ) f = open(Flow1D_thermomech_expected_values_file, 'w') for s in stats_flow1D: f.write(s) f.close() frd_result_file = os.path.splitext(fea.inp_file_name)[0] + '.frd' dat_result_file = os.path.splitext(fea.inp_file_name)[0] + '.dat' frd_Flow1D_thermomech_test_result_file = join( Flow1D_thermomech_analysis_dir, 'Flow1D_thermomech.frd' ) dat_Flow1D_thermomech_test_result_file = join( Flow1D_thermomech_analysis_dir, 'Flow1D_thermomech.dat' ) shutil.copyfile(frd_result_file, frd_Flow1D_thermomech_test_result_file) shutil.copyfile(dat_result_file, dat_Flow1D_thermomech_test_result_file) print('Flow1D thermomech results copied to the appropriate FEM test dirs in: ' + temp_dir) ''' update the results of FEM ccxtools unit tests: from femtest.testccxtools import create_test_results create_test_results() copy result files from your_temp_directory/FEM_unittests/ test directories into the src directory compare the results with git difftool run make start FreeCAD and run FEM unit test if FEM unit test is fine --> commit new FEM unit test results TODO compare the inp file of the helper with the inp file of FEM unit tests TODO the better way: move the result creation inside the TestFem and add some preference to deactivate this because it needs ccx '''