1# -*- coding: utf-8 -*-
2
3#-------------------------------------------------------------------------------
4
5# This file is part of Code_Saturne, a general-purpose CFD tool.
6#
7# Copyright (C) 1998-2021 EDF S.A.
8#
9# This program is free software; you can redistribute it and/or modify it under
10# the terms of the GNU General Public License as published by the Free Software
11# Foundation; either version 2 of the License, or (at your option) any later
12# version.
13#
14# This program is distributed in the hope that it will be useful, but WITHOUT
15# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17# details.
18#
19# You should have received a copy of the GNU General Public License along with
20# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
21# Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
23#-------------------------------------------------------------------------------
24
25"""
26This module contains the following classes:
27- BoundaryConditionsElectricalView
28"""
29
30#-------------------------------------------------------------------------------
31# Standard modules
32#-------------------------------------------------------------------------------
33
34import logging
35
36#-------------------------------------------------------------------------------
37# Third-party modules
38#-------------------------------------------------------------------------------
39
40from code_saturne.Base.QtCore    import *
41from code_saturne.Base.QtGui     import *
42from code_saturne.Base.QtWidgets import *
43
44#-------------------------------------------------------------------------------
45# Application modules import
46#-------------------------------------------------------------------------------
47
48from code_saturne.model.Common import GuiParam
49from code_saturne.Base.QtPage import DoubleValidator, ComboModel, from_qvariant
50
51from code_saturne.Pages.BoundaryConditionsElectricalForm import Ui_BoundaryConditionsElectricalForm
52from code_saturne.model.ElectricalModel import ElectricalModel
53
54from code_saturne.model.LocalizationModel import LocalizationModel, Zone
55from code_saturne.Pages.QMegEditorView import QMegEditorView
56from code_saturne.model.Boundary import Boundary
57from code_saturne.model.NotebookModel import NotebookModel
58
59#-------------------------------------------------------------------------------
60# log config
61#-------------------------------------------------------------------------------
62
63logging.basicConfig()
64log = logging.getLogger("BoundaryConditionsElectricalView")
65log.setLevel(GuiParam.DEBUG)
66
67#-------------------------------------------------------------------------------
68# Main class
69#-------------------------------------------------------------------------------
70
71class BoundaryConditionsElectricalView(QWidget, Ui_BoundaryConditionsElectricalForm):
72    """
73    Boundary condifition for the velocity part
74    """
75    def __init__(self, parent):
76        """
77        Constructor.
78        """
79        QWidget.__init__(self, parent)
80
81        Ui_BoundaryConditionsElectricalForm.__init__(self)
82        self.setupUi(self)
83
84
85    def setup(self, case):
86        """
87        Setup the widget.
88        """
89        self.case = case
90        self.__boundary = None
91        self.__model = ElectricalModel(self.case)
92        self.species_list = []
93        self.notebook = NotebookModel(self.case)
94
95        self.lineEditValuePotElec.textChanged[str].connect(self.slotPotElec)
96        self.lineEditValuePotElecIm.textChanged[str].connect(self.slotPotElecIm)
97        self.lineEditValueSpecies.textChanged[str].connect(self.slotSpecies)
98
99        self.pushButtonPotVectorFormula.clicked.connect(self.slotPotVectorFormula)
100        self.pushButtonPotElecFormula.clicked.connect(self.slotPotElecFormula)
101        self.pushButtonPotElecImFormula.clicked.connect(self.slotPotElecImFormula)
102
103        self.comboBoxTypePotElec.activated[str].connect(self.slotPotElecChoice)
104        self.comboBoxTypePotElecIm.activated[str].connect(self.slotPotElecImChoice)
105        self.comboBoxTypePotVector.activated[str].connect(self.slotPotVectorChoice)
106        self.comboBoxSpecies.activated[str].connect(self.slotSpeciesChoice)
107        self.comboBoxPotVector.activated[str].connect(self.slotPotVectorComponentChoice)
108
109        ## Validators
110        validatorPotElec      = DoubleValidator(self.lineEditValuePotElec)
111        validatorPotElecIm    = DoubleValidator(self.lineEditValuePotElecIm)
112        validatorSpecies      = DoubleValidator(self.lineEditValueSpecies, min=0.)
113
114        self.lineEditValuePotElec.setValidator(validatorPotElec)
115        self.lineEditValuePotElecIm.setValidator(validatorPotElecIm)
116        self.lineEditValueSpecies.setValidator(validatorSpecies)
117
118
119    def __setBoundary(self, boundary):
120        """
121        Set the current boundary
122        """
123        self.__boundary = boundary
124
125        self.nature  = boundary.getNature()
126
127        self.groupBoxPotElecIm.hide()
128        self.groupBoxPotVector.hide()
129        self.groupBoxMixture.hide()
130
131        self.modelPotElec   = ComboModel(self.comboBoxTypePotElec, 1, 1)
132        self.modelPotElecIm = ComboModel(self.comboBoxTypePotElecIm, 1, 1)
133        self.modelPotVector = ComboModel(self.comboBoxTypePotVector, 1, 1)
134
135        self.modelPotElec.addItem(self.tr("Prescribed value"), 'dirichlet')
136        self.modelPotElec.addItem(self.tr("Prescribed value  (user law)"), 'dirichlet_formula')
137        self.modelPotElec.addItem(self.tr("Prescribed flux"), 'neumann')
138        self.modelPotElec.addItem(self.tr("Prescribed flux  (user law)"), 'neumann_formula')
139        if self.__model.getScaling() == 'on':
140            self.modelPotElec.addItem(self.tr("Implicit value (dpot)"), 'dirichlet_implicit')
141
142        self.potElec = "elec_pot_r"
143        self.modelPotElecLabel = ComboModel(self.comboBoxPotElec,1,1)
144        self.modelPotElecLabel.addItem(self.tr(self.potElec),self.potElec)
145        self.modelPotElecLabel.setItem(str_model = self.potElec)
146
147        self.modelPotElecIm.addItem(self.tr("Prescribed value"), 'dirichlet')
148        self.modelPotElecIm.addItem(self.tr("Prescribed value  (user law)"), 'dirichlet_formula')
149        self.modelPotElecIm.addItem(self.tr("Prescribed flux"), 'neumann')
150        self.modelPotElecIm.addItem(self.tr("Prescribed flux  (user law)"), 'neumann_formula')
151
152        self.potElecIm = 'elec_pot_i'
153        self.modelPotElecImLabel = ComboModel(self.comboBoxPotElecIm,1,1)
154        self.modelPotElecImLabel.addItem(self.tr(self.potElecIm),self.potElecIm)
155        self.modelPotElecImLabel.setItem(str_model = self.potElecIm)
156
157        self.modelPotVector.addItem(self.tr("Prescribed value  (user law)"), 'dirichlet_formula')
158        self.modelPotVector.addItem(self.tr("Null flux"), 'neumann')
159        self.modelPotVector.addItem(self.tr("Implicit flux"), 'neumann_implicit')
160
161        self.potVect = 'vec_potential'
162        self.modelPotVectLabel = ComboModel(self.comboBoxPotVector, 1, 1)
163        self.modelPotVectLabel.addItem(self.tr('vec_potential'), 'vec_potential')
164        self.modelPotVectLabel.setItem(str_model = self.potVect)
165
166        if self.__model.getElectricalModel() == 'joule':
167            if self.__model.getJouleModel() == 'three-phase' or \
168               self.__model.getJouleModel() == 'three-phase+Transformer':
169                self.groupBoxPotElecIm.show()
170        elif self.__model.getElectricalModel() == 'arc':
171            self.groupBoxPotVector.show()
172
173            self.species = ""
174
175            if self.nature == 'inlet':
176                if self.__model.getGasNumber() > 1:
177                    self.groupBoxMixture.show()
178                    self.modelSpecies = ComboModel(self.comboBoxSpecies, 1, 1)
179                    self.species_list = self.__model.getSpeciesLabelsList()
180                    for species in self.species_list:
181                        self.modelSpecies.addItem(self.tr(species), species)
182                    self.species = self.species_list[0]
183                    self.modelSpecies.setItem(str_model = self.species)
184
185        self.initializeVariables()
186
187
188    def initializeVariables(self):
189        """
190        Initialize widget
191        """
192        self.lineEditValuePotElec.hide()
193        self.lineEditValuePotElecIm.hide()
194        self.lineEditValuePotVector.hide()
195        self.labelValuePotVector.hide()
196        self.labelValuePotElec.hide()
197        self.labelValuePotElecIm.hide()
198
199        self.pushButtonPotVectorFormula.setEnabled(False)
200        self.pushButtonPotVectorFormula.setStyleSheet("background-color: None")
201        self.pushButtonPotElecFormula.setEnabled(False)
202        self.pushButtonPotElecFormula.setStyleSheet("background-color: None")
203        self.pushButtonPotElecImFormula.setEnabled(False)
204        self.pushButtonPotElecImFormula.setStyleSheet("background-color: None")
205
206        # Initialize electric potential
207        self.potElec_type = self.__b.getElecScalarChoice(self.potElec)
208        self.modelPotElec.setItem(str_model = self.potElec_type)
209
210        if self.potElec_type == 'dirichlet' or self.potElec_type == 'neumann':
211            self.lineEditValuePotElec.show()
212            self.labelValuePotElec.show()
213            v = self.__b.getElecScalarValue(self.potElec, self.potElec_type)
214            self.lineEditValuePotElec.setText(str(v))
215        elif '_formula' in self.potElec_type:
216            self.labelValuePotElec.show()
217            self.pushButtonPotElecFormula.setEnabled(True)
218            exp = self.__b.getElecScalarFormula(self.potElec, self.potElec_type)
219            if exp:
220                self.pushButtonPotElecFormula.setStyleSheet("background-color: green")
221                self.pushButtonPotElecFormula.setToolTip(exp)
222            else:
223                self.pushButtonPotElecFormula.setStyleSheet("background-color: red")
224
225        # Initialize imaginary electric potential
226        if self.__model.getElectricalModel() == 'joule':
227            if self.__model.getJouleModel() == 'three-phase' or \
228               self.__model.getJouleModel() == 'three-phase+Transformer':
229                self.potElecIm_type = self.__b.getElecScalarChoice(self.potElecIm)
230                self.modelPotElecIm.setItem(str_model = self.potElecIm_type)
231
232                if self.potElecIm_type == 'dirichlet' or self.potElecIm_type == 'neumann':
233                    self.lineEditValuePotElecIm.show()
234                    self.labelValuePotElecIm.show()
235                    v = self.__b.getElecScalarValue(self.potElecIm, self.potElecIm_type)
236                    self.lineEditValuePotElecIm.setText(str(v))
237                elif '_formula' in self.potElecIm_type:
238                    self.labelValuePotElec.show()
239                    self.pushButtonPotElecFormula.setEnabled(True)
240                    exp = self.__b.getElecScalarFormula(self.potElecIm, self.potElecIm_type)
241                    if exp:
242                        self.pushButtonPotElecImFormula.setStyleSheet("background-color: green")
243                        self.pushButtonPotElecImFormula.setToolTip(exp)
244                    else:
245                        self.pushButtonPotElecImFormula.setStyleSheet("background-color: red")
246
247        # Initialize potential vector
248        if self.__model.getElectricalModel() == 'arc':
249            self.potVec_type = self.__b.getPotentialVectorChoice(self.potVect)
250            self.modelPotVector.setItem(str_model = self.potVec_type)
251
252            if self.potVec_type == 'dirichlet_formula':
253                self.pushButtonPotVectorFormula.setEnabled(True)
254                exp = self.__b.getElecScalarFormula(self.potVect, self.potVec_type)
255                if exp:
256                    self.pushButtonPotVectorFormula.setStyleSheet("background-color: green")
257                    self.pushButtonPotVectorFormula.setToolTip(exp)
258                else:
259                    self.pushButtonPotVectorFormula.setStyleSheet("background-color: red")
260
261            # Initialize species
262            if self.species :
263                v = self.__b.getElecScalarValue(self.species, 'dirichlet')
264                self.lineEditValueSpecies.setText(str(v))
265
266
267    @pyqtSlot(str)
268    def slotPotElecChoice(self, text):
269        """
270        INPUT choice for electric potential type
271        """
272        potElec_type = self.modelPotElec.dicoV2M[str(text)]
273        self.__b.setElecScalarChoice(self.potElec, potElec_type)
274        self.initializeVariables()
275
276
277    @pyqtSlot(str)
278    def slotPotElecImChoice(self, text):
279        """
280        INPUT choice for imaginary electric potential type
281        """
282        potElecIm_type = self.modelPotElecIm.dicoV2M[str(text)]
283        self.__b.setElecScalarChoice(self.potElecIm, potElecIm_type)
284        self.initializeVariables()
285
286
287    @pyqtSlot(str)
288    def slotPotVectorChoice(self, text):
289        """
290        INPUT choice for potential vector type
291        """
292        potVec_choice = self.modelPotVector.dicoV2M[str(text)]
293        self.__b.setPotentialVectorChoice(self.potVect, potVec_choice)
294        self.initializeVariables()
295
296
297    @pyqtSlot(str)
298    def slotSpeciesChoice(self, text):
299        """
300        INPUT species choice
301        """
302        self.species = self.modelSpecies.dicoV2M[str(text)]
303        self.initializeVariables()
304
305
306    @pyqtSlot(str)
307    def slotPotVectorComponentChoice(self, text):
308        """
309        INPUT potential vector component choice
310        """
311        self.potVect = self.modelPotVectLabel.dicoV2M[str(text)]
312        self.initializeVariables()
313
314
315    @pyqtSlot(str)
316    def slotPotElec(self, var):
317        """
318        """
319        if self.sender().validator().state == QValidator.Acceptable:
320            value = from_qvariant(var, float)
321            self.__b.setElecScalarValue(self.potElec, self.potElec_type, value)
322
323
324    @pyqtSlot(str)
325    def slotPotElecIm(self, var):
326        """
327        """
328        if self.sender().validator().state == QValidator.Acceptable:
329            value = from_qvariant(var, float)
330            self.__b.setElecScalarValue(self.potElecIm, self.potElecIm_type, value)
331
332
333    @pyqtSlot(str)
334    def slotSpecies(self, var):
335        """
336        """
337        if self.sender().validator().state == QValidator.Acceptable:
338            value = from_qvariant(var, float)
339            self.__b.setElecScalarValue(self.species, 'dirichlet', value)
340
341
342    def getScalarFormula(self, variable_name, exp_type, exp):
343        """
344        """
345        result = None
346
347        exa = """#example: """
348        if exp_type == 'dirichlet_formula':
349            req = [(variable_name, str(variable_name))]
350        elif exp_type == 'neumann_formula':
351            req = [("flux", "flux")]
352        elif exp_type == 'exchange_coefficient_formula':
353            req = [(variable_name, str(variable_name)),("hc", "heat coefficient")]
354
355        sym = [('x', "X face's gravity center"),
356               ('y', "Y face's gravity center"),
357               ('z', "Z face's gravity center"),
358               ('dt', 'time step'),
359               ('t', 'current time'),
360               ('iter', 'number of iteration'),
361               ('surface', 'Boundary zone surface')]
362
363        for (nme, val) in self.notebook.getNotebookList():
364            sym.append((nme, 'value (notebook) = ' + str(val)))
365
366        c = self.__boundary.getScalarChoice(variable_name)
367        dialog = QMegEditorView(parent        = self,
368                                function_type = 'bnd',
369                                zone_name     = self.__boundary._label,
370                                variable_name = variable_name,
371                                expression    = exp,
372                                required      = req,
373                                symbols       = sym,
374                                condition     = c,
375                                examples      = exa)
376
377        if dialog.exec_():
378            result = dialog.get_result()
379            log.debug("slotSpeciesFormula -> %s" % str(result))
380            self.__b.setElecScalarFormula(variable_name, exp_type, str(result))
381
382        return result
383
384
385    @pyqtSlot()
386    def slotPotElecFormula(self):
387        """
388        """
389        exp = self.__b.getElecScalarFormula(self.potElec, self.potElec_type)
390        if self.getScalarFormula(self.potElec, self.potElec_type, exp):
391            self.pushButtonPotElecFormula.setStyleSheet("background-color: green")
392            self.pushButtonPotElecFormula.setToolTip(exp)
393
394    @pyqtSlot()
395    def slotPotElecImFormula(self):
396        """
397        """
398        exp = self.__b.getElecScalarFormula(self.potElec, self.potElec_type)
399        if self.getScalarFormula(self.potElec, self.potElec_type, exp):
400            self.pushButtonPotElecImFormula.setStyleSheet("background-color: green")
401            self.pushButtonPotElecImFormula.setToolTip(exp)
402
403
404    @pyqtSlot()
405    def slotPotVectorFormula(self):
406        """
407        """
408        exp = self.__b.getElecScalarFormula(self.potVect, self.potVec_type)
409        exa = """#example: """
410
411        if not exp:
412            exp = self.potVect + "[0] = 0;\n" + \
413                  self.potVect + "[1] = 0;\n" + \
414                  self.potVect + "[2] = 0;\n"
415
416        req = [(self.potVect + "[0]", 'vector potential X'),
417               (self.potVect + "[1]", 'vector potential Y'),
418               (self.potVect + "[2]", 'vector potential Z')]
419
420        sym = [('x', "X cell's gravity center"),
421               ('y', "Y cell's gravity center"),
422               ('z', "Z cell's gravity center"),
423               ('dt', 'time step'),
424               ('t', 'current time'),
425               ('iter', 'number of iteration')]
426
427        for (nme, val) in self.notebook.getNotebookList():
428            sym.append((nme, 'value (notebook) = ' + str(val)))
429
430        c = self.__b.getElecScalarChoice(self.potVect)
431
432        dialog = QMegEditorView(parent        = self,
433                                function_type = 'bnd',
434                                zone_name     = self.__boundary._label,
435                                variable_name = self.potVect,
436                                expression    = exp,
437                                required      = req,
438                                symbols       = sym,
439                                condition     = c,
440                                examples      = exa)
441
442        if dialog.exec_():
443            result = dialog.get_result()
444            log.debug("slotPotVectorFormula -> %s" % str(result))
445            self.__b.setElecScalarFormula(self.potVect, self.potVec_type, str(result))
446            self.pushButtonPotVectorFormula.setToolTip(result)
447            self.pushButtonPotVectorFormula.setStyleSheet("background-color: green")
448
449
450    def showWidget(self, b):
451        """
452        Show the widget.
453        """
454        self.__b = b
455        if self.__model.getElectricalModel() != 'off':
456            label = b.getLabel()
457            nature = "joule_" + b.getNature()
458            self.__b = Boundary(nature, label, self.case)
459            self.__setBoundary(b)
460
461            self.show()
462        else:
463            self.hideWidget()
464
465
466    def hideWidget(self):
467        """
468        Hide all.
469        """
470        self.hide()
471
472
473#-------------------------------------------------------------------------------
474# End
475#-------------------------------------------------------------------------------
476