Add FEM Constraint Tutorial/ro: Difference between revisions

From FreeCAD Documentation
No edit summary
(Updating to match new version of source page)
 
(39 intermediate revisions by 3 users not shown)
Line 1: Line 1:
<languages/>
<languages/>

{{TutorialInfo
{{TutorialInfo/ro
|Topic=
|Topic=
|Level=
|Level=
Line 8: Line 9:
|Files=
|Files=
}}
}}

== Introduction ==


În acest tutorial vom adăuga constrângerea vitezei fluxului la FreeCAD și vom implementa suportul pentru elmer solver. Asigurați-vă că ați citit și ați înțeles [[Extend_FEM_Module|Extend FEM Module]] înainte de a citi acest tutorial.
În acest tutorial vom adăuga constrângerea vitezei fluxului la FreeCAD și vom implementa suportul pentru elmer solver. Asigurați-vă că ați citit și ați înțeles [[Extend_FEM_Module|Extend FEM Module]] înainte de a citi acest tutorial.


<div class="mw-translate-fuzzy">
Acest tutorial acoperă doar modul de implementare a constrângerilor în Python. Spre deosebire de constrângerile solver și ecuații, urmați structura modulului FEM clasic. Adică toate modulele unei constrângeri au loc în pachetul PyObjects sau PyGui.
Acest tutorial acoperă doar modul de implementare a constrângerilor în Python. Spre deosebire de constrângerile solver și ecuații, urmați structura modulului FEM clasic. Adică toate modulele unei constrângeri au loc în pachetul PyObjects sau PyGui.
</div>


<span id="Summary"></span>
== Sumar ==
== Sumar ==


# '''Create document object:''' The docuemnt object that resides inside the analysis and though which the constraint can be parametrized and attached to boundaries.
# '''Create document object:''' Obiectul documentului care se află în analiză și în care constrângerea poate fi parametrizată și legată de limite.
# '''Create GUI command:''' Add a command to the FEM workbench that adds a flow constriant to the active analysis.
# '''Create GUI command:''' Adăugați o comandă la atelierul FEM care adaugă o constrângere a fluxului la analiza activă.
# '''Create a task panel:''' The task panel is nessecary to allow the user to set the boundaries at which he wants to set the velocity constraint. It also makes entering the paramters a little more user friendly.
# '''Create a task panel:''' Panoul de sarcini este necesar pentru a permite utilizatorului definească limitele la care dorește definească constrângerea de viteză. Acest lucru face ca intrarea parametrilor fie mai ușor de utilizat.
# '''Extend elmers writer:''' Add support for the new constraint to elmer by extinging its sif file exporter.
# '''Extend elmers writer:''' Adăugați suport pentru noua constrângere modulul Elmer FEM solver prin dezactivarea exportatorului de fișiere sif.

<span id="Create_document_object"></span>
== Crearea Documentului Obiect ==

În acest pas vom modifica următoarele fișiere:
* {{FileName|src/Mod/Fem/CMakeLists.txt}}
* {{FileName|src/Mod/Fem/App/CMakeLists.txt}}
* {{FileName|src/Mod/Fem/ObjectsFem.py}}

și adăugați următoarele fișiere:
* {{FileName|src/Mod/Fem/femobjects/constraint_flowvelocity.py}}
* {{FileName|src/Mod/Fem/femviewprovider/view_constraint_flowvelocity.py}}


Un document proxy și o vedere proxy sunt necesare pentru noua constrângere. Acestea se află în module separate. Proxy documentul în PyObjects și vederea proxy în PyGui. Trebuie doar să copiați modulele dintr-o constrângere existentă, de ex.
== Create Document Object ==
* {{FileName|femobjects/constraint_selfweight.py}}
* {{FileName|femviewprovider/view_constraint_selfweight.py}}


Reglați tipul de variabilă și proprietățile la nevoile dvs. Proxy-ul documentului al constrângerii fluxului arată după cum urmează:
In this step we are going to modify the following files:
* src/Mod/Fem/CMakeLists.txt
* src/Mod/Fem/App/CMakeLists.txt
* src/Mod/Fem/ObjectsFem.py
and add the following files:
* src/Mod/Fem/PyObjects/_FemConstraintFlowVelocity.py
* src/Mod/Fem/PyGui/_ViewProviderFemConstraintFlowVelocity.py


