diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt index b62393d1c7..0a8f6eb03f 100755 --- a/src/Mod/Fem/App/CMakeLists.txt +++ b/src/Mod/Fem/App/CMakeLists.txt @@ -108,6 +108,7 @@ SET(FemScripts_SRCS FemShellThickness.py FemSolverCalculix.py FemTools.py + FemToolsCcx.py MechanicalMaterial.py SelectionObserverFem.py TestFem.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 2c169f923d..efe7c44183 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -21,11 +21,13 @@ INSTALL( ccxFrdReader.py ccxInpWriter.py FemTools.py + FemToolsCcx.py FemCommands.py _CommandFemFromShape.py _CommandPurgeFemResults.py _CommandQuickAnalysis.py + _CommandSolverJobControl.py _CommandMechanicalShowResult.py _TaskPanelResultControl.py @@ -38,10 +40,6 @@ INSTALL( FemAnalysis.py _CommandNewMechanicalAnalysis.py - _CommandSolverJobControl.py - _TaskPanelFemSolverCalculix.py - TaskPanelFemSolverCalculix.ui - FemBeamSection.py _FemBeamSection.py _ViewProviderFemBeamSection.py @@ -67,6 +65,8 @@ INSTALL( _FemSolverCalculix.py _ViewProviderFemSolverCalculix.py _CommandFemSolverCalculix.py + _TaskPanelFemSolverCalculix.py + TaskPanelFemSolverCalculix.ui DESTINATION Mod/Fem diff --git a/src/Mod/Fem/FemTools.py b/src/Mod/Fem/FemTools.py index 7a8d985cad..f0e6bc89cf 100644 --- a/src/Mod/Fem/FemTools.py +++ b/src/Mod/Fem/FemTools.py @@ -1,6 +1,7 @@ # *************************************************************************** # * * # * Copyright (c) 2015 - Przemo Firszt * +# * Copyright (c) 2015 - Bernd Hahnebach * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * @@ -21,24 +22,22 @@ # *************************************************************************** +__title__ = "FemInputWriterCcx" +__author__ = "Przemo Firszt, Bernd Hahnebach" +__url__ = "http://www.freecadweb.org" + + import FreeCAD from PySide import QtCore class FemTools(QtCore.QRunnable, QtCore.QObject): - - finished = QtCore.Signal(int) - - known_analysis_types = ["static", "frequency"] - ## The constructor # @param analysis - analysis object to be used as the core object. - # @param test_mode - True indicates that no real calculations will take place, so ccx bianry is not required. Used by test module. # "__init__" tries to use current active analysis in analysis is left empty. # Rises exception if analysis is not set and there is no active analysis - def __init__(self, analysis=None, test_mode=False): - QtCore.QRunnable.__init__(self) - QtCore.QObject.__init__(self) + # The constructur of FemTools is for use of analysis without solver object + def __init__(self, analysis=None): if analysis: ## @var analysis @@ -50,23 +49,7 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): self.analysis = FemGui.getActiveAnalysis() if self.analysis: self.update_objects() - ## @var base_name - # base name of .inp/.frd file (without extension). It is used to construct .inp file path that is passed to CalculiX ccx - self.base_name = "" - ## @var results_present - # boolean variable indicating if there are calculation results ready for use self.results_present = False - if self.solver: - self.set_analysis_type() - self.set_eigenmode_parameters() - self.setup_working_dir() - else: - raise Exception('FEM: No solver found!') - if test_mode: - self.ccx_binary_present = True - else: - self.ccx_binary_present = False - self.setup_ccx() self.result_object = None else: raise Exception('FEM: No active analysis found!') @@ -269,48 +252,6 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): has_no_references = True return message - def write_inp_file(self): - import ccxInpWriter as iw - import sys - self.inp_file_name = "" - try: - inp_writer = iw.inp_writer(self.analysis, self.mesh, self.materials, - self.fixed_constraints, - self.force_constraints, self.pressure_constraints, - self.displacement_constraints, # OvG: Stick to naming convention - self.beam_sections, self.shell_thicknesses, - self.analysis_type, self.eigenmode_parameters, - self.working_dir) - self.inp_file_name = inp_writer.write_calculix_input_file() - except: - print("Unexpected error when writing CalculiX input file:", sys.exc_info()[0]) - raise - - def start_ccx(self): - import multiprocessing - import os - import subprocess - self.ccx_stdout = "" - self.ccx_stderr = "" - if self.inp_file_name != "" and self.ccx_binary_present: - ont_backup = os.environ.get('OMP_NUM_THREADS') - if not ont_backup: - ont_backup = "" - _env = os.putenv('OMP_NUM_THREADS', str(multiprocessing.cpu_count())) - # change cwd because ccx may crash if directory has no write permission - # there is also a limit of the length of file names so jump to the document directory - cwd = QtCore.QDir.currentPath() - f = QtCore.QFileInfo(self.inp_file_name) - QtCore.QDir.setCurrent(f.path()) - p = subprocess.Popen([self.ccx_binary, "-i ", f.baseName()], - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - shell=False, env=_env) - self.ccx_stdout, self.ccx_stderr = p.communicate() - os.putenv('OMP_NUM_THREADS', ont_backup) - QtCore.QDir.setCurrent(cwd) - return p.returncode - return -1 - ## Sets eigenmode parameters for CalculiX frequency analysis # @param self The python object self # @param number number of eigenmodes that wll be calculated, default read for FEM prefs or 10 if not set in the FEM prefs @@ -393,11 +334,20 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): if working_dir is not None: self.working_dir = working_dir else: - try: - self.working_dir = self.solver.WorkingDir - except: - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem").GetString("WorkingDir") - self.working_dir = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem").GetString("WorkingDir") + self.working_dir = '' + self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem") + if self.fem_prefs.GetString("WorkingDir"): + try: + self.working_dir = self.fem_prefs.GetString("WorkingDir") + except: + print('Could not set working directory to FEM Preferences working directory.') + else: + print('FEM preferences working dir is not set, the solver working directory is used.') + if self.solver.WorkingDir: + try: + self.working_dir = self.solver.WorkingDir + except: + print('Could not set working directory to solver working directory.') if not (os.path.isdir(self.working_dir)): try: @@ -407,78 +357,10 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): import tempfile self.working_dir = tempfile.gettempdir() print("Dir \'{}\' will be used instead.".format(self.working_dir)) + print('FemTools.setup_working_dir() --> self.working_dir = ' + self.working_dir) # Update inp file name self.set_inp_file_name() - ## Sets CalculiX ccx binary path and velidates if the binary can be executed - # @param self The python object self - # @ccx_binary path to ccx binary, default is guessed: "bin/ccx" windows, "ccx" for other systems - # @ccx_binary_sig expected output form ccx when run empty. Default value is "CalculiX.exe -i jobname" - def setup_ccx(self, ccx_binary=None, ccx_binary_sig="CalculiX"): - from platform import system - if not ccx_binary: - self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem") - ccx_binary = self.fem_prefs.GetString("ccxBinaryPath", "") - if not ccx_binary: - if system() == "Linux": - ccx_binary = "ccx" - elif system() == "Windows": - ccx_binary = FreeCAD.getHomePath() + "bin/ccx.exe" - else: - ccx_binary = "ccx" - self.ccx_binary = ccx_binary - - import subprocess - startup_info = None - if system() == "Windows": - # Windows workaround to avoid blinking terminal window - startup_info = subprocess.STARTUPINFO() - startup_info.dwFlags = subprocess.STARTF_USESHOWWINDOW - ccx_stdout = None - ccx_stderr = None - try: - p = subprocess.Popen([self.ccx_binary], stdout=subprocess.PIPE, - stderr=subprocess.PIPE, shell=False, - startupinfo=startup_info) - ccx_stdout, ccx_stderr = p.communicate() - if ccx_binary_sig in ccx_stdout: - self.ccx_binary_present = True - except OSError as e: - FreeCAD.Console.PrintError(e.message) - if e.errno == 2: - raise Exception("FEM: CalculiX binary ccx \'{}\' not found. Please set it in FEM preferences.".format(ccx_binary)) - except Exception as e: - FreeCAD.Console.PrintError(e.message) - raise Exception("FEM: CalculiX ccx \'{}\' output \'{}\' doesn't contain expected phrase \'{}\'. Please use ccx 2.6 or newer". - format(ccx_binary, ccx_stdout, ccx_binary_sig)) - - ## Load results of ccx calculations from .frd file. - # @param self The python object self - def load_results(self): - import ccxFrdReader - import os - self.results_present = False - frd_result_file = os.path.splitext(self.inp_file_name)[0] + '.frd' - if os.path.isfile(frd_result_file): - ccxFrdReader.importFrd(frd_result_file, self.analysis) - for m in self.analysis.Member: - if m.isDerivedFrom("Fem::FemResultObject"): - self.result_object = m - if self.result_object: - self.results_present = True - else: - raise Exception('FEM: No results found at {}!'.format(frd_result_file)) - - import ccxDatReader - dat_result_file = os.path.splitext(self.inp_file_name)[0] + '.dat' - if os.path.isfile(dat_result_file): - mode_frequencies = ccxDatReader.import_dat(dat_result_file, self.analysis) - else: - raise Exception('FEM: No .dat results found at {}!'.format(dat_result_file)) - for m in self.analysis.Member: - if m.isDerivedFrom("Fem::FemResultObject") and m.Eigenmode > 0: - m.EigenmodeFrequency = mode_frequencies[m.Eigenmode - 1]['frequency'] - def use_results(self, results_name=None): for m in self.analysis.Member: if m.isDerivedFrom("Fem::FemResultObject") and m.Name == results_name: @@ -487,28 +369,6 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): if not self.result_object: raise Exception("{} doesn't exist".format(results_name)) - def run(self): - ret_code = 0 - message = self.check_prerequisites() - if not message: - self.write_inp_file() - from FreeCAD import Base - progress_bar = Base.ProgressIndicator() - progress_bar.start("Running CalculiX ccx...", 0) - ret_code = self.start_ccx() - self.finished.emit(ret_code) - progress_bar.stop() - else: - print("Running analysis failed! {}".format(message)) - if ret_code or self.ccx_stderr: - print("Analysis failed with exit code {}".format(ret_code)) - print("--------start of stderr-------") - print(self.ccx_stderr) - print("--------end of stderr---------") - print("--------start of stdout-------") - print(self.ccx_stdout) - print("--------end of stdout---------") - ## Returns minimum, average and maximum value for provided result type # @param self The python object self # @param result_type Type of FEM result, allowed are: diff --git a/src/Mod/Fem/FemToolsCcx.py b/src/Mod/Fem/FemToolsCcx.py new file mode 100644 index 0000000000..d99519f63c --- /dev/null +++ b/src/Mod/Fem/FemToolsCcx.py @@ -0,0 +1,219 @@ +# *************************************************************************** +# * * +# * Copyright (c) 2015 - Przemo Firszt * +# * Copyright (c) 2016 - Bernd Hahnebach * +# * * +# * 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. * +# * * +# * This program 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 this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + + +__title__ = "FemToolsCcx" +__author__ = "Przemo Firszt, Bernd Hahnebach" +__url__ = "http://www.freecadweb.org" + + +import FreeCAD +import FemTools +from PySide import QtCore + + +class FemToolsCcx(FemTools.FemTools): + + known_analysis_types = ["static", "frequency"] + finished = QtCore.Signal(int) + + ## The constructor + # @param analysis - analysis object to be used as the core object. + # @param test_mode - True indicates that no real calculations will take place, so ccx bianry is not required. Used by test module. + # "__init__" tries to use current active analysis in analysis is left empty. + # Rises exception if analysis is not set and there is no active analysis + def __init__(self, analysis=None, test_mode=False): + QtCore.QRunnable.__init__(self) + QtCore.QObject.__init__(self) + if analysis: + ## @var analysis + # FEM analysis - the core object. Has to be present. + # It's set to analysis passed in "__init__" or set to current active analysis by default if nothing has been passed to "__init__". + self.analysis = analysis + else: + import FemGui + self.analysis = FemGui.getActiveAnalysis() + if self.analysis: + self.update_objects() + ## @var base_name + # base name of .inp/.frd file (without extension). It is used to construct .inp file path that is passed to CalculiX ccx + self.base_name = "" + ## @var results_present + # boolean variable indicating if there are calculation results ready for use + self.results_present = False + if self.solver: + self.set_analysis_type() + self.set_eigenmode_parameters() + self.setup_working_dir() + else: + raise Exception('FEM: No solver found!') + if test_mode: + self.ccx_binary_present = True + else: + self.ccx_binary_present = False + self.setup_ccx() + self.result_object = None + else: + raise Exception('FEM: No active analysis found!') + + def write_inp_file(self): + import FemInputWriterCcx as iw + import sys + self.inp_file_name = "" + try: + inp_writer = iw.FemInputWriterCcx(self.analysis, self.mesh, self.materials, + self.fixed_constraints, + self.force_constraints, self.pressure_constraints, + self.displacement_constraints, + self.beam_sections, self.shell_thicknesses, + self.analysis_type, self.eigenmode_parameters, + self.working_dir) + self.inp_file_name = inp_writer.write_calculix_input_file() + except: + print("Unexpected error when writing CalculiX input file:", sys.exc_info()[0]) + raise + + ## Sets CalculiX ccx binary path and velidates if the binary can be executed + # @param self The python object self + # @ccx_binary path to ccx binary, default is guessed: "bin/ccx" windows, "ccx" for other systems + # @ccx_binary_sig expected output form ccx when run empty. Default value is "CalculiX.exe -i jobname" + def setup_ccx(self, ccx_binary=None, ccx_binary_sig="CalculiX"): + from platform import system + if not ccx_binary: + self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem") + ccx_binary = self.fem_prefs.GetString("ccxBinaryPath", "") + if not ccx_binary: + if system() == "Linux": + ccx_binary = "ccx" + elif system() == "Windows": + ccx_binary = FreeCAD.getHomePath() + "bin/ccx.exe" + else: + ccx_binary = "ccx" + self.ccx_binary = ccx_binary + + import subprocess + startup_info = None + if system() == "Windows": + # Windows workaround to avoid blinking terminal window + startup_info = subprocess.STARTUPINFO() + startup_info.dwFlags = subprocess.STARTF_USESHOWWINDOW + ccx_stdout = None + ccx_stderr = None + try: + p = subprocess.Popen([self.ccx_binary], stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=False, + startupinfo=startup_info) + ccx_stdout, ccx_stderr = p.communicate() + if ccx_binary_sig in ccx_stdout: + self.ccx_binary_present = True + except OSError as e: + FreeCAD.Console.PrintError(e.message) + if e.errno == 2: + raise Exception("FEM: CalculiX binary ccx \'{}\' not found. Please set it in FEM preferences.".format(ccx_binary)) + except Exception as e: + FreeCAD.Console.PrintError(e.message) + raise Exception("FEM: CalculiX ccx \'{}\' output \'{}\' doesn't contain expected phrase \'{}\'. Please use ccx 2.6 or newer". + format(ccx_binary, ccx_stdout, ccx_binary_sig)) + + def start_ccx(self): + import multiprocessing + import os + import subprocess + self.ccx_stdout = "" + self.ccx_stderr = "" + if self.inp_file_name != "" and self.ccx_binary_present: + ont_backup = os.environ.get('OMP_NUM_THREADS') + if not ont_backup: + ont_backup = "" + _env = os.putenv('OMP_NUM_THREADS', str(multiprocessing.cpu_count())) + # change cwd because ccx may crash if directory has no write permission + # there is also a limit of the length of file names so jump to the document directory + cwd = QtCore.QDir.currentPath() + f = QtCore.QFileInfo(self.inp_file_name) + QtCore.QDir.setCurrent(f.path()) + p = subprocess.Popen([self.ccx_binary, "-i ", f.baseName()], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + shell=False, env=_env) + self.ccx_stdout, self.ccx_stderr = p.communicate() + os.putenv('OMP_NUM_THREADS', ont_backup) + QtCore.QDir.setCurrent(cwd) + return p.returncode + return -1 + + def run(self): + ret_code = 0 + message = self.check_prerequisites() + if not message: + self.write_inp_file() + from FreeCAD import Base + progress_bar = Base.ProgressIndicator() + progress_bar.start("Running CalculiX ccx...", 0) + ret_code = self.start_ccx() + self.finished.emit(ret_code) + progress_bar.stop() + else: + print("Running analysis failed! {}".format(message)) + if ret_code or self.ccx_stderr: + print("Analysis failed with exit code {}".format(ret_code)) + print("--------start of stderr-------") + print(self.ccx_stderr) + print("--------end of stderr---------") + print("--------start of stdout-------") + print(self.ccx_stdout) + print("--------end of stdout---------") + + def load_results(self): + self.results_present = False + self.load_results_ccxfrd() + self.load_results_ccxdat() + + ## Load results of ccx calculations from .frd file. + # @param self The python object self + def load_results_ccxfrd(self): + import os + import ccxFrdReader + frd_result_file = os.path.splitext(self.inp_file_name)[0] + '.frd' + if os.path.isfile(frd_result_file): + ccxFrdReader.importFrd(frd_result_file, self.analysis) + for m in self.analysis.Member: + if m.isDerivedFrom("Fem::FemResultObject"): + self.result_object = m + if self.result_object: + self.results_present = True + else: + raise Exception('FEM: No results found at {}!'.format(frd_result_file)) + self.load_results_ccxdat() + + ## Load results of ccx calculations from .dat file. + # @param self The python object self + def load_results_ccxdat(self): + import os + import ccxDatReader + dat_result_file = os.path.splitext(self.inp_file_name)[0] + '.dat' + if os.path.isfile(dat_result_file): + mode_frequencies = ccxDatReader.import_dat(dat_result_file, self.analysis) + else: + raise Exception('FEM: No .dat results found at {}!'.format(dat_result_file)) + for m in self.analysis.Member: + if m.isDerivedFrom("Fem::FemResultObject") and m.Eigenmode > 0: + m.EigenmodeFrequency = mode_frequencies[m.Eigenmode - 1]['frequency'] diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index 71cd03c179..8ac511a457 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -25,7 +25,7 @@ #***************************************************************************/ import Fem -import FemTools +import FemToolsCcx import FreeCAD import FemAnalysis import FemSolverCalculix @@ -202,7 +202,7 @@ class FemTest(unittest.TestCase): self.assertTrue(self.pressure_constraint, "FemTest of new pressure constraint failed") self.analysis.Member = self.analysis.Member + [self.pressure_constraint] - fea = FemTools.FemTools(self.analysis, test_mode=True) + fea = FemToolsCcx.FemToolsCcx(self.analysis, 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, @@ -210,7 +210,7 @@ class FemTest(unittest.TestCase): fcc_print('Checking FEM inp file prerequisites for static analysis...') error = fea.check_prerequisites() - self.assertFalse(error, "FemTools check_prerequisites returned error message: {}".format(error)) + self.assertFalse(error, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) fcc_print('Checking FEM inp file write...') @@ -224,7 +224,7 @@ class FemTest(unittest.TestCase): 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, "FemTools write_inp_file test failed.\n{}".format(ret)) + 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) @@ -266,7 +266,7 @@ class FemTest(unittest.TestCase): fcc_print('Checking FEM inp file prerequisites for frequency analysis...') error = fea.check_prerequisites() - self.assertFalse(error, "FemTools check_prerequisites returned error message: {}".format(error)) + 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() @@ -274,7 +274,7 @@ class FemTest(unittest.TestCase): 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, "FemTools write_inp_file test failed.\n{}".format(ret)) + 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) @@ -322,8 +322,8 @@ def create_cube_test_results(): FreeCAD.open(cube_file) import FemGui FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.MechanicalAnalysis) - import FemTools - fea = FemTools.FemTools() + import FemToolsCcx + fea = FemToolsCcx.FemToolsCcx() # static fea.reset_all() @@ -340,7 +340,7 @@ def create_cube_test_results(): f.write(s) f.close() - # could be added in FemTools to the self object as an Attribut + # 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' diff --git a/src/Mod/Fem/_CommandPurgeFemResults.py b/src/Mod/Fem/_CommandPurgeFemResults.py index bff5a718cc..b63554b9e9 100644 --- a/src/Mod/Fem/_CommandPurgeFemResults.py +++ b/src/Mod/Fem/_CommandPurgeFemResults.py @@ -26,7 +26,7 @@ __url__ = "http://www.freecadweb.org" import FreeCAD from FemCommands import FemCommands -from FemTools import FemTools +import FemTools if FreeCAD.GuiUp: import FreeCADGui @@ -43,7 +43,7 @@ class _CommandPurgeFemResults(FemCommands): self.is_active = 'with_results' def Activated(self): - fea = FemTools() + fea = FemTools.FemTools() fea.reset_all() self.hide_meshes_show_parts_constraints() diff --git a/src/Mod/Fem/_CommandQuickAnalysis.py b/src/Mod/Fem/_CommandQuickAnalysis.py index c8604adcf3..ab156e6d05 100644 --- a/src/Mod/Fem/_CommandQuickAnalysis.py +++ b/src/Mod/Fem/_CommandQuickAnalysis.py @@ -25,7 +25,6 @@ __author__ = "Juergen Riegel" __url__ = "http://www.freecadweb.org" import FreeCAD -from FemTools import FemTools from FemCommands import FemCommands if FreeCAD.GuiUp: @@ -48,18 +47,21 @@ class _CommandQuickAnalysis(FemCommands): self.fea.load_results() self.show_results_on_mesh() self.hide_parts_constraints_show_meshes() - else: print ("CalculiX failed ccx finished with error {}".format(ret_code)) - self.fea = FemTools() - self.fea.reset_all() - message = self.fea.check_prerequisites() - if message: - QtGui.QMessageBox.critical(None, "Missing prerequisite", message) - return - self.fea.finished.connect(load_results) - QtCore.QThreadPool.globalInstance().start(self.fea) + if FreeCADGui.Selection.getSelection()[0].SolverType == "FemSolverCalculix": + import FemToolsCcx + self.fea = FemToolsCcx.FemToolsCcx() + self.fea.reset_all() + message = self.fea.check_prerequisites() + if message: + QtGui.QMessageBox.critical(None, "Missing prerequisite", message) + return + self.fea.finished.connect(load_results) + QtCore.QThreadPool.globalInstance().start(self.fea) + else: + QtGui.QMessageBox.critical(None, "Not known solver type", message) def show_results_on_mesh(self): #FIXME proprer mesh refreshing as per FreeCAD.FEM_dialog settings required diff --git a/src/Mod/Fem/_FemSolverCalculix.py b/src/Mod/Fem/_FemSolverCalculix.py index 9e20bd2bfb..0fb44912ef 100644 --- a/src/Mod/Fem/_FemSolverCalculix.py +++ b/src/Mod/Fem/_FemSolverCalculix.py @@ -26,7 +26,7 @@ __url__ = "http://www.freecadweb.org" import FreeCAD -from FemTools import FemTools +import FemToolsCcx class _FemSolverCalculix(): @@ -46,9 +46,9 @@ class _FemSolverCalculix(): obj.WorkingDir = fem_prefs.GetString("WorkingDir", "") obj.addProperty("App::PropertyEnumeration", "AnalysisType", "Fem", "Type of the analysis") - obj.AnalysisType = FemTools.known_analysis_types + obj.AnalysisType = FemToolsCcx.FemToolsCcx.known_analysis_types analysis_type = fem_prefs.GetInt("AnalysisType", 0) - obj.AnalysisType = FemTools.known_analysis_types[analysis_type] + obj.AnalysisType = FemToolsCcx.FemToolsCcx.known_analysis_types[analysis_type] obj.addProperty("App::PropertyIntegerConstraint", "NumberOfEigenmodes", "Fem", "Number of modes for frequency calculations") noe = fem_prefs.GetInt("NumberOfEigenmodes", 10) diff --git a/src/Mod/Fem/_TaskPanelFemSolverCalculix.py b/src/Mod/Fem/_TaskPanelFemSolverCalculix.py index 35381e4c2d..eae135b555 100644 --- a/src/Mod/Fem/_TaskPanelFemSolverCalculix.py +++ b/src/Mod/Fem/_TaskPanelFemSolverCalculix.py @@ -24,7 +24,7 @@ __title__ = "CalculiX Job Control Task Panel" __author__ = "Juergen Riegel" __url__ = "http://www.freecadweb.org" -from FemTools import FemTools +import FemToolsCcx import FreeCAD import os import time @@ -141,7 +141,7 @@ class _TaskPanelFemSolverCalculix: self.form.pb_run_ccx.setText("Re-run CalculiX") self.femConsoleMessage("Loading result sets...") self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start)) - fea = FemTools() + fea = FemToolsCcx.FemToolsCcx() fea.reset_all() fea.inp_file_name = self.inp_file_name QApplication.setOverrideCursor(Qt.WaitCursor) @@ -182,7 +182,7 @@ class _TaskPanelFemSolverCalculix: if self.check_prerequisites_helper(): QApplication.setOverrideCursor(Qt.WaitCursor) self.inp_file_name = "" - fea = FemTools() + fea = FemToolsCcx.FemToolsCcx() fea.set_analysis_type(self.solver_object.AnalysisType) fea.update_objects() fea.write_inp_file() @@ -200,7 +200,7 @@ class _TaskPanelFemSolverCalculix: self.femConsoleMessage("Check dependencies...") self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start)) - fea = FemTools() + fea = FemToolsCcx.FemToolsCcx() fea.update_objects() message = fea.check_prerequisites() if message != "": diff --git a/src/Mod/Fem/_TaskPanelResultControl.py b/src/Mod/Fem/_TaskPanelResultControl.py index c4d892aa25..51f48b3aa9 100644 --- a/src/Mod/Fem/_TaskPanelResultControl.py +++ b/src/Mod/Fem/_TaskPanelResultControl.py @@ -26,7 +26,7 @@ __url__ = "http://www.freecadweb.org" import FreeCAD -from FemTools import FemTools +import FemTools if FreeCAD.GuiUp: import FreeCADGui @@ -100,7 +100,7 @@ class _TaskPanelResultControl: def restore_initial_result_dialog(self): FreeCAD.FEM_dialog = {"results_type": "None", "show_disp": False, "disp_factor": 0, "disp_factor_max": 100} - fea = FemTools() + fea = FemTools.FemTools() fea.reset_mesh_color() fea.reset_mesh_deformation() @@ -122,7 +122,7 @@ class _TaskPanelResultControl: def none_selected(self, state): FreeCAD.FEM_dialog["results_type"] = "None" self.set_result_stats("mm", 0.0, 0.0, 0.0) - fea = FemTools() + fea = FemTools.FemTools() fea.reset_mesh_color() def abs_displacement_selected(self, state):