Add FEM Equation Tutorial: Difference between revisions
No edit summary |
m (Roy 043 moved page Add FEM equation tutorial to Add FEM Equation Tutorial without leaving a redirect: Part of translatable page "Add FEM equation tutorial") |
||
(39 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
<languages/> |
<languages/> |
||
<translate> |
<translate> |
||
<!--T:1--> |
<!--T:1--> |
||
{{TutorialInfo |
{{TutorialInfo |
||
|Topic= |
|Topic=Add FEM Equation |
||
|Level= |
|Level=Advanced |
||
|Time= |
|Time=1 day |
||
|Author=[[User:JohnWang|JohnWang]] |
|Author=[[User:JohnWang|JohnWang]] |
||
|FCVersion=0.19 |
|FCVersion=0.19 |
||
|Files= |
|||
}} |
}} |
||
== Introduction == <!--T:28--> |
|||
<!--T:2--> |
<!--T:2--> |
||
In this tutorial we are going to add the '''Flow''' equation to FreeCAD and implement support for elmer solver. Please make sure you have read and understood [[Extend_FEM_Module| |
In this tutorial we are going to add the '''Flow''' equation to FreeCAD and implement support for the elmer solver. Please make sure you have read and understood [[Extend_FEM_Module|Extend FEM Module]] before reading this tutorial. |
||
<!--T:3--> |
<!--T:3--> |
||
Line 19: | Line 21: | ||
* '''New equation object'''. Adding a concrete document object representing the elmer specific equation. |
* '''New equation object'''. Adding a concrete document object representing the elmer specific equation. |
||
* '''Extend solver object'''. Adding support for the new equation to the solver object of elmer. |
* '''Extend solver object'''. Adding support for the new equation to the solver object of elmer. |
||
* '''Extend |
* '''Extend writer object'''. Extending the analysis export of elmer to support the new equation type. |
||
* '''Gui tool to create a equation'''. Access the new equation function through workbench Gui. |
* '''Gui tool to create a equation'''. Access the new equation function through workbench Gui. |
||
== New |
== New equation type == <!--T:4--> |
||
<!--T:29--> |
|||
In this step we are going to modify the following file: |
|||
</translate> |
|||
* {{FileName|src/Mod/Fem/femsolver/equationbase.py}} |
|||
<translate> |
|||
<!--T:30--> |
|||
In this step we are going to modify the following files: |
|||
The equation type is shared among all equation objects of the different solver. Each type has a string specifier (e.g. "Heat") and a dedicated command that adds the equation to the selected solver. This allows for a simpler GUI where we have only one button for the heat equation which is used for all supported solver. |
|||
<!--T:31--> |
|||
* src/Mod/Fem/femsolver/equationbase.py |
|||
First add the new equation to the {{Incode|equationbase.py}} module. Each equation requires two classes. A document proxy and a view proxy. Those two classes will later be used as base classes for the Elmer specific equation classes. Just copy-paste them from an existing equation type and adjust the icon path inside {{Incode|getIcon(self)}} of the view proxy. |
|||
</translate> |
|||
The equation type is shared among all equation objects of the different solver. Each type has a string specifier (e.g. "Heat") and a dedicated command that adds the equation to the selected solver. This allows for a simpler GUI where we have only one button for the heat equation which is used for all supported solver. |
|||
{{Code|code= |
|||
class FlowProxy(BaseProxy): |
|||
First add the new equation to the {{incode|equationbase.py}} module. Each equation requires two classes. A document proxy and a view proxy. Those two classes will later be used as base classes for the Elmer specific equation classes. Just copy-paste them from an existing equation type and adjust the icon path inside getIcon(self) of the view proxy. |
|||
<pre>class FlowProxy(BaseProxy): |
|||
pass |
pass |
||
class FlowViewProxy(BaseViewProxy): |
class FlowViewProxy(BaseViewProxy): |
||
def getIcon(self): |
def getIcon(self): |
||
return |
return ":/icons/FEM_EquationFlow.svg" |
||
}} |
|||
</pre> |
|||
<translate> |
|||
== New Elmer's |
== New Elmer's equation object == <!--T:12--> |
||
<!--T:13--> |
<!--T:13--> |
||
In this step we are going to implement the document object. We need to add a new flow.py file at: |
In this step we are going to implement the document object. We need to add a new {{Incode|flow.py}} file at: |
||
</translate> |
</translate> |
||
* src/Mod/Fem/femsolver/elmer/equations/flow.py |
* {{FileName|src/Mod/Fem/femsolver/elmer/equations/flow.py}} |
||
<translate> |
<translate> |
||
<!--T:14--> |
<!--T:14--> |
||
and modify the following |
and modify the following files: |
||
</translate> |
</translate> |
||
* src/Mod/Fem/ObjectsFem.py |
* {{FileName|src/Mod/Fem/ObjectsFem.py}} |
||
* src/Mod/Fem/CMakeLists.txt |
* {{FileName|src/Mod/Fem/CMakeLists.txt}} |
||
<translate> |
<translate> |
||
<!--T:15--> |
<!--T:15--> |
||
Let's start with adding the new flow.py file. This file can be copied from an existing equation |
Let's start with adding the new {{Incode|flow.py}} file. This file can be copied from an existing equation. |
||
=== Keywords === <!--T:32--> |
|||
<!--T:33--> |
|||
* If the new equation only supports keywords for '''linear''' systems copy the {{Incode|femsolver/elmer/equations/elasticity.py}} module. |
|||
* If the new equation supports keywords for both '''linear''' and '''non-linear''' systems, copy {{Incode|femsolver/elmer/equations/heat.py}}. |
|||
<!--T:34--> |
|||
The flow equation in Elmer is a potentially non-linear equation. This means that we are going to base our work on {{Incode|heat.py}}. |
|||
=== Editing files === <!--T:35--> |
|||
<!--T:16--> |
<!--T:16--> |
||
After copying {{ |
After copying {{Incode|heat.py}} to {{Incode|flow.py}}, adjust {{Incode|flow.py}} in these locations: |
||
* the name argument of the {{Incode|create}} module function, |
|||
* the base classes of the {{Incode|Proxy}} class, |
|||
* the {{Incode|Type}} attribute of the {{Incode|Proxy}} class, |
|||
* the {{Incode|ViewProxy}} classes. |
|||
</translate> |
|||
</translate> |
|||
def create(doc, name="'''Flow'''"): |
|||
{{Code|code= |
|||
def create(doc, name="'''Flow'''"): |
|||
return femutils.createObject( |
return femutils.createObject( |
||
doc, name, Proxy, ViewProxy) |
doc, name, Proxy, ViewProxy) |
||
Line 72: | Line 96: | ||
class Proxy(nonlinear.Proxy, equationbase.'''Flow'''Proxy): |
class Proxy(nonlinear.Proxy, equationbase.'''Flow'''Proxy): |
||
Type = |
Type = "Fem::EquationElmer'''Flow'''" |
||
def __init__(self, obj): |
def __init__(self, obj): |
||
Line 80: | Line 104: | ||
class ViewProxy(nonlinear.ViewProxy, equationbase.'''Flow'''ViewProxy): |
class ViewProxy(nonlinear.ViewProxy, equationbase.'''Flow'''ViewProxy): |
||
pass |
pass |
||
}} |
|||
<translate> |
<translate> |
||
Then you need to change the properties added via the {{incode|obj.addProperty(..)}} function to those needed by the equation. |
|||
<!--T:36--> |
|||
Then you need to change the properties added via the {{Incode|obj.addProperty(..)}} function to those needed by the equation. |
|||
<!--T:17--> |
<!--T:17--> |
||
Line 87: | Line 114: | ||
<!--T:27--> |
<!--T:27--> |
||
Finally one has to register a '''makeEquationFlow''' definition in {{ |
Finally one has to register a '''makeEquationFlow''' definition in {{Incode|src/Mod/Fem/ObjectsFem.py}} by duplicating an available entry. |
||
<!--T:18--> |
<!--T:18--> |
||
FreeCAD uses '''make''' to build the program. So we need to register the new module file ({{ |
FreeCAD uses '''make''' to build the program. So we need to register the new module file ({{Incode|flow.py}}) in {{Incode|src/Mod/Fem/CMakeLists.txt}} the way described in [https://www.freecadweb.org/wiki/Extend_FEM_Module Extend FEM Module]. The suitable lists can be easily found by searching for existing equation modules files of Elmer. |
||
== Extend Solver Object == <!--T:19--> |
== Extend Solver Object == <!--T:19--> |
||
Line 96: | Line 123: | ||
<!--T:20--> |
<!--T:20--> |
||
In this step we are going to modify the following file: |
In this step we are going to modify the following file: |
||
</translate> |
</translate> |
||
* src/Mod/Fem/femsolver/elmer/solver.py |
* {{FileName|src/Mod/Fem/femsolver/elmer/solver.py}} |
||
<translate> |
<translate> |
||
<!--T:21--> |
<!--T:21--> |
||
Right now we made FreeCAD aware that there is a new type of equation and even added a command that adds this equation to the selected solver object. We also implemented a concrete equation object for Elmer. Whats left to do now is to make the connection between Elmer and the flow equation. This must be done directly in Elmer solver object. |
Right now we made FreeCAD aware that there is a new type of equation and even added a command that adds this equation to the selected solver object. We also implemented a concrete equation object for Elmer. Whats left to do now is to make the connection between Elmer and the flow equation. This must be done directly in Elmer solver object. |
||
<!--T:22--> |
<!--T:22--> |
||
Register the module in which we just implemented our new equation object ({{ |
Register the module in which we just implemented our new equation object ({{Incode|flow.py}}) with the equation specifier from step 1 ("Flow") in the {{Incode|_EQUATIONS}} list in {{Incode|elmer/solver.py}}. |
||
</translate> |
</translate> |
||
{{Code|code= |
|||
<pre> |
|||
from .equations import electrostatic |
from .equations import electrostatic |
||
+from .equations import flow |
+from .equations import flow |
||
Line 112: | Line 142: | ||
_EQUATIONS = { |
_EQUATIONS = { |
||
"Heat": heat, |
|||
"Elasticity": elasticity, |
|||
+ |
+ "Flow": flow, |
||
} |
} |
||
}} |
|||
</pre> |
|||
<translate> |
<translate> |
||
== Extend |
== Extend writer object == <!--T:23--> |
||
<!--T:24--> |
<!--T:24--> |
||
In this step we are going to modify the following file: |
In this step we are going to modify the following file: |
||
</translate> |
</translate> |
||
* src/Mod/Fem/femsolver/elmer/writer.py |
* {{FileName|src/Mod/Fem/femsolver/elmer/writer.py}} |
||
<translate> |
<translate> |
||
<!--T:25--> |
<!--T:25--> |
||
This file contains the {{Incode|Writer}} class which exports the analysis into Elmer SIF format. |
|||
<!--T:26--> |
<!--T:26--> |
||
For every supported equation there are two main methods handling the export of the respective equation. Just copy all of them from an existing equation and adjust them to your needs. |
For every supported equation there are two main methods handling the export of the respective equation. Just copy all of them from an existing equation and adjust them to your needs. |
||
</translate> |
|||
* _getFlowSolver |
|||
* _handleFlow |
|||
</translate> |
|||
* {{Incode|_getFlowSolver}} |
|||
* {{Incode|_handleFlow}} |
|||
<translate> |
<translate> |
||
You need to register _handleFlow method inside class Writer: |
|||
<!--T:37--> |
|||
</translate> |
|||
You need to register the {{Incode|_handleFlow}} method inside the {{Incode|Writer}} class: |
|||
</translate> |
|||
<pre> |
|||
{{Code|code= |
|||
class Writer(object): |
class Writer(object): |
||
... |
... |
||
Line 149: | Line 182: | ||
... |
... |
||
}} |
|||
</pre> |
|||
<translate> |
<translate> |
||
_handleFlow can control a series of other detailed methods. Our flow equation uses the following detailed methods:: |
|||
</translate> |
|||
* _handleFlowConstants |
|||
* _handleFlowMaterial |
|||
* _handleFlowInitialVelocity |
|||
* _handleFlowBndConditions |
|||
* _handleFlowEquation |
|||
<!--T:38--> |
|||
We now finished the function part of the new equation. Next we'll connect the new equation through the GUI. |
|||
{{Incode|_handleFlow}} can control a series of other detailed methods. Our flow equation uses the following detailed methods: |
|||
{{clear}} |
|||
[[Category:FEM{{#translation:}}]] |
|||
</translate> |
|||
== Gui tool to create an equation == <!--T:4--> |
|||
* {{Incode|_handleFlowConstants}} |
|||
In this step we are going to modify the following files: |
|||
* {{Incode|_handleFlowMaterial}} |
|||
* src/Mod/Fem/femcommands/commands.py |
|||
* {{Incode|_handleFlowInitialVelocity}} |
|||
* src/Mod/Fem/Gui/Workbench.cpp |
|||
* {{Incode|_handleFlowBndConditions}} |
|||
* src/Mod/Fem/Gui/Resources/Fem.qrc |
|||
* {{Incode|_handleFlowEquation}} |
|||
We also need to create an Icon file: |
|||
* src/Mod/Fem/Gui/Resources/icons/FEM_EquationFlow.svg |
|||
We need a FEM_EquationFlow.svg file and has to be put into {{incode|/Gui/Resources/icons/}}. The new FEM_EquationFlow.svg icon has to be registered for the GUI-button with {{incode|<file>icons/FEM_EquationFlow.svg</file>}} in {{incode|Fem.qrc}} (in {{incode|/Gui/Resources/}}). |
|||
<!--T:9--> |
|||
<translate> |
<translate> |
||
In addition to those base classes we have to create a new command class that adds a flow equation to the selected solver object. |
|||
Next, the command/equation has to be added to the {{incode|femcommands/commands.py}} module. Just copy an existing command and adjust the icon, menu text and tool-tip in __init__(self). '''Don't forget''' to register the command at the bottom of the module file by using the addCommand(...) method. Please see the discussion in the forum at https://forum.freecadweb.org/viewtopic.php?f=18&t=46693&start=10#p402004 if icons are involved. |
|||
</translate> |
|||
<pre> |
|||
class _EquationFlow(CommandManager): |
|||
"The FEM_EquationFlow command definition" |
|||
<!--T:39--> |
|||
def __init__(self): |
|||
We now finished the function part of the new equation. Next we'll connect the new equation through the GUI. |
|||
super(_EquationFlow, self).__init__() |
|||
self.menuetext = "Flow equation" |
|||
self.tooltip = "Creates a FEM equation for flow" |
|||
self.is_active = "with_solver_elmer" |
|||
self.do_activated = "add_obj_on_gui_selobj_noset_edit" |
|||
... |
|||
FreeCADGui.addCommand( |
|||
"FEM_EquationFlow", |
|||
_EquationFlow() |
|||
) |
|||
</pre> |
|||
== Gui tool to create an equation == <!--T:40--> |
|||
<!--T:41--> |
|||
<translate> |
|||
We have just created a new equation class. To access it from the FEM GUI, we need to create a button and link it to the new equation class. Here is a tutorial: [[Add_Button_to_FEM_Toolbar_Tutorial|Add Button to FEM Toolbar Tutorial]]. |
|||
Our newly created command still needs to be made accessible via the GUI of the FEM workbench. The workbench has several toolbars and menus. We will add it on to both the '''solve''' toolbar and the '''solve''' menu. |
|||
To add it to the '''solve''' toolbar, search for the following code snippet in {{incode|/Gui/Workbench.cpp}} and add the new command to the rest of the equation commands. |
|||
</translate> |
|||
<pre> |
|||
Gui::ToolBarItem* solve = new Gui::ToolBarItem(root); |
|||
solve->setCommand("Solve"); |
|||
*solve << "FEM_SolverCalculixCxxtools" |
|||
<< "FEM_SolverCalculiX" |
|||
<< "FEM_SolverElmer" |
|||
<< "Separator" |
|||
<< "FEM_EquationElasticity" |
|||
<< "FEM_EquationElectrostatic" |
|||
+ << "FEM_EquationFlow" |
|||
<< "FEM_EquationFluxsolver" |
|||
<< "FEM_EquationElectricforce" |
|||
<< "FEM_EquationHeat" |
|||
<< "Separator" |
|||
<< "FEM_SolverControl" |
|||
<< "FEM_SolverRun"; |
|||
</pre> |
|||
<translate> |
|||
To add the '''flow''' equation command to the '''solve''' menu of the FEM workbench, search for the following code snippet in {{incode|Workbench.cpp}}. |
|||
</translate> |
</translate> |
||
[[Category:FEM{{#translation:}}]] |
|||
<pre> |
|||
[[Category:Developer Documentation{{#translation:}}]] |
|||
Gui::MenuItem* solve = new Gui::MenuItem; |
|||
root->insertItem(item, solve); |
|||
solve->setCommand("&Solve"); |
|||
*solve << "FEM_SolverCalculixCxxtools" |
|||
<< "FEM_SolverCalculiX" |
|||
<< "FEM_SolverElmer" |
|||
<< "FEM_SolverZ88" |
|||
<< "Separator" |
|||
<< "FEM_EquationElasticity" |
|||
<< "FEM_EquationElectrostatic" |
|||
+ << "FEM_EquationFlow" |
|||
<< "FEM_EquationFluxsolver" |
|||
<< "FEM_EquationElectricforce" |
|||
<< "FEM_EquationHeat" |
|||
<< "Separator" |
|||
<< "FEM_SolverControl" |
|||
<< "FEM_SolverRun"; |
|||
</pre> |
Revision as of 14:34, 3 November 2021
Tutorial |
Topic |
---|
Add FEM Equation |
Level |
Advanced |
Time to complete |
1 day |
Authors |
JohnWang |
FreeCAD version |
0.19 |
Example files |
None |
See also |
None |
Introduction
In this tutorial we are going to add the Flow equation to FreeCAD and implement support for the elmer solver. Please make sure you have read and understood Extend FEM Module before reading this tutorial.
The task can be split into five parts:
- New equation type. This step must only be done if the equation doesn't exist in FreeCAD yet (as opposed to a equation that is already in FreeCAD but not supported by the target solver).
- New equation object. Adding a concrete document object representing the elmer specific equation.
- Extend solver object. Adding support for the new equation to the solver object of elmer.
- Extend writer object. Extending the analysis export of elmer to support the new equation type.
- Gui tool to create a equation. Access the new equation function through workbench Gui.
New equation type
In this step we are going to modify the following file:
- src/Mod/Fem/femsolver/equationbase.py
The equation type is shared among all equation objects of the different solver. Each type has a string specifier (e.g. "Heat") and a dedicated command that adds the equation to the selected solver. This allows for a simpler GUI where we have only one button for the heat equation which is used for all supported solver.
First add the new equation to the equationbase.py
module. Each equation requires two classes. A document proxy and a view proxy. Those two classes will later be used as base classes for the Elmer specific equation classes. Just copy-paste them from an existing equation type and adjust the icon path inside getIcon(self)
of the view proxy.
class FlowProxy(BaseProxy):
pass
class FlowViewProxy(BaseViewProxy):
def getIcon(self):
return ":/icons/FEM_EquationFlow.svg"
New Elmer's equation object
In this step we are going to implement the document object. We need to add a new flow.py
file at:
- src/Mod/Fem/femsolver/elmer/equations/flow.py
and modify the following files:
- src/Mod/Fem/ObjectsFem.py
- src/Mod/Fem/CMakeLists.txt
Let's start with adding the new flow.py
file. This file can be copied from an existing equation.
Keywords
- If the new equation only supports keywords for linear systems copy the
femsolver/elmer/equations/elasticity.py
module. - If the new equation supports keywords for both linear and non-linear systems, copy
femsolver/elmer/equations/heat.py
.
The flow equation in Elmer is a potentially non-linear equation. This means that we are going to base our work on heat.py
.
Editing files
After copying heat.py
to flow.py
, adjust flow.py
in these locations:
- the name argument of the
create
module function, - the base classes of the
Proxy
class, - the
Type
attribute of theProxy
class, - the
ViewProxy
classes.
def create(doc, name="'''Flow'''"):
return femutils.createObject(
doc, name, Proxy, ViewProxy)
class Proxy(nonlinear.Proxy, equationbase.'''Flow'''Proxy):
Type = "Fem::EquationElmer'''Flow'''"
def __init__(self, obj):
super(Proxy, self).__init__(obj)
obj.Priority = 10
class ViewProxy(nonlinear.ViewProxy, equationbase.'''Flow'''ViewProxy):
pass
Then you need to change the properties added via the obj.addProperty(..)
function to those needed by the equation.
At the moment of writing this tutorial Elmer flow equation doesn't have any special properties. See Elmer elasticity equation for an example with properties.
Finally one has to register a makeEquationFlow definition in src/Mod/Fem/ObjectsFem.py
by duplicating an available entry.
FreeCAD uses make to build the program. So we need to register the new module file (flow.py
) in src/Mod/Fem/CMakeLists.txt
the way described in Extend FEM Module. The suitable lists can be easily found by searching for existing equation modules files of Elmer.
Extend Solver Object
In this step we are going to modify the following file:
- src/Mod/Fem/femsolver/elmer/solver.py
Right now we made FreeCAD aware that there is a new type of equation and even added a command that adds this equation to the selected solver object. We also implemented a concrete equation object for Elmer. Whats left to do now is to make the connection between Elmer and the flow equation. This must be done directly in Elmer solver object.
Register the module in which we just implemented our new equation object (flow.py
) with the equation specifier from step 1 ("Flow") in the _EQUATIONS
list in elmer/solver.py
.
from .equations import electrostatic
+from .equations import flow
...
_EQUATIONS = {
"Heat": heat,
"Elasticity": elasticity,
+ "Flow": flow,
}
Extend writer object
In this step we are going to modify the following file:
- src/Mod/Fem/femsolver/elmer/writer.py
This file contains the Writer
class which exports the analysis into Elmer SIF format.
For every supported equation there are two main methods handling the export of the respective equation. Just copy all of them from an existing equation and adjust them to your needs.
_getFlowSolver
_handleFlow
You need to register the _handleFlow
method inside the Writer
class:
class Writer(object):
...
def write(self):
...
self._handleFlow()
...
_handleFlow
can control a series of other detailed methods. Our flow equation uses the following detailed methods:
_handleFlowConstants
_handleFlowMaterial
_handleFlowInitialVelocity
_handleFlowBndConditions
_handleFlowEquation
We now finished the function part of the new equation. Next we'll connect the new equation through the GUI.
Gui tool to create an equation
We have just created a new equation class. To access it from the FEM GUI, we need to create a button and link it to the new equation class. Here is a tutorial: Add Button to FEM Toolbar Tutorial.