{{Code|code=
A document proxy and a view proxy are required for the new constraint. Those reside in separate modules. The document proxy in PyObjects and the view proxy in PyGui. Just copy the modules from an existing constraint e.g.
class Proxy(FemConstraint.Proxy):
* PyObjects/_FemConstraintSelfWeight.py
Type = "Fem::ConstraintFlowVelocity"
* PyGui/_ViewProviderFemConstraintSelfWeight.py
Adjust the Type variable and the properties to your needs. The document proxy of the flow constraint looks like the following:
<pre>class Proxy(FemConstraint.Proxy):
Type = &quot;Fem::ConstraintFlowVelocity&quot;
def __init__(self, obj):
def __init__(self, obj):
super(Proxy, self).__init__(obj)
super(Proxy, self).__init__(obj)
obj.addProperty(
obj.addProperty(
&quot;App::PropertyFloat&quot;, &quot;VelocityX&quot;,
"App::PropertyFloat", "VelocityX",
&quot;Parameter&quot;, &quot;Body heat flux&quot;)
"Parameter", "Body heat flux")
obj.addProperty(
obj.addProperty(
&quot;App::PropertyBool&quot;, &quot;VelocityXEnabled&quot;,
"App::PropertyBool", "VelocityXEnabled",
&quot;Parameter&quot;, &quot;Body heat flux&quot;)
"Parameter", "Body heat flux")
obj.addProperty(
obj.addProperty(
&quot;App::PropertyFloat&quot;, &quot;VelocityY&quot;,
"App::PropertyFloat", "VelocityY",
&quot;Parameter&quot;, &quot;Body heat flux&quot;)
"Parameter", "Body heat flux")
obj.addProperty(
obj.addProperty(
&quot;App::PropertyBool&quot;, &quot;VelocityYEnabled&quot;,
"App::PropertyBool", "VelocityYEnabled",
&quot;Parameter&quot;, &quot;Body heat flux&quot;)
"Parameter", "Body heat flux")
obj.addProperty(
obj.addProperty(
&quot;App::PropertyFloat&quot;, &quot;VelocityZ&quot;,
"App::PropertyFloat", "VelocityZ",
&quot;Parameter&quot;, &quot;Body heat flux&quot;)
"Parameter", "Body heat flux")
obj.addProperty(
obj.addProperty(
&quot;App::PropertyBool&quot;, &quot;VelocityZEnabled&quot;,
"App::PropertyBool", "VelocityZEnabled",
&quot;Parameter&quot;, &quot;Body heat flux&quot;)
"Parameter", "Body heat flux")
obj.addProperty(
obj.addProperty(
&quot;App::PropertyBool&quot;, &quot;NormalToBoundary&quot;,
"App::PropertyBool", "NormalToBoundary",
&quot;Parameter&quot;, &quot;Body heat flux&quot;)</pre>
"Parameter", "Body heat flux")
}}
The module containing the view proxy might look a little more complicated. But for now just adjust the icon path. We are going to come back to this file in later steps of the tutorial.

<pre>class ViewProxy(FemConstraint.ViewProxy):
Modulul care conține proxy-ul ar putea părea puțin mai complicat. Dar pentru moment ajustați calea pictogramelor. Vom reveni la acest dosar.

