From 4360c0b8b3182f6356bc45d55984af9863d0b971 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Fri, 13 Jan 2017 21:02:00 +0100 Subject: [PATCH] FEM: unit tests, fix some issues and save FreeCAD files of the unit tests --- src/Mod/Fem/TestFem.py | 112 ++++++++++++++---- src/Mod/Fem/test_files/ccx/cube_frequency.inp | 2 +- src/Mod/Fem/test_files/ccx/cube_static.inp | 2 +- .../ccx/spine_thermomech_expected_values | 14 +-- 4 files changed, 97 insertions(+), 33 deletions(-) diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index cfa75bffd661..4c497dbb70a7 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -52,6 +52,10 @@ frequency_expected_values = test_file_dir + "/cube_frequency_expected_values" thermomech_analysis_inp_file = test_file_dir + '/' + thermomech_base_name + '.inp' thermomech_expected_values = test_file_dir + "/spine_thermomech_expected_values" +static_save_fc_file = static_analysis_dir + '/' + static_base_name + '.fcstd' +frequency_save_fc_file = frequency_analysis_dir + '/' + frequency_base_name + '.fcstd' +thermomech_save_fc_file = thermomech_analysis_dir + '/' + thermomech_base_name + '.fcstd' + mesh_points_file = test_file_dir + '/mesh_points.csv' mesh_volumes_file = test_file_dir + '/mesh_volumes.csv' spine_points_file = test_file_dir + '/spine_points.csv' @@ -76,7 +80,7 @@ def setUp(self): self.active_doc.recompute() def create_new_analysis(self): - self.analysis = FemAnalysis.makeFemAnalysis('MechanicalAnalysis') + self.analysis = FemAnalysis.makeFemAnalysis('Analysis') self.active_doc.recompute() def create_new_solver(self): @@ -134,6 +138,9 @@ def create_pressure_constraint(self): self.pressure_constraint.Pressure = 1000.0 self.pressure_constraint.Reversed = False + def save_file(self, fc_file_name): + self.active_doc.saveAs(fc_file_name) + def force_unix_line_ends(self, line_list): new_line_list = [] for l in line_list: @@ -146,12 +153,12 @@ def compare_inp_files(self, file_name1, file_name2): file1 = open(file_name1, 'r') f1 = file1.readlines() file1.close() - lf1 = [l for l in f1 if not l.startswith('** written ')] + lf1 = [l for l in f1 if not (l.startswith('** written ') or l.startswith('** file '))] lf1 = self.force_unix_line_ends(lf1) file2 = open(file_name2, 'r') f2 = file2.readlines() file2.close() - lf2 = [l for l in f2 if not l.startswith('** written ')] + lf2 = [l for l in f2 if not (l.startswith('** written ') or l.startswith('** file '))] lf2 = self.force_unix_line_ends(lf2) import difflib diff = difflib.unified_diff(lf1, lf2, n=0) @@ -181,6 +188,7 @@ def compare_stats(self, fea, stat_file=None): return False def test_new_analysis(self): + # static fcc_print('--------------- Start of FEM tests ---------------') fcc_print('Checking FEM new analysis...') self.create_new_analysis() @@ -263,6 +271,11 @@ def test_new_analysis(self): ret = self.compare_stats(fea, static_expected_values) self.assertFalse(ret, "Invalid results read from .frd file") + fcc_print('Save FreeCAD file for static analysis to {}...'.format(static_save_fc_file)) + self.save_file(static_save_fc_file) + self.assertTrue(self.save_file, "FemTest saving of file {} failed ...".format(static_save_fc_file)) + + # frequency fcc_print('Setting analysis type to \'frequency\"') fea.set_analysis_type("frequency") self.assertTrue(True if fea.analysis_type == 'frequency' else False, "Setting anlysis type to \'frequency\' failed") @@ -307,7 +320,11 @@ def test_new_analysis(self): ret = self.compare_stats(fea, frequency_expected_values) self.assertFalse(ret, "Invalid results read from .frd file") - fcc_print('--------------- End of FEM tests ---------------') + fcc_print('Save FreeCAD file for frequency analysis to {}...'.format(frequency_save_fc_file)) + self.save_file(frequency_save_fc_file) + self.assertTrue(self.save_file, "FemTest saving of file {} failed ...".format(frequency_save_fc_file)) + + fcc_print('--------------- End of FEM tests static and frequency analysis ---------------') def tearDown(self): FreeCAD.closeDocument("FemTest") @@ -336,6 +353,7 @@ def create_new_analysis(self): def create_new_solver(self): self.solver_object = FemSolverCalculix.makeFemSolverCalculix('CalculiX') + self.solver_object.AnalysisType = 'thermomech' self.solver_object.GeometricalNonlinearity = 'linear' self.solver_object.ThermoMechSteadyState = True self.solver_object.MatrixSolverType = 'default' @@ -392,6 +410,9 @@ def create_heatflux_constraint(self): self.heatflux_constraint.AmbientTemp = 255.3722 self.heatflux_constraint.FilmCoef = 5.678 + def save_file(self, fc_file_name): + self.active_doc.saveAs(fc_file_name) + def force_unix_line_ends(self, line_list): new_line_list = [] for l in line_list: @@ -518,26 +539,46 @@ def test_new_analysis(self): self.assertTrue(True if fea.inp_file_name == thermomech_analysis_inp_file else False, "Setting inp file name to {} failed".format(thermomech_analysis_inp_file)) + 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...') + ret = self.compare_stats(fea, thermomech_expected_values) + self.assertFalse(ret, "Invalid results read from .frd file") + + fcc_print('Save FreeCAD file for thermomech analysis to {}...'.format(thermomech_save_fc_file)) + self.save_file(thermomech_save_fc_file) + self.assertTrue(self.save_file, "FemTest saving of file {} failed ...".format(thermomech_save_fc_file)) + + fcc_print('--------------- End of FEM tests thermomech analysis ---------------') + def tearDown(self): FreeCAD.closeDocument("TherMechFemTest") pass # helpers -def open_cube_test(): - cube_file = test_file_dir + '/cube.fcstd' - FreeCAD.open(cube_file) +def run_fem_unittests(): + import unittest + suite = unittest.TestSuite() + suite.addTest(unittest.defaultTestLoader.loadTestsFromName("TestFem")) + r = unittest.TextTestRunner() + r.run(suite) + +def create_test_results(): + # run FEM unit tests + run_fem_unittests() -def create_cube_test_results(): import os import shutil - cube_file = test_file_dir + '/cube.fcstd' - - FreeCAD.open(cube_file) import FemGui - FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.MechanicalAnalysis) import FemToolsCcx + + # static and frequency cube + FreeCAD.open(static_save_fc_file) + FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) fea = FemToolsCcx.FemToolsCcx() # static @@ -549,7 +590,7 @@ def create_cube_test_results(): stats_static = [] # we only have one result object so we are fine for s in stat_types: stats_static.append("{}: {}\n".format(s, fea.get_stats(s))) - static_expected_values_file = temp_dir + '/cube_static_expected_values' + static_expected_values_file = static_analysis_dir + '/cube_static_expected_values' f = open(static_expected_values_file, 'w') for s in stats_static: f.write(s) @@ -559,8 +600,8 @@ def create_cube_test_results(): 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 = temp_dir + '/cube_static.frd' - dat_static_test_result_file = temp_dir + '/cube_static.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) @@ -574,28 +615,55 @@ def create_cube_test_results(): stats_frequency = [] # since we set eigenmodeno. we only have one result object so we are fine for s in stat_types: stats_frequency.append("{}: {}\n".format(s, fea.get_stats(s))) - frequency_expected_values_file = temp_dir + '/cube_frequency_expected_values' + frequency_expected_values_file = 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 = temp_dir + '/cube_frequency.frd' - dat_frequency_test_result_file = temp_dir + '/cube_frequency.dat' + 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) - print('Results copied to: ' + temp_dir) + # thermomech + FreeCAD.open(thermomech_save_fc_file) + FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) + fea = FemToolsCcx.FemToolsCcx() + fea.reset_all() + fea.run() + + fea.load_results() + stat_types = ["U1", "U2", "U3", "Uabs", "Sabs"] + stats_thermomech = [] # we only have one result object so we are fine + for s in stat_types: + stats_thermomech.append("{}: {}\n".format(s, fea.get_stats(s))) + thermomech_expected_values_file = thermomech_analysis_dir + '/expected_values_thermomech' + f = open(thermomech_expected_values_file, 'w') + for s in stats_thermomech: + f.write(s) + f.close() + + # could be added in FemToolsCcx to the self object as an Attribut + 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) ''' update the results in FEM untit tests: -start FreeCAD import TestFem -TestFem.create_cube_test_results() +TestFem.create_test_results() -copy result files from /tmp into the src dirctory +copy result files from FEM test directories into the src dirctory +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 diff --git a/src/Mod/Fem/test_files/ccx/cube_frequency.inp b/src/Mod/Fem/test_files/ccx/cube_frequency.inp index 3e1d02013c8e..bb8b5323b053 100644 --- a/src/Mod/Fem/test_files/ccx/cube_frequency.inp +++ b/src/Mod/Fem/test_files/ccx/cube_frequency.inp @@ -525,7 +525,7 @@ S ** written by --> FreeCAD 0.16.5838 +1 (Git) ** written on --> Mon Oct 26 18:34:01 2015 ** file name --> -** analysis name --> MechanicalAnalysis +** analysis name --> Analysis ** ** ** diff --git a/src/Mod/Fem/test_files/ccx/cube_static.inp b/src/Mod/Fem/test_files/ccx/cube_static.inp index 09f63801247e..7c44ef7e773a 100644 --- a/src/Mod/Fem/test_files/ccx/cube_static.inp +++ b/src/Mod/Fem/test_files/ccx/cube_static.inp @@ -588,7 +588,7 @@ S ** written by --> FreeCAD 0.16.5838 +1 (Git) ** written on --> Mon Oct 26 18:28:42 2015 ** file name --> -** analysis name --> MechanicalAnalysis +** analysis name --> Analysis ** ** ** diff --git a/src/Mod/Fem/test_files/ccx/spine_thermomech_expected_values b/src/Mod/Fem/test_files/ccx/spine_thermomech_expected_values index 2bcaec7af23c..b86005a1d5ca 100644 --- a/src/Mod/Fem/test_files/ccx/spine_thermomech_expected_values +++ b/src/Mod/Fem/test_files/ccx/spine_thermomech_expected_values @@ -1,9 +1,5 @@ -U1: (-0.000942455, 0.00305855, 0.00729818) -U2: (-0.00163382, 0.000616589, 0.00222318) -U3: (-0.00185329, 0.000543914, 0.00220675) -Uabs: (0, 0.00364478, 0.00732571) -Sabs: (0.307123, 7.74746, 35.8618) -MaxPrin: (-5.82387, 1.31924, 10.9205) -MidPrin: (-37.7671, -4.87764, 10.9098) -MinPrin: (-39.3672, -7.02358, 6.47377) -MaxShear: (0.168182, 4.17141, 18.1004) \ No newline at end of file +U1: (-0.000942455, 0.0030585454755555556, 0.00729818) +U2: (-0.00163382, 0.0006165889555555556, 0.00222318) +U3: (-0.00185329, 0.0005439136222222222, 0.00220675) +Uabs: (0.0, 0.003644782698151031, 0.007325712241135124) +Sabs: (0.30712297252407333, 7.747458526266711, 35.86180372766652)