# Unit test for the FEM module # *************************************************************************** # * Copyright (c) 2015 - FreeCAD Developers * # * Author: Przemo Firszt * # * * # * 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 FemToolsCcx import FreeCAD import FemAnalysis import FemSolverCalculix import FemMaterial import csv import tempfile import unittest mesh_name = 'Mesh' home_path = FreeCAD.getHomePath() temp_dir = tempfile.gettempdir() test_file_dir = home_path + 'Mod/Fem/test_files/ccx' static_base_name = 'cube_static' static_analysis_dir = temp_dir + '/FEM_static' static_save_fc_file = static_analysis_dir + '/' + static_base_name + '.fcstd' static_analysis_inp_file = test_file_dir + '/' + static_base_name + '.inp' static_expected_values = test_file_dir + "/cube_static_expected_values" frequency_base_name = 'cube_frequency' frequency_analysis_dir = temp_dir + '/FEM_frequency' frequency_save_fc_file = frequency_analysis_dir + '/' + frequency_base_name + '.fcstd' frequency_analysis_inp_file = test_file_dir + '/' + frequency_base_name + '.inp' frequency_expected_values = test_file_dir + "/cube_frequency_expected_values" thermomech_base_name = 'spine_thermomech' thermomech_analysis_dir = temp_dir + '/FEM_thermomech' thermomech_save_fc_file = thermomech_analysis_dir + '/' + thermomech_base_name + '.fcstd' thermomech_analysis_inp_file = test_file_dir + '/' + thermomech_base_name + '.inp' thermomech_expected_values = test_file_dir + "/spine_thermomech_expected_values" 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' spine_volumes_file = test_file_dir + '/spine_volumes.csv' def fcc_print(message): FreeCAD.Console.PrintMessage('{} \n'.format(message)) class FemTest(unittest.TestCase): def setUp(self): try: FreeCAD.setActiveDocument("FemTest") except: FreeCAD.newDocument("FemTest") finally: FreeCAD.setActiveDocument("FemTest") self.active_doc = FreeCAD.ActiveDocument self.box = self.active_doc.addObject("Part::Box", "Box") self.active_doc.recompute() def create_new_analysis(self): self.analysis = FemAnalysis.makeFemAnalysis('Analysis') self.active_doc.recompute() def create_new_solver(self): self.solver_object = FemSolverCalculix.makeFemSolverCalculix('CalculiX') self.solver_object.GeometricalNonlinearity = 'linear' self.solver_object.ThermoMechSteadyState = False self.solver_object.MatrixSolverType = 'default' self.solver_object.IterationsControlParameterTimeUse = False self.solver_object.EigenmodesCount = 10 self.solver_object.EigenmodeHighLimit = 1000000.0 self.solver_object.EigenmodeLowLimit = 0.0 self.active_doc.recompute() def create_new_mesh(self): self.mesh_object = self.active_doc.addObject('Fem::FemMeshObject', mesh_name) self.mesh = Fem.FemMesh() with open(mesh_points_file, 'r') as points_file: reader = csv.reader(points_file) for p in reader: self.mesh.addNode(float(p[1]), float(p[2]), float(p[3]), int(p[0])) with open(mesh_volumes_file, 'r') as volumes_file: reader = csv.reader(volumes_file) for v in reader: self.mesh.addVolume([int(v[2]), int(v[1]), int(v[3]), int(v[4]), int(v[5]), int(v[7]), int(v[6]), int(v[9]), int(v[8]), int(v[10])], int(v[0])) self.mesh_object.FemMesh = self.mesh self.active_doc.recompute() def create_new_material(self): self.new_material_object = FemMaterial.makeFemMaterial('MechanicalMaterial') mat = self.new_material_object.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "200000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" self.new_material_object.Material = mat def create_fixed_constraint(self): self.fixed_constraint = self.active_doc.addObject("Fem::ConstraintFixed", "FemConstraintFixed") self.fixed_constraint.References = [(self.box, "Face1")] def create_force_constraint(self): self.force_constraint = self.active_doc.addObject("Fem::ConstraintForce", "FemConstraintForce") self.force_constraint.References = [(self.box, "Face6")] self.force_constraint.Force = 40000.0 self.force_constraint.Direction = (self.box, ["Edge5"]) self.force_constraint.Reversed = True def create_pressure_constraint(self): self.pressure_constraint = self.active_doc.addObject("Fem::ConstraintPressure", "FemConstraintPressure") self.pressure_constraint.References = [(self.box, "Face2")] 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: if l.endswith("\r\n"): l = l[:-2] + '\n' new_line_list.append(l) return new_line_list 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 ') 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 ') or l.startswith('** file '))] lf2 = self.force_unix_line_ends(lf2) import difflib diff = difflib.unified_diff(lf1, lf2, n=0) result = '' for l in diff: result += l if result: result = "Comparing {} to {} failed!\n".format(file_name1, file_name2) + result return result def compare_stats(self, fea, stat_file=None): if stat_file: sf = open(stat_file, 'r') sf_content = sf.readlines() sf.close() sf_content = self.force_unix_line_ends(sf_content) stat_types = ["U1", "U2", "U3", "Uabs", "Sabs"] stats = [] for s in stat_types: stats.append("{}: {}\n".format(s, fea.get_stats(s))) if sf_content != stats: fcc_print("Expected stats from {}".format(stat_file)) fcc_print(sf_content) fcc_print("Stats read from {}.frd file".format(fea.base_name)) fcc_print(stats) return True return False def test_new_analysis(self): # static fcc_print('--------------- Start of FEM tests ---------------') fcc_print('Checking FEM new analysis...') self.create_new_analysis() self.assertTrue(self.analysis, "FemTest of new analysis failed") fcc_print('Checking FEM new solver...') self.create_new_solver() self.assertTrue(self.solver_object, "FemTest of new solver failed") self.analysis.Member = self.analysis.Member + [self.solver_object] fcc_print('Checking FEM new mesh...') self.create_new_mesh() self.assertTrue(self.mesh, "FemTest of new mesh failed") self.analysis.Member = self.analysis.Member + [self.mesh_object] fcc_print('Checking FEM new material...') self.create_new_material() self.assertTrue(self.new_material_object, "FemTest of new material failed") self.analysis.Member = self.analysis.Member + [self.new_material_object] fcc_print('Checking FEM new fixed constraint...') self.create_fixed_constraint() self.assertTrue(self.fixed_constraint, "FemTest of new fixed constraint failed") self.analysis.Member = self.analysis.Member + [self.fixed_constraint] fcc_print('Checking FEM new force constraint...') self.create_force_constraint() self.assertTrue(self.force_constraint, "FemTest of new force constraint failed") self.analysis.Member = self.analysis.Member + [self.force_constraint] fcc_print('Checking FEM new pressure constraint...') self.create_pressure_constraint() self.assertTrue(self.pressure_constraint, "FemTest of new pressure constraint failed") self.analysis.Member = self.analysis.Member + [self.pressure_constraint] fea = FemToolsCcx.FemToolsCcx(self.analysis, self.solver_object, test_mode=True) 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, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) fcc_print('Checking FEM inp file write...') fcc_print('Setting analysis type to \'static\"') fea.set_analysis_type("static") self.assertTrue(True if fea.analysis_type == 'static' else False, "Setting anlysis type to \'static\' failed") fcc_print('Writing {}/{}.inp for static analysis'.format(static_analysis_dir, mesh_name)) error = fea.write_inp_file() self.assertFalse(error, "Writing failed") fcc_print('Comparing {} to {}/{}.inp'.format(static_analysis_inp_file, static_analysis_dir, mesh_name)) ret = self.compare_inp_files(static_analysis_inp_file, static_analysis_dir + "/" + mesh_name + '.inp') self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) fcc_print('Setting up working directory to {} in order to read simulated calculations'.format(test_file_dir)) fea.setup_working_dir(test_file_dir) self.assertTrue(True if fea.working_dir == test_file_dir else False, "Setting working directory {} failed".format(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 == static_analysis_inp_file else False, "Setting inp file name to {} failed".format(static_analysis_inp_file)) 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...') 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") fcc_print('Setting up working directory to {} in order to write frequency calculations'.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, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) fcc_print('Writing {}/{}.inp for frequency analysis'.format(frequency_analysis_dir, mesh_name)) error = fea.write_inp_file() self.assertFalse(error, "Writing failed") fcc_print('Comparing {} to {}/{}.inp'.format(frequency_analysis_inp_file, frequency_analysis_dir, mesh_name)) ret = self.compare_inp_files(frequency_analysis_inp_file, frequency_analysis_dir + "/" + mesh_name + '.inp') self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) fcc_print('Setting up working directory to {} in order to read simulated calculations'.format(test_file_dir)) fea.setup_working_dir(test_file_dir) self.assertTrue(True if fea.working_dir == test_file_dir else False, "Setting working directory {} failed".format(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 == frequency_analysis_inp_file else False, "Setting inp file name to {} failed".format(frequency_analysis_inp_file)) 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...') ret = self.compare_stats(fea, frequency_expected_values) self.assertFalse(ret, "Invalid results read from .frd file") 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") pass class TherMechFemTest(unittest.TestCase): def setUp(self): try: FreeCAD.setActiveDocument("TherMechFemTest") except: FreeCAD.newDocument("TherMechFemTest") finally: FreeCAD.setActiveDocument("TherMechFemTest") self.active_doc = FreeCAD.ActiveDocument self.box = self.active_doc.addObject("Part::Box", "Box") self.box.Height = 25.4 self.box.Width = 25.4 self.box.Length = 203.2 self.active_doc.recompute() def create_new_analysis(self): self.analysis = FemAnalysis.makeFemAnalysis('Analysis') self.active_doc.recompute() 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' self.solver_object.IterationsThermoMechMaximum = 2000 self.solver_object.IterationsControlParameterTimeUse = True self.active_doc.recompute() def create_new_mesh(self): self.mesh_object = self.active_doc.addObject('Fem::FemMeshObject', mesh_name) self.mesh = Fem.FemMesh() with open(spine_points_file, 'r') as points_file: reader = csv.reader(points_file) for p in reader: self.mesh.addNode(float(p[1]), float(p[2]), float(p[3]), int(p[0])) with open(spine_volumes_file, 'r') as volumes_file: reader = csv.reader(volumes_file) for v in reader: self.mesh.addVolume([int(v[2]), int(v[1]), int(v[3]), int(v[4]), int(v[5]), int(v[7]), int(v[6]), int(v[9]), int(v[8]), int(v[10])], int(v[0])) self.mesh_object.FemMesh = self.mesh self.active_doc.recompute() def create_new_material(self): self.new_material_object = FemMaterial.makeFemMaterial('MechanicalMaterial') mat = self.new_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 self.new_material_object.Material = mat def create_fixed_constraint(self): self.fixed_constraint = self.active_doc.addObject("Fem::ConstraintFixed", "FemConstraintFixed") self.fixed_constraint.References = [(self.box, "Face1")] def create_initialtemperature_constraint(self): self.initialtemperature_constraint = self.active_doc.addObject("Fem::ConstraintInitialTemperature", "FemConstraintInitialTemperature") self.initialtemperature_constraint.initialTemperature = 300.0 def create_temperature_constraint(self): self.temperature_constraint = self.active_doc.addObject("Fem::ConstraintTemperature", "FemConstraintTemperature") self.temperature_constraint.References = [(self.box, "Face1")] self.temperature_constraint.Temperature = 310.93 def create_heatflux_constraint(self): self.heatflux_constraint = self.active_doc.addObject("Fem::ConstraintHeatflux", "FemConstraintHeatflux") self.heatflux_constraint.References = [(self.box, "Face3"), (self.box, "Face4"), (self.box, "Face5"), (self.box, "Face6")] 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: if l.endswith("\r\n"): l = l[:-2] + '\n' new_line_list.append(l) return new_line_list 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 ') if not 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 ') if not l.startswith('** file ')] lf2 = self.force_unix_line_ends(lf2) import difflib diff = difflib.unified_diff(lf1, lf2, n=0) result = '' for l in diff: result += l if result: result = "Comparing {} to {} failed!\n".format(file_name1, file_name2) + result return result def compare_stats(self, fea, stat_file=None): if stat_file: sf = open(stat_file, 'r') sf_content = sf.readlines() sf.close() sf_content = self.force_unix_line_ends(sf_content) stat_types = ["U1", "U2", "U3", "Uabs", "Sabs"] stats = [] for s in stat_types: stats.append("{}: {}\n".format(s, fea.get_stats(s))) if sf_content != stats: fcc_print("Expected stats from {}".format(stat_file)) fcc_print(sf_content) fcc_print("Stats read from {}.frd file".format(fea.base_name)) fcc_print(stats) return True return False def test_new_analysis(self): fcc_print('--------------- Start of FEM tests ---------------') fcc_print('Checking FEM new analysis...') self.create_new_analysis() self.assertTrue(self.analysis, "FemTest of new analysis failed") fcc_print('Checking FEM new solver...') self.create_new_solver() self.assertTrue(self.solver_object, "FemTest of new solver failed") self.analysis.Member = self.analysis.Member + [self.solver_object] fcc_print('Checking FEM new mesh...') self.create_new_mesh() self.assertTrue(self.mesh, "FemTest of new mesh failed") self.analysis.Member = self.analysis.Member + [self.mesh_object] fcc_print('Checking FEM new material...') self.create_new_material() self.assertTrue(self.new_material_object, "FemTest of new material failed") self.analysis.Member = self.analysis.Member + [self.new_material_object] fcc_print('Checking FEM new fixed constraint...') self.create_fixed_constraint() self.assertTrue(self.fixed_constraint, "FemTest of new fixed constraint failed") self.analysis.Member = self.analysis.Member + [self.fixed_constraint] fcc_print('Checking FEM new initial temperature constraint...') self.create_initialtemperature_constraint() self.assertTrue(self.initialtemperature_constraint, "FemTest of new initial temperature constraint failed") self.analysis.Member = self.analysis.Member + [self.initialtemperature_constraint] fcc_print('Checking FEM new temperature constraint...') self.create_temperature_constraint() self.assertTrue(self.temperature_constraint, "FemTest of new temperature constraint failed") self.analysis.Member = self.analysis.Member + [self.temperature_constraint] fcc_print('Checking FEM new heatflux constraint...') self.create_heatflux_constraint() self.assertTrue(self.heatflux_constraint, "FemTest of new heatflux constraint failed") self.analysis.Member = self.analysis.Member + [self.heatflux_constraint] fea = FemToolsCcx.FemToolsCcx(self.analysis, test_mode=True) 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('Setting analysis type to \'thermomech\"') fea.set_analysis_type("thermomech") self.assertTrue(True if fea.analysis_type == 'thermomech' else False, "Setting anlysis type to \'thermomech\' failed") fcc_print('Checking FEM inp file prerequisites for thermo-mechanical analysis...') error = fea.check_prerequisites() self.assertFalse(error, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) fcc_print('Checking FEM inp file write...') fcc_print('Writing {}/{}.inp for thermomech analysis'.format(thermomech_analysis_dir, mesh_name)) error = fea.write_inp_file() self.assertFalse(error, "Writing failed") fcc_print('Comparing {} to {}/{}.inp'.format(thermomech_analysis_inp_file, thermomech_analysis_dir, mesh_name)) ret = self.compare_inp_files(thermomech_analysis_inp_file, thermomech_analysis_dir + "/" + mesh_name + '.inp') self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) fcc_print('Setting up working directory to {} in order to read simulated calculations'.format(test_file_dir)) fea.setup_working_dir(test_file_dir) self.assertTrue(True if fea.working_dir == test_file_dir else False, "Setting working directory {} failed".format(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 == 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 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() import os import shutil import FemGui import FemToolsCcx # static and frequency cube FreeCAD.open(static_save_fc_file) FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) fea = FemToolsCcx.FemToolsCcx() # static fea.reset_all() fea.run() fea.load_results() stat_types = ["U1", "U2", "U3", "Uabs", "Sabs"] 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 = static_analysis_dir + '/cube_static_expected_values' f = open(static_expected_values_file, 'w') for s in stats_static: 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_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 fea.reset_all() fea.set_analysis_type('frequency') fea.solver.EigenmodesCount = 1 # we should only have one result object fea.run() fea.load_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 = 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 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: import TestFem TestFem.create_test_results() 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 TODO compare the inp file of the helper with the inp file of FEM unit tests '''