{{Code|code=
class ViewProxy(FemConstraint.ViewProxy):
def getIcon(self):
def getIcon(self):
return &quot;:/icons/fem-constraint-flow-velocity.svg&quot;</pre>
return ":/icons/fem-constraint-flow-velocity.svg"
}}
Add the two new modules to the build system like descripted in [https://www.freecadweb.org/wiki/Extend_FEM_Module Extend FEM Module]. Locate the correct list be searching for constraint modules.


Adăugați cele două module noi la construirea sistemului descrisă în [https://www.freecadweb.org/wiki/Extend_FEM_Module Extend FEM Module]. Găsiți lista de căutare corectă pentru modulele de constrângere.
As all objects of the FEM workbench the velocity constraint must be registerd in <code>ObjectsFem.py</code>. The following method adds a velocity constraint to the active document. This method will be used by the GUI command to add the constraint. It must be inserted somewhere in <code>ObjectsFem.py</code>.

<pre>def makeConstraintFlowVelocity(name=&quot;FlowVelocity&quot;):
Ca toate obiectele din bancul de lucru FEM, constrângerile de viteză trebuie să fie înregistrate <code>ObjectsFem.py</code>. Următoarea metodă adaugă viteza documentului activ. Această metodă va fi utilizată de comanda GUI pentru a adăuga constrângerea. Trebuie să fie inserat undeva în <code>ObjectsFem.py</code>.
obj = FreeCAD.ActiveDocument.addObject(&quot;Fem::ConstraintPython&quot;, name)

import PyObjects._FemConstraintFlowVelocity
{{Code|code=
PyObjects._FemConstraintFlowVelocity.Proxy(obj)
def makeConstraintFlowVelocity(name="FlowVelocity"):
obj = FreeCAD.ActiveDocument.addObject("Fem::ConstraintPython", name)
import femobjects.constraint_flowvelocity
femobjects.constraint_flowvelocity.Proxy(obj)
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
import PyGui._ViewProviderFemConstraintFlowVelocity
import femviewprovider.view_constraint_flowvelocity
PyGui._ViewProviderFemConstraintFlowVelocity.ViewProxy(obj.ViewObject)
femviewprovider.view_constraint_flowvelocity.ViewProxy(obj.ViewObject)
return obj</pre>
return obj
}}
== Create GUI command ==

<span id="Create_GUI_command"></span>
== Creează o camandă GUI ==

În acest pas vom modifica următoarele fișiere:
* {{FileName|src/Mod/Fem/CMakeLists.txt}}
* {{FileName|src/Mod/Fem/App/CMakeLists.txt}}
* {{FileName|src/Mod/Fem/Gui/Workbench.cpp}}

și adăugați următorul fișier nou:
* {{FileName|src/Mod/Fem/femobjects/constraint_flowvelocity.py}}


Comanda permite utilizatorului să adauge constrângerea la analiza activă. Trebuie doar să copiați o comandă dintr-o constrângere existentă. Commands reside in the <code>PyGui</code> package. Ajustați resursele și efectuați metoda numită Activat la nevoile dvs. Utilizați, de asemenea, o comandă diferită id in the addCommand apel în partea de jos a modulului. Următoarea clasă este clasa constrângerii vitezei.
In this step we are going to modify the following files:
* src/Mod/Fem/CMakeLists.txt
* src/Mod/Fem/App/CMakeLists.txt
* src/Mod/Fem/Gui/Workbench.cpp
and add the following new file:
* src/Mod/Fem/PyGui/_CommandFemConstraintFlowVelocity.py


{{Code|code=
The command allows the user to actually add the constraint to the active analysis. Just copy a command from an existing constraint. Commands reside in the <code>PyGui</code> package. Adjust the resources attribute and the make method called in Activated to your needs. Also use a different command id in the addCommand call on the bottom of the module. The following class is the command class of the velocity constraint.
<pre>class Command(FemCommands.FemCommands):
class Command(FemCommands.FemCommands):


def __init__(self):
def __init__(self):
Line 91: Line 116:
'Pixmap': 'fem-constraint-flow-velocity',
'Pixmap': 'fem-constraint-flow-velocity',
'MenuText': QtCore.QT_TRANSLATE_NOOP(
'MenuText': QtCore.QT_TRANSLATE_NOOP(
&quot;FEM_ConstraintFlowVelocity&quot;,
"FEM_ConstraintFlowVelocity",
&quot;Constraint Velocity&quot;),
"Constraint Velocity"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP(
'ToolTip': QtCore.QT_TRANSLATE_NOOP(
&quot;FEM_ConstraintFlowVelocity&quot;,
"FEM_ConstraintFlowVelocity",
&quot;Creates a FEM constraint body heat flux&quot;)}
"Creates a FEM constraint body heat flux")}
self.is_active = 'with_analysis'
self.is_active = 'with_analysis'


def Activated(self):
def Activated(self):
App.ActiveDocument.openTransaction(
App.ActiveDocument.openTransaction(
&quot;Create FemConstraintFlowVelocity&quot;)
"Create FemConstraintFlowVelocity")
Gui.addModule(&quot;ObjectsFem&quot;)
Gui.addModule("ObjectsFem")
Gui.doCommand(
Gui.doCommand(
&quot;FemGui.getActiveAnalysis().Member += &quot;
"FemGui.getActiveAnalysis().Member += "
&quot;[ObjectsFem.makeConstraintFlowVelocity()]&quot;)
"[ObjectsFem.makeConstraintFlowVelocity()]")


Gui.addCommand('FEM_AddConstraintFlowVelocity', Command())</pre>
Gui.addCommand('FEM_AddConstraintFlowVelocity', Command())
}}
Add the new command file to the build system as decripted in [https://www.freecadweb.org/wiki/Extend_FEM_Module Extend FEM Module]. Locate the correct list be searching for existing command modules.

Adăugați noua comandă în sistem așa cum este încorporată [https://www.freecadweb.org/wiki/Extend_FEM_Module Extend FEM Module]. Identificați lista corectă pentru a căuta modulele de comandă existente.

Puneți o comandă în Gui/Workbench.cpp pentru a o adăuga în bara de instrumente și în meniu. Căutați o constrângere existentă din aceeași categorie ca cea nouă (de exemplu, Flow) copiați-o și adaptați id-ul comenzii. Acest lucru ar trebui făcut de două ori. Odată pentru meniu și din nou pentru bara de instrumente.

<span id="Create_a_task_panel"></span>
== Creara Task Panel ==


În acest pas vom modifica următorul fișier:
Put the command into Gui/Workbench.cpp to add it to the toolbar and menu. Search for an existing constraint of the same category as the new one (e.g. Flow) copy-paste it and adjust the command id. This should be done two times. Once for the menu and again for the toolbar.
* {{FileName|src/Mod/Fem/femviewprovider/view_constraint_flowvelocity.py}}


În obiectele de constrângere FreeCAD beneficiați foarte mult de panourile de sarcini. Tsolicită panourile pot utiliza mai multe widget-uri de intrare mai puternice care expun unitatea de valori introduse direct către utilizator. Constrângerea de viteză presupune chiar utilizarea unui task panel(panou de sarcini), deoarece un panou de sarcini este singura modalitate de a specifica fața pe care trebuie aplicată constrângerea.
== Create a Task Panel ==


Localizarea modulului în care sunt implementate panourile de sarcini nu este strict definită. Pentru constrângerea de viteză, vom pune doar panoul de sarcini în același modul pe care îl punem proxy-ul de vizualizare. Panoul de sarcini este destul de complicat. Folosește FemSolectionWidgets.BoundarySelector(). Acesta este modul în care widget-ul permite utilizatorului să selecteze limitele pe care va fi aplicată constrângerea. În plus față de acest widget, acesta generează un altul prin încărcarea unui fișier ui specific creat pentru constrângerea de viteză. Prin intermediul acestui widget se poate specifica vectorul de viteză.
In this step we are going to modify the following file:
* src/Mod/Fem/PyGui/_ViewProviderFemConstraintFlowVelocity.py
In FreeCAD constraint objects benefit greatly from task panels. Task panels can make use of more powerful input widgets which expose the unit of entered values directely to the user. The velocity constraint even requires the use of a task panel since a task panel is the only way of specifieing the face(s) on which the constraint shall be applied.


Majoritatea timpului ar trebui să fie suficient, trebuie doar să utilizați acest fișier (în schimbul TaskPanelFemFlowVelocity.ui) și adjust _initParamWidget() la fel ca _applyWidgetChanges(). Dacă noua constrângere necesită ca referințe corpuri în loc de limite, pur și simplu înlocuiți obeictul BoundarySelector cu SolidSelector.
The location of the module in which task panels are implemented is not strictely defined. For the velocity constraint we are just going to put the task panel in the same module we put the view proxy. The task panel is quite complicated. It makes use of the FemSolectionWidgets.BoundarySelector(). Thats a qt widget which allows the user to select the boundaries on which the constraint shall be applied. In addition to this widget it generates another one by loading a ui file specifically created for the velocity constraint. Via this widget the velocity vector can be specified.


{{Code|code=
Most of the time is should be sufficient to just copy this class, use a suitable ui file (instead of TaskPanelFemFlowVelocity.ui) and adjust _initParamWidget() as well as _applyWidgetChanges(). If the new constraint requires bodies as references instead of boundaries just replace the BoundarySelector object with the SolidSelector.
<pre>class _TaskPanel(object):
class _TaskPanel(object):


def __init__(self, obj):
def __init__(self, obj):
Line 128: Line 159:
self._refWidget.setReferences(obj.References)
self._refWidget.setReferences(obj.References)
self._paramWidget = Gui.PySideUic.loadUi(
self._paramWidget = Gui.PySideUic.loadUi(
App.getHomePath() + &quot;Mod/Fem/PyGui/TaskPanelFemFlowVelocity.ui&quot;)
App.getHomePath() + "Mod/Fem/femviewprovider/TaskPanelFemFlowVelocity.ui")
self._initParamWidget()
self._initParamWidget()
self.form = [self._refWidget, self._paramWidget]
self.form = [self._refWidget, self._paramWidget]
analysis = FemMisc.findAnalysisOfMember(obj)
analysis = FemMisc.findAnalysisOfMember(obj)
self._mesh = FemMisc.getSingleMember(analysis, &quot;Fem::FemMeshObject&quot;)
self._mesh = FemMisc.getSingleMember(analysis, "Fem::FemMeshObject")
self._part = self._mesh.Part if self._mesh is not None else None
self._part = self._mesh.Part if self._mesh is not None else None
self._partVisible = None
self._partVisible = None
Line 168: Line 199:


def _initParamWidget(self):
def _initParamWidget(self):
unit = &quot;m/s&quot;
unit = "m/s"
self._paramWidget.velocityXTxt.setText(
self._paramWidget.velocityXTxt.setText(
str(self._obj.VelocityX) + unit)
str(self._obj.VelocityX) + unit)
Line 185: Line 216:


def _applyWidgetChanges(self):
def _applyWidgetChanges(self):
unit = &quot;m/s&quot;
unit = "m/s"
self._obj.VelocityXEnabled = \
self._obj.VelocityXEnabled = \
not self._paramWidget.velocityXBox.isChecked()
not self._paramWidget.velocityXBox.isChecked()
Line 201: Line 232:
quantity = Units.Quantity(self._paramWidget.velocityZTxt.text())
quantity = Units.Quantity(self._paramWidget.velocityZTxt.text())
self._obj.VelocityZ = float(quantity.getValueAs(unit))
self._obj.VelocityZ = float(quantity.getValueAs(unit))
self._obj.NormalToBoundary = self._paramWidget.normalBox.isChecked()</pre>
self._obj.NormalToBoundary = self._paramWidget.normalBox.isChecked()
}}
The view proxy must be extended to support the task panel we just implemented. The following extended view proxy opens the task panel when the user makes a double click on the constraint object in the tree view.

<pre>class ViewProxy(FemConstraint.ViewProxy):
Proxy-ul de vizualizare trebuie extins pentru a sprijini panoul de sarcini pe care tocmai l-am implementat. Următoarea vizualizare extinsă deschide panoul de sarcini atunci când utilizatorul face dublu clic pe obiectul constrângere din vizualizarea arborescentă.

{{Code|code=
class ViewProxy(FemConstraint.ViewProxy):


def getIcon(self):
def getIcon(self):
return &quot;:/icons/fem-constraint-flow-velocity.svg&quot;
return ":/icons/fem-constraint-flow-velocity.svg"


def setEdit(self, vobj, mode=0):
def setEdit(self, vobj, mode=0):
Line 219: Line 254:
Gui.Control.closeDialog()
Gui.Control.closeDialog()
Gui.ActiveDocument.setEdit(vobj.Object.Name)
Gui.ActiveDocument.setEdit(vobj.Object.Name)
return True</pre>
return True
}}
== Extend Elmers Writer ==


<span id="Extend_Elmer&#039;s_writer"></span>
In this step we are going to modify the following file:
== Extensia Elmer FEM solver Writer ==
* src/Mod/Fem/FemSolver/Elmer/Writer.py

The writer module contains methods for all equation types. Depending on the type of the constriant, boundary condition, initial condition or body force one has to modifiy different methods. For our flow velocity we have to adjust _handleFlowBndConditions(...).
În acest pas vom modifica următorul fișier:
<pre>def _handleFlowBndConditions(self):
* {{FileName|src/Mod/Fem/femsolver/elmer/writer.py}}
for obj in self._getMember(&quot;Fem::ConstraintFlowVelocity&quot;):

Modulul de scriere conține metode pentru toate tipurile de ecuații. În funcție de tipul de restricție, de condiția de limită, de starea inițială sau de forța corpului, trebuie modificate diferite metode. Pentru viteza fluxului nostru trebuie să ne ajustăm _handleFlowBndConditions(...).

{{Code|code=
def _handleFlowBndConditions(self):
for obj in self._getMember("Fem::ConstraintFlowVelocity"):
if obj.References:
if obj.References:
for name in obj.References[0][1]:
for name in obj.References[0][1]:
if obj.VelocityXEnabled:
if obj.VelocityXEnabled:
velocity = getFromUi(obj.VelocityX, &quot;m/s&quot;, &quot;L/T&quot;)
velocity = getFromUi(obj.VelocityX, "m/s", "L/T")
self._boundary(name, &quot;Velocity 1&quot;, velocity)
self._boundary(name, "Velocity 1", velocity)
if obj.VelocityYEnabled:
if obj.VelocityYEnabled:
velocity = getFromUi(obj.VelocityY, &quot;m/s&quot;, &quot;L/T&quot;)
velocity = getFromUi(obj.VelocityY, "m/s", "L/T")
self._boundary(name, &quot;Velocity 2&quot;, velocity)
self._boundary(name, "Velocity 2", velocity)
if obj.VelocityZEnabled:
if obj.VelocityZEnabled:
velocity = getFromUi(obj.VelocityZ, &quot;m/s&quot;, &quot;L/T&quot;)
velocity = getFromUi(obj.VelocityZ, "m/s", "L/T")
self._boundary(name, &quot;Velocity 3&quot;, velocity)
self._boundary(name, "Velocity 3", velocity)
if obj.NormalToBoundary:
if obj.NormalToBoundary:
self._boundary(name, &quot;Normal-Tangential Velocity&quot;, True)
self._boundary(name, "Normal-Tangential Velocity", True)
self._handled(obj)</pre>
self._handled(obj)
}}




[[Category:FEM{{#translation:}}]]
{{clear}}

Latest revision as of 10:05, 8 May 2023

Tutorial
Topic
Level
Time to complete
Authors
M42kus
FreeCAD version
Example files
See also
None

Introduction

În acest tutorial vom adăuga constrângerea vitezei fluxului la FreeCAD și vom implementa suportul pentru elmer solver. Asigurați-vă că ați citit și ați înțeles Extend FEM Module înainte de a citi acest tutorial.

Acest tutorial acoperă doar modul de implementare a constrângerilor în Python. Spre deosebire de constrângerile solver și ecuații, urmați structura modulului FEM clasic. Adică toate modulele unei constrângeri au loc în pachetul PyObjects sau PyGui.

Sumar

  1. Create document object: Obiectul documentului care se află în analiză și în care constrângerea poate fi parametrizată și legată de limite.
  2. Create GUI command: Adăugați o comandă la atelierul FEM care adaugă o constrângere a fluxului la analiza activă.
  3. Create a task panel: Panoul de sarcini este necesar pentru a permite utilizatorului să definească limitele la care dorește să definească constrângerea de viteză. Acest lucru face ca intrarea parametrilor să fie mai ușor de utilizat.
  4. Extend elmers writer: Adăugați suport pentru noua constrângere modulul Elmer FEM solver prin dezactivarea exportatorului de fișiere sif.

Crearea Documentului Obiect

În acest pas vom modifica următoarele fișiere:

  • src/Mod/Fem/CMakeLists.txt
  • src/Mod/Fem/App/CMakeLists.txt
  • src/Mod/Fem/ObjectsFem.py

și adăugați următoarele fișiere:

  • src/Mod/Fem/femobjects/constraint_flowvelocity.py
  • src/Mod/Fem/femviewprovider/view_constraint_flowvelocity.py

Un document proxy și o vedere proxy sunt necesare pentru noua constrângere. Acestea se află în module separate. Proxy documentul în PyObjects și vederea proxy în PyGui. Trebuie doar să copiați modulele dintr-o constrângere existentă, de ex.

  • femobjects/constraint_selfweight.py
  • femviewprovider/view_constraint_selfweight.py

Reglați tipul de variabilă și proprietățile la nevoile dvs. Proxy-ul documentului al constrângerii fluxului arată după cum urmează:

class Proxy(FemConstraint.Proxy):
    Type = "Fem::ConstraintFlowVelocity"
    def __init__(self, obj):
        super(Proxy, self).__init__(obj)
        obj.addProperty(
            "App::PropertyFloat", "VelocityX",
            "Parameter", "Body heat flux")
        obj.addProperty(
            "App::PropertyBool", "VelocityXEnabled",
            "Parameter", "Body heat flux")
        obj.addProperty(
            "App::PropertyFloat", "VelocityY",
            "Parameter", "Body heat flux")
        obj.addProperty(
            "App::PropertyBool", "VelocityYEnabled",
            "Parameter", "Body heat flux")
        obj.addProperty(
            "App::PropertyFloat", "VelocityZ",
            "Parameter", "Body heat flux")
        obj.addProperty(
            "App::PropertyBool", "VelocityZEnabled",
            "Parameter", "Body heat flux")
        obj.addProperty(
            "App::PropertyBool", "NormalToBoundary",
            "Parameter", "Body heat flux")

Modulul care conține proxy-ul ar putea părea puțin mai complicat. Dar pentru moment ajustați calea pictogramelor. Vom reveni la acest dosar.

class ViewProxy(FemConstraint.ViewProxy):
    def getIcon(self):
        return ":/icons/fem-constraint-flow-velocity.svg"

Adăugați cele două module noi la construirea sistemului descrisă în Extend FEM Module. Găsiți lista de căutare corectă pentru modulele de constrângere.

Ca toate obiectele din bancul de lucru FEM, constrângerile de viteză trebuie să fie înregistrate ObjectsFem.py. Următoarea metodă adaugă viteza documentului activ. Această metodă va fi utilizată de comanda GUI pentru a adăuga constrângerea. Trebuie să fie inserat undeva în ObjectsFem.py.

def makeConstraintFlowVelocity(name="FlowVelocity"):
    obj = FreeCAD.ActiveDocument.addObject("Fem::ConstraintPython", name)
    import femobjects.constraint_flowvelocity
    femobjects.constraint_flowvelocity.Proxy(obj)
    if FreeCAD.GuiUp:
        import femviewprovider.view_constraint_flowvelocity
        femviewprovider.view_constraint_flowvelocity.ViewProxy(obj.ViewObject)
    return obj

Creează o camandă GUI

În acest pas vom modifica următoarele fișiere:

  • src/Mod/Fem/CMakeLists.txt
  • src/Mod/Fem/App/CMakeLists.txt
  • src/Mod/Fem/Gui/Workbench.cpp

și adăugați următorul fișier nou:

  • src/Mod/Fem/femobjects/constraint_flowvelocity.py

Comanda permite utilizatorului să adauge constrângerea la analiza activă. Trebuie doar să copiați o comandă dintr-o constrângere existentă. Commands reside in the PyGui package. Ajustați resursele și efectuați metoda numită Activat la nevoile dvs. Utilizați, de asemenea, o comandă diferită id in the addCommand apel în partea de jos a modulului. Următoarea clasă este clasa constrângerii vitezei.

class Command(FemCommands.FemCommands):

    def __init__(self):
        super(Command, self).__init__()
        self.resources = {
            'Pixmap': 'fem-constraint-flow-velocity',
            'MenuText': QtCore.QT_TRANSLATE_NOOP(
                "FEM_ConstraintFlowVelocity",
                "Constraint Velocity"),
            'ToolTip': QtCore.QT_TRANSLATE_NOOP(
                "FEM_ConstraintFlowVelocity",
                "Creates a FEM constraint body heat flux")}
        self.is_active = 'with_analysis'

    def Activated(self):
        App.ActiveDocument.openTransaction(
            "Create FemConstraintFlowVelocity")
        Gui.addModule("ObjectsFem")
        Gui.doCommand(
            "FemGui.getActiveAnalysis().Member += "
            "[ObjectsFem.makeConstraintFlowVelocity()]")

Gui.addCommand('FEM_AddConstraintFlowVelocity', Command())

Adăugați noua comandă în sistem așa cum este încorporată Extend FEM Module. Identificați lista corectă pentru a căuta modulele de comandă existente.

Puneți o comandă în Gui/Workbench.cpp pentru a o adăuga în bara de instrumente și în meniu. Căutați o constrângere existentă din aceeași categorie ca cea nouă (de exemplu, Flow) copiați-o și adaptați id-ul comenzii. Acest lucru ar trebui făcut de două ori. Odată pentru meniu și din nou pentru bara de instrumente.

Creara Task Panel

În acest pas vom modifica următorul fișier:

  • src/Mod/Fem/femviewprovider/view_constraint_flowvelocity.py

În obiectele de constrângere FreeCAD beneficiați foarte mult de panourile de sarcini. Tsolicită panourile pot utiliza mai multe widget-uri de intrare mai puternice care expun unitatea de valori introduse direct către utilizator. Constrângerea de viteză presupune chiar utilizarea unui task panel(panou de sarcini), deoarece un panou de sarcini este singura modalitate de a specifica fața pe care trebuie aplicată constrângerea.

Localizarea modulului în care sunt implementate panourile de sarcini nu este strict definită. Pentru constrângerea de viteză, vom pune doar panoul de sarcini în același modul pe care îl punem proxy-ul de vizualizare. Panoul de sarcini este destul de complicat. Folosește FemSolectionWidgets.BoundarySelector(). Acesta este modul în care widget-ul permite utilizatorului să selecteze limitele pe care va fi aplicată constrângerea. În plus față de acest widget, acesta generează un altul prin încărcarea unui fișier ui specific creat pentru constrângerea de viteză. Prin intermediul acestui widget se poate specifica vectorul de viteză.

Majoritatea timpului ar trebui să fie suficient, trebuie doar să utilizați acest fișier (în schimbul TaskPanelFemFlowVelocity.ui) și adjust _initParamWidget() la fel ca _applyWidgetChanges(). Dacă noua constrângere necesită ca referințe corpuri în loc de limite, pur și simplu înlocuiți obeictul BoundarySelector cu SolidSelector.

class _TaskPanel(object):

    def __init__(self, obj):
        self._obj = obj
        self._refWidget = FemSelectionWidgets.BoundarySelector()
        # self._refWidget = FemSelectionWidgets.SolidSelector()
        self._refWidget.setReferences(obj.References)
        self._paramWidget = Gui.PySideUic.loadUi(
            App.getHomePath() + "Mod/Fem/femviewprovider/TaskPanelFemFlowVelocity.ui")
        self._initParamWidget()
        self.form = [self._refWidget, self._paramWidget]
        analysis = FemMisc.findAnalysisOfMember(obj)
        self._mesh = FemMisc.getSingleMember(analysis, "Fem::FemMeshObject")
        self._part = self._mesh.Part if self._mesh is not None else None
        self._partVisible = None
        self._meshVisible = None

    def open(self):
        if self._mesh is not None and self._part is not None:
            self._meshVisible = self._mesh.ViewObject.isVisible()
            self._partVisible = self._part.ViewObject.isVisible()
            self._mesh.ViewObject.hide()
            self._part.ViewObject.show()

    def reject(self):
        self._restoreVisibility()
        return True

    def accept(self):
        if self._obj.References != self._refWidget.references():
            self._obj.References = self._refWidget.references()
        self._applyWidgetChanges()
        self._obj.Document.recompute()
        self._restoreVisibility()
        return True

    def _restoreVisibility(self):
        if self._mesh is not None and self._part is not None:
            if self._meshVisible:
                self._mesh.ViewObject.show()
            else:
                self._mesh.ViewObject.hide()
            if self._partVisible:
                self._part.ViewObject.show()
            else:
                self._part.ViewObject.hide()

    def _initParamWidget(self):
        unit = "m/s"
        self._paramWidget.velocityXTxt.setText(
            str(self._obj.VelocityX) + unit)
        self._paramWidget.velocityYTxt.setText(
            str(self._obj.VelocityY) + unit)
        self._paramWidget.velocityZTxt.setText(
            str(self._obj.VelocityZ) + unit)
        self._paramWidget.velocityXBox.setChecked(
            not self._obj.VelocityXEnabled)
        self._paramWidget.velocityYBox.setChecked(
            not self._obj.VelocityYEnabled)
        self._paramWidget.velocityZBox.setChecked(
            not self._obj.VelocityZEnabled)
        self._paramWidget.normalBox.setChecked(
            self._obj.NormalToBoundary)

    def _applyWidgetChanges(self):
        unit = "m/s"
        self._obj.VelocityXEnabled = \
            not self._paramWidget.velocityXBox.isChecked()
        if self._obj.VelocityXEnabled:
            quantity = Units.Quantity(self._paramWidget.velocityXTxt.text())
            self._obj.VelocityX = float(quantity.getValueAs(unit))
        self._obj.VelocityYEnabled = \
            not self._paramWidget.velocityYBox.isChecked()
        if self._obj.VelocityYEnabled:
            quantity = Units.Quantity(self._paramWidget.velocityYTxt.text())
            self._obj.VelocityY = float(quantity.getValueAs(unit))
        self._obj.VelocityZEnabled = \
            not self._paramWidget.velocityZBox.isChecked()
        if self._obj.VelocityZEnabled:
            quantity = Units.Quantity(self._paramWidget.velocityZTxt.text())
            self._obj.VelocityZ = float(quantity.getValueAs(unit))
        self._obj.NormalToBoundary = self._paramWidget.normalBox.isChecked()

Proxy-ul de vizualizare trebuie extins pentru a sprijini panoul de sarcini pe care tocmai l-am implementat. Următoarea vizualizare extinsă deschide panoul de sarcini atunci când utilizatorul face dublu clic pe obiectul constrângere din vizualizarea arborescentă.

class ViewProxy(FemConstraint.ViewProxy):

    def getIcon(self):
        return ":/icons/fem-constraint-flow-velocity.svg"

    def setEdit(self, vobj, mode=0):
        task = _TaskPanel(vobj.Object)
        Gui.Control.showDialog(task)

    def unsetEdit(self, vobj, mode=0):
        Gui.Control.closeDialog()

    def doubleClicked(self, vobj):
        if Gui.Control.activeDialog():
            Gui.Control.closeDialog()
        Gui.ActiveDocument.setEdit(vobj.Object.Name)
        return True

Extensia Elmer FEM solver Writer

În acest pas vom modifica următorul fișier:

  • src/Mod/Fem/femsolver/elmer/writer.py

Modulul de scriere conține metode pentru toate tipurile de ecuații. În funcție de tipul de restricție, de condiția de limită, de starea inițială sau de forța corpului, trebuie modificate diferite metode. Pentru viteza fluxului nostru trebuie să ne ajustăm _handleFlowBndConditions(...).

def _handleFlowBndConditions(self):
    for obj in self._getMember("Fem::ConstraintFlowVelocity"):
        if obj.References:
            for name in obj.References[0][1]:
                if obj.VelocityXEnabled:
                    velocity = getFromUi(obj.VelocityX, "m/s", "L/T")
                    self._boundary(name, "Velocity 1", velocity)
                if obj.VelocityYEnabled:
                    velocity = getFromUi(obj.VelocityY, "m/s", "L/T")
                    self._boundary(name, "Velocity 2", velocity)
                if obj.VelocityZEnabled:
                    velocity = getFromUi(obj.VelocityZ, "m/s", "L/T")
                    self._boundary(name, "Velocity 3", velocity)
                if obj.NormalToBoundary:
                    self._boundary(name, "Normal-Tangential Velocity", True)
            self._handled(obj)