| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | """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 independent functions use |
| | the settings system as a backend and expose a easy to use interface for other |
| | modules of the FEM module. |
| | |
| | Functions querying 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 |
| | - Mystran |
| | - Z88 |
| | |
| | To query settings about those solver the solver name must be given exactly 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__ = "https://www.freecad.org" |
| |
|
| |
|
| | import FreeCAD |
| |
|
| |
|
| | 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" |
| |
|
| |
|
| | |
| | _PARAM_PATH = "User parameter:BaseApp/Preferences/Mod/Fem/" |
| | _GENERAL_PARAM = _PARAM_PATH + "General" |
| |
|
| |
|
| | def get_binary(name, silent=False): |
| | """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* is not supported ``None`` is |
| | returned. |
| | This method does not check whether the binary actually exists and is callable. |
| | That check is done in DlgSettingsFem_Solver_Imp.cpp |
| | |
| | :param name: solver id as a ``str`` (see :mod:`femsolver.settings`) |
| | :param silent: whether to output error if binary not found |
| | """ |
| | if name in _SOLVER_PARAM: |
| | binary = _SOLVER_PARAM[name].get_binary(silent) |
| | return binary |
| | else: |
| | if not silent: |
| | FreeCAD.Console.PrintError( |
| | "Settings solver name: {} not found in " |
| | "solver settings modules _SOLVER_PARAM dirctionary.\n".format(name) |
| | ) |
| | return None |
| |
|
| |
|
| | def get_cores(name): |
| | """Read number of CPU cores for solver *name* honoring user settings. |
| | |
| | Returns number of CPU cores to be used for the solver run |
| | |
| | :param name: solver id as a ``str`` (see :mod:`femsolver.settings`) |
| | """ |
| | if name in _SOLVER_PARAM: |
| | cores = _SOLVER_PARAM[name].get_cores() |
| | return cores |
| | 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 is |
| | not 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 |
| |
|
| |
|
| | def get_default_solver(): |
| | """Return default solver name.""" |
| | solver_map = {0: None} |
| | if get_binary("Calculix", True): |
| | solver_map[1] = "CalculiX" |
| | if get_binary("ElmerSolver", True): |
| | solver_map[len(solver_map)] = "Elmer" |
| | if get_binary("Mystran", True): |
| | solver_map[len(solver_map)] = "Mystran" |
| | if get_binary("Z88", True): |
| | solver_map[len(solver_map)] = "Z88" |
| | param_group = FreeCAD.ParamGet(_GENERAL_PARAM) |
| | return solver_map[param_group.GetInt("DefaultSolver", 0)] |
| |
|
| |
|
| | class _SolverDlg: |
| | """Internal query logic for solver specific settings. |
| | |
| | Each instance queries settings for one specific solver (e.g. Elmer) common |
| | among all solvers. To clarify: 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, custom_path): |
| | self.default = default |
| | self.param_path = param_path |
| | self.custom_path = custom_path |
| |
|
| | self.param_group = FreeCAD.ParamGet(self.param_path) |
| |
|
| | def get_binary(self, silent=False): |
| |
|
| | |
| | |
| | |
| | |
| | |
| | binary = self.param_group.GetString(self.custom_path) |
| | if not binary: |
| | binary = self.default |
| | FreeCAD.Console.PrintLog(f"Solver binary path default: {binary} \n") |
| |
|
| | |
| | |
| | |
| | from shutil import which as find_bin |
| |
|
| | the_found_binary = find_bin(binary) |
| | if (the_found_binary is None) and (not silent): |
| | FreeCAD.Console.PrintError( |
| | f"The binary has not been found. Full binary search path: {binary}\n" |
| | ) |
| | else: |
| | FreeCAD.Console.PrintLog(f"Found solver binary path: {the_found_binary}\n") |
| | return the_found_binary |
| |
|
| | def get_cores(self): |
| | cores = self.param_group.GetInt("UseNumberOfCores") |
| | return cores |
| |
|
| | def get_write_comments(self): |
| | return self.param_group.GetBool(self.WRITE_COMMENTS_PARAM, True) |
| |
|
| |
|
| | _SOLVER_PARAM = { |
| | "Calculix": _SolverDlg( |
| | default="ccx", |
| | param_path=_PARAM_PATH + "Ccx", |
| | custom_path="ccxBinaryPath", |
| | ), |
| | "ElmerSolver": _SolverDlg( |
| | default="ElmerSolver", |
| | param_path=_PARAM_PATH + "Elmer", |
| | custom_path="elmerBinaryPath", |
| | ), |
| | "ElmerGrid": _SolverDlg( |
| | default="ElmerGrid", |
| | param_path=_PARAM_PATH + "Elmer", |
| | custom_path="gridBinaryPath", |
| | ), |
| | "Mystran": _SolverDlg( |
| | default="mystran", |
| | param_path=_PARAM_PATH + "Mystran", |
| | custom_path="mystranBinaryPath", |
| | ), |
| | "Z88": _SolverDlg( |
| | default="z88r", |
| | param_path=_PARAM_PATH + "Z88", |
| | custom_path="z88BinaryPath", |
| | ), |
| | } |
| |
|