From 688a6ddf058ed9ec1283d08ba4cbcb16f230e893 Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:53 +0200 Subject: [PATCH] FEM: Add documentation to setting module --- src/Mod/Fem/femsolver/run.py | 27 ++-- src/Mod/Fem/femsolver/settings.py | 220 +++++++++++++++++++----------- 2 files changed, 151 insertions(+), 96 deletions(-) diff --git a/src/Mod/Fem/femsolver/run.py b/src/Mod/Fem/femsolver/run.py index 0e2f8dc4de..ed63130fc2 100644 --- a/src/Mod/Fem/femsolver/run.py +++ b/src/Mod/Fem/femsolver/run.py @@ -124,15 +124,15 @@ def _isPathValid(m, path): setting = settings.get_dir_setting() if path is not None: return t is None and m.directory == path - if setting == settings.BESIDE: - if t == settings.BESIDE: + if setting == settings.DirSetting.BESIDE: + if t == settings.DirSetting.BESIDE: base = os.path.split(m.directory.rstrip("/"))[0] return base == femutils.get_beside_base(m.solver) return False - if setting == settings.TEMPORARY: - return t == settings.TEMPORARY - if setting == settings.CUSTOM: - if t == settings.CUSTOM: + if setting == settings.DirSetting.TEMPORARY: + return t == settings.DirSetting.TEMPORARY + if setting == settings.DirSetting.CUSTOM: + if t == settings.DirSetting.CUSTOM: firstBase = os.path.split(m.directory.rstrip("/"))[0] customBase = os.path.split(firstBase)[0] return customBase == femutils.get_custom_base(m.solver) @@ -393,17 +393,11 @@ class _DocObserver(object): def _deleteMachine(self, obj): m = _machines[obj] t = _dirTypes[m.directory] - - def delegate(): - m.join() - if t == settings.TEMPORARY: - shutil.rmtree(m.directory) - del _dirTypes[m.directory] - del _machines[obj] m.abort() - thread = threading.Thread(target=delegate) - thread.daemon = False - thread.start() + if t == settings.DirSetting.TEMPORARY: + shutil.rmtree(m.directory) + del _machines[obj] + del _dirTypes[m.directory] def _checkEquation(self, obj): for o in obj.Document.Objects: @@ -456,5 +450,4 @@ class _DocObserver(object): return True return False - ## @} diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py index 7b3621fde8..48b4f685c4 100644 --- a/src/Mod/Fem/femsolver/settings.py +++ b/src/Mod/Fem/femsolver/settings.py @@ -19,28 +19,58 @@ # * USA * # * * # *************************************************************************** +""" Query FEM specific settings including solver settings. + +Query settings from the hierarchically organized settings/parameter system of +FreeCAD related to the FEM module. The collection of independed functions use +the settings system as a backend and expose a easy to use interface for other +modules of the FEM module. + +Functions quering solver specific settings always take a solver name as a +string to identify the solver in question. At the moment the following solvers +are supported: + + - Calculix + - ElmerSolver + - Z88 + +To query settings about those solver the solver name must be given exactely in +the form written in the list above. To make the solver recognize settings for a +new solver have a look at :class:`_SolverDlg`. +""" __title__ = "FreeCAD FEM solver settings" __author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" -## \addtogroup FEM -# @{ - -""" -parameter in FreeCAD can be edited in two ways, either in the -Preferences: menu Edit --> Preferences -or -Parameter editor: menu Tools --> Edit parameter -""" import FreeCAD -# working directory: possible choices -TEMPORARY = "temporary" -BESIDE = "beside" -CUSTOM = "custom" +class DirSetting: + """ Enum of possible directory setting values. + + Strings used to indicate the solver directory setting set in FreeCADs + setting system. Returned by :func:`get_dir_setting` for that purpose. There + are three different possible values: + + :cvar TEMPORARY: + Let FreeCAD manage (create, delete) the working directories for all + solver. Use temporary directories. + + :cvar BESIDE: + Create a directory in the same folder in which the FCStd file of the + document is located. Use Subfolder for each solver (e.g. for a file + ./mydoc.FCStd and a solver with the label Elmer002 use + ./mydoc/Elmer002). + + :cvar CUSTOM: + Use directory set below. Create own subdirectory for every solver. Name + directory after the solver label prefixed with the document name. + """ + TEMPORARY = "temporary" + BESIDE = "beside" + CUSTOM = "custom" # FEM parameter location path @@ -48,26 +78,117 @@ _PARAM_PATH = "User parameter:BaseApp/Preferences/Mod/Fem/" _GENERAL_PARAM = _PARAM_PATH + "General" -# ******** binary parameter ********************************************************************** +def get_binary(name): + """ Find binary of solver *name* honoring user settings. + + Return the specific path set by the user in FreeCADs settings/parameter + system if set or the default binary name if no specific path is set. If no + path was found because the solver *name* isn't supported ``None`` is + returned. This method does not check whether the binary actually exists + and is callable. + + :param name: solver id as a ``str`` (see :mod:`femsolver.settings`) + """ + if name in _SOLVER_PARAM: + binary = _SOLVER_PARAM[name].get_binary() + FreeCAD.Console.PrintMessage('Solver binary path: {} \n'.format(binary)) + return binary + else: + FreeCAD.Console.PrintError( + 'Settings solver name: {} not found in ' + 'solver settings modules _SOLVER_PARAM dirctionary.\n' + .format(name) + ) + return None + + +def get_write_comments(name): + """ Check whether "write_comments" is set for solver. + + Returns ``True`` if the "write_comments" setting/parameter is set for the + solver with the id *name*. Returns ``False`` otherwise. If the solver isn't + supported ``None`` is returned. + + :param name: solver id as a ``str`` (see :mod:`femsolver.settings`) + """ + if name in _SOLVER_PARAM: + return _SOLVER_PARAM[name].get_write_comments() + else: + FreeCAD.Console.PrintError( + 'Settings solver name: {} not found in ' + 'solver settings modules _SOLVER_PARAM dirctionary.\n' + .format(name) + ) + return None + + +def get_custom_dir(): + """ Get value for :term:`General/CustomDirectoryPath` parameter. """ + param_group = FreeCAD.ParamGet(_GENERAL_PARAM) + return param_group.GetString("CustomDirectoryPath") + + +def get_dir_setting(): + """ Return directory setting set by the user. + + Return one of the three possible values of the :class:`DirSetting` enum + depending on the setting set in FreeCAD parameter system. Result dependes + on the values of :term:`General/UseTempDirectory`, + :term:`General/UseBesideDirectory` and :term:`General/UseCustomDirectory`. + """ + param_group = FreeCAD.ParamGet(_GENERAL_PARAM) + if param_group.GetBool("UseBesideDirectory"): + return DirSetting.BESIDE + elif param_group.GetBool("UseCustomDirectory"): + return DirSetting.CUSTOM + return DirSetting.TEMPORARY + + class _SolverDlg(object): + """ Internal query logic for solver specific settings. + + Each instance queries settings for one specific solver (e.g. Elmer) common + among all solvers. To clearify: There are a few settings that are useful + for every solver (e.g. where to find the solver binary) but the value and + the FreeCAD parameter path is different for each one. A instance of this + class contains all the solver specific paths needed. The settings can be + queried via the methods which use those path members to query the value for + the specific solver. + + :ivar default: + Default binary name as a string preferably without a prefix path to + make it more generic (e.g. "ccx"). This only works if the binary can be + found via the PATH environment variable on linux or similar mechanisms + on other operating systems. Used if nothing else is specified by the + user. + + :ivar param_path: + Parent param path (FreeCADs settings/parameter system) that contains + all settings for the specific solver. + + :ivar use_default: + Param path identifying the "use_default" setting. Only specifie the + last part as the *param_path* is prepended to this value. + + :ivar custom_path: + Param path identifying the "custom_path" setting. Only specifie the + last part as the *param_path* is prepended to this value. + """ + + WRITE_COMMENTS_PARAM = "writeCommentsToInputFile" def __init__(self, default, param_path, use_default, custom_path): - - # set the parameter identifier self.default = default self.param_path = param_path self.use_default = use_default self.custom_path = custom_path - self.write_comments = "writeCommentsToInputFile" - # get the parameter object where the paramete are saved in self.param_group = FreeCAD.ParamGet(self.param_path) def get_binary(self): # set the binary path to the FreeCAD defaults # ATM pure unix shell commands without path names are used - # TODO see todo on use_default later in this module binary = self.default FreeCAD.Console.PrintLog("Solver binary path: {} \n".format(binary)) @@ -82,24 +203,9 @@ class _SolverDlg(object): return find_bin(binary) def get_write_comments(self): - return self.param_group.GetBool(self.write_comments, True) + return self.param_group.GetBool(self.WRITE_COMMENTS_PARAM, True) -""" -default: - default command to run the binary - this one is taken if the UseStandardXXXLocationis not given or set to True -param: - path where these settings are saved, in FEM normally one path in one Tab in Preferences GUI -use_default: - the UseStandardXXXLocation parameter identifier - if this parameter is set to True FreeCAD standards - for the binary are usedor FreeCAD tries to find the binary - TODO: see method setup_ccx in ccx tools module, which sets up ccx binary for various os -custom_path: - the xxxBinaryPath parameter identifier - binary path given by the user -""" _SOLVER_PARAM = { "Calculix": _SolverDlg( default="ccx", @@ -122,47 +228,3 @@ _SOLVER_PARAM = { use_default="UseStandardZ88Location", custom_path="z88BinaryPath"), } - - -def get_binary(name): - if name in _SOLVER_PARAM: - binary = _SOLVER_PARAM[name].get_binary() - FreeCAD.Console.PrintMessage("Solver binary path: {} \n".format(binary)) - return binary - else: - FreeCAD.Console.PrintError( - "Settings solver name: {} not found in " - "solver settings modules _SOLVER_PARAM dirctionary.\n" - .format(name) - ) - return None - - -def get_write_comments(name): - if name in _SOLVER_PARAM: - return _SOLVER_PARAM[name].get_write_comments() - else: - FreeCAD.Console.PrintError( - "Settings solver name: {} not found in " - "solver settings modules _SOLVER_PARAM dirctionary.\n" - .format(name) - ) - return None - - -# ******** working directory parameter *********************************************************** -def get_custom_dir(): - param_group = FreeCAD.ParamGet(_GENERAL_PARAM) - return param_group.GetString("CustomDirectoryPath") - - -def get_dir_setting(): - param_group = FreeCAD.ParamGet(_GENERAL_PARAM) - if param_group.GetBool("UseBesideDirectory"): - return BESIDE - elif param_group.GetBool("UseCustomDirectory"): - return CUSTOM - return TEMPORARY - - -## @}