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 defines the 'Additional user's scalars' page.
27
28This module defines the following classes:
29- DefineUserScalarsModel
30"""
31
32#-------------------------------------------------------------------------------
33# Library modules import
34#-------------------------------------------------------------------------------
35
36import unittest
37
38#-------------------------------------------------------------------------------
39# Application modules import
40#-------------------------------------------------------------------------------
41
42from code_saturne.model.Common import *
43from code_saturne.model.XMLvariables import Variables
44from code_saturne.model.XMLvariables import Model
45from code_saturne.model.XMLmodel import XMLmodel, ModelTest
46
47#-------------------------------------------------------------------------------
48# Define User Scalars model class
49#-------------------------------------------------------------------------------
50
51class DefineUserScalarsModel(Variables, Model):
52    """
53    Useful methods for operation of the page.
54    __method : private methods for the Model class.
55    _method  : private methods for the View Class
56    """
57    def __init__(self, case):
58        """
59        Constructor
60        """
61        self.case = case
62
63        self.scalar_node = self.case.xmlGetNode('additional_scalars')
64        self.node_models = self.case.xmlGetNode('thermophysical_models')
65        self.node_therm  = self.node_models.xmlGetNode('thermal_scalar')
66        self.node_source = self.node_models.xmlGetNode('source_terms')
67        self.node_bc     = self.case.xmlGetNode('boundary_conditions')
68        self.node_ana    = self.case.xmlInitNode('analysis_control')
69        self.node_prof   = self.node_ana.xmlInitNode('profiles')
70        self.node_ava    = self.node_ana.xmlInitNode('time_averages')
71        self.gas_node    = self.case.xmlGetNode('gas_combustion')
72
73    def defaultScalarValues(self):
74        """Return the default values - Method also used by ThermalScalarModel"""
75        default = {}
76        default['scalar_label']          = "scalar"
77        default['variance_label']        = "variance"
78        default['coefficient_label']     = "Dscal"
79        default['diffusion_coefficient'] = 1.83e-05
80        default['diffusion_choice']      = 'constant'
81        default['zone_id']               = "1"
82        from code_saturne.model.GroundwaterModel import GroundwaterModel
83        if GroundwaterModel(self.case).getGroundwaterModel() == "groundwater":
84            default['GGDH']                  = "OFF"
85        else:
86            default['GGDH']                  = "SGDH"
87        del GroundwaterModel
88        if self.getThermalScalarName():
89            default['variance']          = self.getThermalScalarName()[0]
90        else:
91            if self.getScalarNameList():
92                default['variance']          = self.getScalarNameList()[0]
93            else:
94                default['variance']          = "no scalar"
95
96        return default
97
98
99    def __removeScalarChildNode(self, name, tag):
100        """
101        Private method.
102        Delete 'variance' or 'property' markup from scalar named I{name}
103        """
104        for node in self.scalar_node.xmlGetNodeList('variable'):
105            if node['name'] == name:
106                node.xmlRemoveChild(tag)
107
108
109    def __deleteScalarBoundaryConditions(self, name):
110        """
111        Private method.
112        Delete boundary conditions for scalar I{name}
113        """
114        for nature in ('inlet', 'outlet', 'wall'):
115            for node in self.node_bc.xmlGetChildNodeList(nature):
116                for n in node.xmlGetChildNodeList('scalar'):
117                    if n['name'] == name:
118                        n.xmlRemoveNode()
119
120
121    def __defaultScalarNameAndDiffusivityLabel(self, scalar_name=None):
122        """
123        Private method.
124        Return a default name and label for a new scalar.
125        Create a default name for the associated diffusion coefficient to.
126        """
127        __coef = {}
128        for l in self.getScalarNameList():
129            __coef[l] = self.getScalarDiffusivityLabel(l)
130        length = len(__coef)
131        Lscal = self.defaultScalarValues()['scalar_label']
132        Dscal = self.defaultScalarValues()['coefficient_label']
133
134        # new scalar: default value for both scalar and diffusivity
135
136        if not scalar_name:
137            if length != 0:
138                i = 1
139                while (Dscal + str(i)) in list(__coef.values()):
140                    i = i + 1
141                num = str(i)
142            else:
143                num = str(1)
144            scalar_name = Lscal + num
145            __coef[scalar_name] = Dscal + num
146
147        # existing scalar
148
149        else:
150            if scalar_name not in list(__coef.keys())or \
151               (scalar_name in list(__coef.keys()) and __coef[scalar_name] == ''):
152
153                __coef[scalar_name] = Dscal + str(length + 1)
154
155        return scalar_name, __coef[scalar_name]
156
157
158    def __defaultVarianceName(self, scalar_name=None):
159        """
160        Private method.
161        Return a default name and label for a new variance.
162        """
163        __coef = {}
164        for l in self.getScalarsVarianceList():
165            __coef[l] = l
166        length = len(__coef)
167        Lscal = self.defaultScalarValues()['variance_label']
168
169        # new scalar: default value for both scalar and diffusivity
170
171        if not scalar_name:
172            if length != 0:
173                i = 1
174                while (Lscal + str(i)) in list(__coef.values()):
175                    i = i + 1
176                num = str(i)
177            else:
178                num = str(1)
179            scalar_name = Lscal + num
180        return scalar_name
181
182
183    def __updateScalarNameAndDiffusivityName(self):
184        """
185        Private method.
186        Update suffix number for scalar name and diffusivity' name.
187        """
188        lst = []
189        for node in self.scalar_node.xmlGetNodeList('variable'):
190            nprop = node.xmlGetChildNode('property')
191            if nprop:
192                old_name = nprop['name']
193                nprop['name'] = node['name'] + '_diffusivity'
194                new_name = nprop['name']
195                if old_name:
196                    for no in self.case.xmlGetNodeList('formula'):
197                        txt = no.xmlGetTextNode()
198                        if txt != None:
199                            f = txt.replace(old_name, new_name)
200                            no.xmlSetTextNode(f)
201
202
203    def __setScalarDiffusivity(self, scalar_name, coeff_label):
204        """
205        Private method.
206
207        Input default initial value of property "diffusivity"
208        for a new scalar I{scalar_name}
209        """
210        self.isNotInList(scalar_name, self.getScalarsVarianceList())
211        self.isInList(scalar_name, self.getUserScalarNameList())
212
213        n = self.scalar_node.xmlGetNode('variable', type='user', name=scalar_name)
214        n.xmlInitChildNode('property', label=coeff_label)
215
216        if not self.getScalarDiffusivityChoice(scalar_name):
217            self.setScalarDiffusivityChoice(scalar_name, 'constant')
218
219        if not self.getScalarDiffusivityInitialValue(scalar_name):
220            ini = self.defaultScalarValues()['diffusion_coefficient']
221            self.setScalarDiffusivityInitialValue(scalar_name, ini)
222
223
224    def __deleteScalar(self, name):
225        """
226        Private method.
227
228        Delete scalar I{name}.
229        """
230        node = self.scalar_node.xmlGetNode('variable', name=name)
231        node.xmlRemoveNode()
232        self.__deleteScalarBoundaryConditions(name)
233        self.__updateScalarNameAndDiffusivityName()
234        # delete scalar in profiles and time averages nodes
235        for node in self.node_prof.xmlGetNodeList('profile'):
236            node.xmlRemoveChild('var_prop', name=name)
237        for node in self.node_ava.xmlGetNodeList('time_average'):
238            node.xmlRemoveChild('var_prop', name=name)
239
240
241
242    @Variables.noUndo
243    def getThermalScalarName(self):
244        """Public method.
245        Return the thermal scalar name"""
246        lst = []
247        for node in self.node_therm.xmlGetNodeList('variable'):
248            lst.append(node['name'])
249        return lst
250
251
252    @Variables.noUndo
253    def getScalarNameList(self):
254        """Public method.
255        Return the User scalar name list (thermal scalar included)"""
256        lst = []
257        for node in self.scalar_node.xmlGetChildNodeList('variable'):
258            lst.append(node['name'])
259        return lst
260
261
262    @Variables.noUndo
263    def getMeteoScalarsNameList(self):
264        node_list = []
265        models = self.case.xmlGetNode('thermophysical_models')
266        node = models.xmlGetNode('atmospheric_flows', 'model')
267        if node == None:
268            return
269
270        model = node['model']
271        list_scalar=[]
272        if model != 'off':
273            node_list = node.xmlGetNodeList('variable')
274            for node_scalar in node_list:
275                list_scalar.append(node_scalar['name'])
276
277        return list_scalar
278
279
280    @Variables.noUndo
281    def getGasCombScalarsNameList(self):
282        node_list = []
283        models = self.case.xmlGetNode('thermophysical_models')
284        node = models.xmlGetNode('gas_combustion', 'model')
285        if node == None:
286            return
287
288        model = node['model']
289        list_scalar=[]
290        if model != 'off':
291            node_list = node.xmlGetNodeList('variable')
292            for node_scalar in node_list:
293                list_scalar.append(node_scalar['name'])
294
295        return list_scalar
296
297
298    @Variables.noUndo
299    def getElectricalScalarsNameList(self):
300        node_list = []
301        models = self.case.xmlGetNode('thermophysical_models')
302        node = models.xmlGetNode('joule_effect', 'model')
303        if node == None:
304            return
305
306        model = node['model']
307        if model != 'off':
308            node_list = node.xmlGetNodeList('variable')
309            list_scalar=[]
310            for node_scalar in node_list:
311                list_scalar.append(node_scalar['name'])
312        else:
313            return
314
315        return list_scalar
316
317
318    @Variables.noUndo
319    def getUserScalarNameList(self):
320        """Public method.
321        Return the user scalar name list (without thermal scalar).
322        Method also used by UserScalarPropertiesView
323        """
324        lst = []
325        for node in self.scalar_node.xmlGetNodeList('variable', type='user'):
326            lst.append(node['name'])
327        return lst
328
329
330    @Variables.undoGlobal
331    def setScalarBoundaries(self):
332        """Public method.
333        Input boundaries conditions for a scalar node. Method also used by ThermalScalarModel
334        """
335        from code_saturne.model.Boundary import Boundary
336
337        for node in self.node_bc.xmlGetChildNodeList('inlet'):
338            model = Boundary('inlet', node['name'], self.case)
339            for name in self.getScalarNameList():
340                model.setScalarValue(name, 'dirichlet', 0.0)
341
342        for node in self.node_bc.xmlGetChildNodeList('outlet'):
343            model = Boundary('outlet', node['name'], self.case)
344            for name in self.getScalarNameList():
345                model.setScalarValue(name, 'dirichlet', 0.0)
346
347
348    @Variables.undoGlobal
349    def addUserScalar(self, name=None):
350        """Public method.
351        Input a new user scalar I{name}"""
352
353        l, c = self.__defaultScalarNameAndDiffusivityLabel(name)
354
355        if l not in self.getScalarNameList() and l not in self.getThermalScalarName():
356            self.scalar_node.xmlInitNode('variable', name=l, type="user", label=l)
357
358            self.__setScalarDiffusivity(l, c)
359            self.setScalarBoundaries()
360
361        self.__updateScalarNameAndDiffusivityName()
362
363        return l
364
365
366    @Variables.undoGlobal
367    def addVariance(self, name=None):
368        """Public method.
369        Input a new user scalar I{name}"""
370
371        l= self.__defaultVarianceName(name)
372        if l not in self.getScalarsVarianceList():
373            self.scalar_node.xmlInitNode('variable', name=l, type="user", label=l)
374            if (self.getThermalScalarName() != None) or (self.getScalarNameList() != None):
375                self.setScalarVariance(l, self.defaultScalarValues()['variance'])
376
377        self.__updateScalarNameAndDiffusivityName()
378
379        return l
380
381
382    @Variables.undoLocal
383    def renameScalarLabel(self, old_name, new_name):
384        """Public method.
385        Modify old_name of scalar with new_name and put new name if variancy exists"""
386        # fusion de cette methode avec OutputVolumicVariablesModel.setVariablesLabel
387        self.isInList(old_name, self.getScalarNameList())
388
389        name = new_name[:LABEL_LENGTH_MAX]
390        if name not in self.getScalarNameList():
391            for node in self.scalar_node.xmlGetNodeList('variable'):
392                if node['name'] == old_name:
393                    node['label'] = name
394                    node['name']  = name
395
396                    # Rename scalar diffusivity consistently with the scalar
397                    for ndiff in node.xmlGetNodeList('property'):
398                        if ndiff['name'] == old_name+'_diffusivity':
399                            ndiff['name'] = name + '_diffusivity'
400
401                if node.xmlGetString('variance') == old_name:
402                    node.xmlSetData('variance', name)
403
404        for nature in ('inlet', 'outlet', 'wall'):
405            for node in self.node_bc.xmlGetChildNodeList(nature):
406                for n in node.xmlGetChildNodeList('scalar'):
407                    if n['name'] == old_name:
408                        n['label'] = new_name
409                        n['name']  = new_name
410
411        for node in self.case.xmlGetNodeList('formula'):
412            text = f = node.xmlGetTextNode()
413            if text:
414                f = text.replace(old_name, new_name)
415                node.xmlSetTextNode(f)
416
417        node_gw = self.node_models.xmlGetNode('groundwater_model')
418        if node_gw:
419            for n in node_gw.xmlGetChildNodeList('scalar'):
420                if n['name'] == old_name:
421                    n['name']  = new_name
422
423
424    @Variables.undoGlobal
425    def setTurbulentFluxGlobalModel(self, TurbulenceModel):
426        """Put turbulent flux model of an additional_scalar with name scalar_name"""
427        lst = self.getScalarNameList() + self.getThermalScalarName()
428
429        if TurbulenceModel not in ('Rij-epsilon', 'Rij-SSG', 'Rij-EBRSM'):
430            mdl = self.defaultScalarValues()['GGDH']
431            for var in lst:
432                n = self.case.xmlGetNode('variable', name=var)
433                n.xmlSetData('turbulent_flux_model', mdl)
434
435
436    @Variables.noUndo
437    def getTurbulentFluxModel(self, l):
438        """
439        Get turbulent flux model of an additional_scalar with name I{l}.
440        """
441        lst = self.getScalarNameList() + self.getThermalScalarName() + self.getGasCombScalarsNameList()
442        self.isInList(l, lst)
443        n = self.case.xmlGetNode('variable', name=l)
444        mdl = n.xmlGetString('turbulent_flux_model')
445        if not mdl:
446            mdl = self.defaultScalarValues()['GGDH']
447            self.setTurbulentFluxModel(l, mdl)
448
449        return mdl
450
451
452    @Variables.undoGlobal
453    def setTurbulentFluxModel(self, scalar_name, TurbFlux):
454        """Put turbulent flux model of an additional_scalar with name scalar_name"""
455        lst = self.getScalarNameList() + self.getThermalScalarName() + self.getGasCombScalarsNameList()
456        self.isInList(scalar_name, lst)
457
458        n = self.case.xmlGetNode('variable', name=scalar_name)
459        n.xmlSetData('turbulent_flux_model', TurbFlux)
460
461
462    @Variables.noUndo
463    def getScalarVariance(self, l):
464        """
465        Get variance of an additional_scalar with name I{l}.
466        Method also used by UserScalarPropertiesView
467        """
468        self.isInList(l, self.getScalarNameList() + self.getGasCombScalarsNameList())
469
470        if l in self.getScalarNameList():
471            return self.scalar_node.xmlGetNode('variable', name=l).xmlGetString('variance')
472        elif l in self.getGasCombScalarsNameList():
473            return self.gas_node.xmlGetNode('variable', name=l).xmlGetString('variance')
474
475
476    @Variables.undoGlobal
477    def setScalarVariance(self, scalar_name, variance_name):
478        """Put variance of an additional_scalar with name scalar_name"""
479        self.isInList(scalar_name, self.getUserScalarNameList())
480        lst = self.getScalarNameList() + self.getThermalScalarName()
481        self.isInList(variance_name, lst)
482
483        n = self.scalar_node.xmlGetNode('variable', type='user', name=scalar_name)
484        n.xmlSetData('variance', variance_name)
485
486        self.__removeScalarChildNode(scalar_name, 'property')
487
488
489    @Variables.noUndo
490    def getScalarsWithVarianceList(self):
491        """
492        Return list of scalars which have a variance
493        """
494        lst = []
495        for node in self.scalar_node.xmlGetNodeList('variable'):
496            sca = node.xmlGetString('variance')
497            if sca and sca not in lst:
498                lst.append(sca)
499        return lst
500
501
502    @Variables.noUndo
503    def getScalarsVarianceList(self):
504        """
505        Return list of scalars which are also a variance
506        """
507        lst = []
508        for node in self.scalar_node.xmlGetNodeList('variable'):
509            if node.xmlGetString('variance') and node['name'] not in lst:
510                lst.append(node['name'])
511        return lst
512
513
514    @Variables.noUndo
515    def getVarianceLabelFromScalarLabel(self, name):
516        """
517        Get the name of scalar with variancy's name: name
518        """
519        self.isInList(name, self.getScalarNameList())
520
521        lab = ""
522        for node in self.scalar_node.xmlGetNodeList('variable'):
523            if node.xmlGetString('variance') == name:
524                lab = node['name']
525        return lab
526
527
528    @Variables.noUndo
529    def getScalarDiffusivityName(self, scalar_name):
530        """
531        Get name of diffusivity's property for an additional_scalar
532        with name scalar_name
533        """
534        self.isInList(scalar_name, self.getScalarNameList())
535
536        lab_diff = ""
537        n = self.scalar_node.xmlGetNode('variable', name=scalar_name)
538        n_diff = n.xmlGetChildNode('property')
539        if n_diff:
540            lab_diff = n_diff['name']
541
542        return lab_diff
543
544
545    @Variables.undoLocal
546    def setScalarDiffusivityLabel(self, scalar_name, diff_label):
547        """
548        Set name of diffusivity's property for an additional_scalar
549        """
550        self.isInList(scalar_name, self.getScalarNameList())
551
552        n = self.scalar_node.xmlGetNode('variable', name=scalar_name)
553        n.xmlGetChildNode('property')['label'] = diff_label
554
555
556    @Variables.noUndo
557    def getScalarDiffusivityLabel(self, scalar_name):
558        """
559        Get name of diffusivity's property for an additional_scalar
560        with name scalar_name
561        """
562        self.isInList(scalar_name, self.getScalarNameList())
563
564        lab_diff = ""
565        n = self.scalar_node.xmlGetNode('variable', name=scalar_name)
566        n_diff = n.xmlGetChildNode('property')
567        if n_diff:
568            lab_diff = n_diff['label']
569
570        return lab_diff
571
572
573    @Variables.undoLocal
574    def setScalarDiffusivityInitialValue(self, scalar_name, initial_value):
575        """
576        Set initial value of diffusivity's property for an additional_scalar
577        with name scalar_name. Method also called by UserScalarPropertiesView.
578        """
579        self.isNotInList(scalar_name, self.getScalarsVarianceList())
580        self.isInList(scalar_name, self.getUserScalarNameList())
581        self.isFloat(initial_value)
582
583        n = self.scalar_node.xmlGetNode('variable', name=scalar_name)
584        n_diff = n.xmlInitChildNode('property')
585        n_diff.xmlSetData('initial_value', initial_value)
586
587
588    @Variables.noUndo
589    def getScalarDiffusivityInitialValue(self, scalar_name):
590        """
591        Get initial value of diffusivity's property for an additional_scalar
592        with name scalar_name. Method also called by UserScalarPropertiesView.
593        """
594        self.isNotInList(scalar_name, self.getScalarsVarianceList())
595        self.isInList(scalar_name, self.getUserScalarNameList())
596
597        n = self.scalar_node.xmlGetNode('variable', name=scalar_name)
598        n_diff = n.xmlInitChildNode('property')
599        diffu = n_diff.xmlGetDouble('initial_value')
600        if diffu == None:
601            diffu = self.defaultScalarValues()['diffusion_coefficient']
602            self.setScalarDiffusivityInitialValue(scalar_name, diffu)
603
604        return diffu
605
606
607    @Variables.undoLocal
608    def setScalarDiffusivityChoice(self, scalar_name, choice):
609        """
610        Set choice of diffusivity's property for an additional_scalar
611        with name scalar_name
612        """
613        self.isNotInList(scalar_name, self.getScalarsVarianceList())
614        self.isInList(scalar_name, self.getUserScalarNameList())
615        self.isInList(choice, ('constant', 'user_law'))
616
617        n = self.scalar_node.xmlGetNode('variable', name=scalar_name)
618        n_diff = n.xmlInitChildNode('property')
619        n_diff['choice'] = choice
620
621
622    @Variables.noUndo
623    def getScalarDiffusivityChoice(self, scalar_name):
624        """
625        Get choice of diffusivity's property for an additional_scalar
626        with name scalar_name
627        """
628        self.isNotInList(scalar_name, self.getScalarsVarianceList())
629        self.isInList(scalar_name, self.getUserScalarNameList())
630
631        n = self.scalar_node.xmlGetNode('variable', name=scalar_name)
632        choice = n.xmlInitChildNode('property')['choice']
633        if not choice:
634            choice = self.defaultScalarValues()['diffusion_choice']
635            self.setScalarDiffusivityChoice(scalar_name, choice)
636
637        return choice
638
639
640    @Variables.noUndo
641    def getDiffFormula(self, scalar, zone="1"):
642        """
643        Return a formula for I{tag} 'density', 'molecular_viscosity',
644        'specific_heat' or 'thermal_conductivity'
645        """
646        self.isNotInList(scalar, self.getScalarsVarianceList())
647        self.isInList(scalar, self.getUserScalarNameList())
648        n = self.scalar_node.xmlGetNode('variable', name = scalar)
649        node = n.xmlGetNode('property')
650
651        if zone != "1":
652            if node.xmlGetChildNode("zone", zone_id=zone):
653                node = node.xmlGetChildNode("zone", zone_id=zone)
654            else:
655                node = node.xmlInitChildNode("zone", zone_id=zone)
656
657        formula = node.xmlGetChildString('formula')
658        if not formula:
659            formula = self.getDefaultFormula(scalar)
660            self.setDiffFormula(scalar, formula)
661        return formula
662
663
664    @Variables.noUndo
665    def getDefaultFormula(self, scalar):
666        """
667        Return default formula
668        """
669        self.isNotInList(scalar, self.getScalarsVarianceList())
670        self.isInList(scalar, self.getUserScalarNameList())
671
672        name = scalar
673
674        formula = str(name) + "_diffusivity = 1.e-5;"
675
676        return formula
677
678
679    @Variables.undoLocal
680    def setDiffFormula(self, scalar, formula, zone="1"):
681        """
682        Gives a formula for 'density', 'molecular_viscosity',
683        'specific_heat'or 'thermal_conductivity'
684        """
685        self.isNotInList(scalar, self.getScalarsVarianceList())
686        self.isInList(scalar, self.getUserScalarNameList())
687        n = self.scalar_node.xmlGetNode('variable', name = scalar)
688        node = n.xmlGetNode('property')
689        if zone != "1":
690            if node.xmlGetChildNode("zone", zone_id=zone):
691                node = node.xmlGetChildNode("zone", zone_id=zone)
692            else:
693                node = node.xmlInitChildNode("zone", zone_id=zone)
694        node.xmlSetData('formula', formula)
695
696
697    @Variables.undoGlobal
698    def setScalarValues(self, name, vari):
699        """
700        Put values to scalar with name I{name} for creating or replacing values.
701        """
702        l = self.getScalarNameList()
703        l.append('no')
704        self.isInList(vari, l)
705
706        if vari != "no":
707            self.setScalarVariance(name, vari)
708        else:
709            self.__removeScalarChildNode(name, 'variance')
710            l, c = self.__defaultScalarNameAndDiffusivityLabel(name)
711            self.__setScalarDiffusivity(l, c)
712
713        self.__updateScalarNameAndDiffusivityName()
714
715
716    @Variables.undoGlobal
717    def deleteScalar(self, sname):
718        """
719        Public method.
720        Delete scalar I{name}
721        Warning: deleting a scalar may delete other scalar which are variances
722        of previous deleting scalars.
723        """
724        self.isInList(sname, self.getScalarNameList())
725
726        # First add the main scalar to delete
727        lst = []
728        lst.append(sname)
729
730        # Then add variance scalar related to the main scalar
731        for node in self.scalar_node.xmlGetNodeList('variable'):
732            if node.xmlGetString('variance') == sname:
733                lst.append(node['name'])
734
735        # update scalar source term status
736        if self.node_source != None:
737            for node in self.node_source.xmlGetNodeList('scalar_formula'):
738                if node.xmlGetString('name') == sname:
739                   node.xmlRemoveNode()
740
741        # Delete scalars in list
742        for scalar in lst:
743            self.__deleteScalar(scalar)
744
745        if len(self.scalar_node.xmlGetNodeList('variable')) == 0:
746            node_domain = self.case.xmlGetNode('solution_domain')
747            node_vol = node_domain.xmlGetNode('volumic_conditions')
748            for node in node_vol.xmlGetChildNodeList('zone'):
749                node['scalar_source_term'] = 'off'
750
751        return lst
752
753
754    @Variables.undoGlobal
755    def deleteThermalScalar(self, sname):
756        """
757        Public method.
758        Delete scalar I{namel}. Called by ThermalScalarModel
759        Warning: deleting a scalar may delete other scalar which are variances
760        of previous deleting scalars.
761        """
762        self.isInList(sname, self.getThermalScalarName())
763
764        # First add the main scalar to delete
765        lst = []
766        lst.append(sname)
767
768        # Then add variance scalar related to the main scalar
769        for node in self.scalar_node.xmlGetNodeList('variable'):
770            if node.xmlGetString('variance') == sname:
771                self.__deleteScalar(node['name'])
772
773        # Delete scalars
774        node = self.node_therm.xmlGetNode('variable', name=sname)
775        node.xmlRemoveNode()
776        self.__deleteScalarBoundaryConditions(sname)
777        self.__updateScalarNameAndDiffusivityName()
778
779        return lst
780
781
782    @Variables.noUndo
783    def getScalarTypeByName(self, scalarName):
784        """
785        Return type of scalar for choice of color (for view)
786        """
787        self.isInList(scalarName, self.getScalarNameList() + self.getThermalScalarName())
788        if scalarName not in self.getScalarNameList():
789            node = self.node_therm.xmlGetNode('variable', name = scalarName)
790        else:
791            node = self.scalar_node.xmlGetNode('variable', 'type', name = scalarName)
792        Model().isInList(node['type'], ('user', 'thermal'))
793        return node['type']
794
795
796    @Variables.noUndo
797    def getScalarType(self, scalar_name):
798        """
799        Return type of scalar for choice of color (for view)
800        """
801        self.isInList(scalar_name, self.getScalarNameList() + self.getThermalScalarName() + self.getGasCombScalarsNameList())
802        if scalar_name not in self.getScalarNameList() and scalar_name not in self.getGasCombScalarsNameList():
803            node = self.node_therm.xmlGetNode('variable', name=scalar_name)
804        elif scalar_name in self.getGasCombScalarsNameList():
805            node = self.gas_node.xmlGetChildNode('variable', 'type', name=scalar_name)
806        else:
807            node = self.scalar_node.xmlGetNode('variable', 'type', name=scalar_name)
808        Model().isInList(node['type'], ('user', 'thermal', 'var_model'))
809        return node['type']
810
811
812    @Variables.noUndo
813    def getScalarName(self, scalar_name):
814        """
815        Return type of scalar for choice of color (for view)
816        """
817        self.isInList(scalar_name, self.getScalarNameList() + self.getThermalScalarName())
818        if scalar_name not in self.getScalarNameList():
819            node = self.node_therm.xmlGetNode('variable', name=scalar_name)
820        else:
821            node = self.scalar_node.xmlGetNode('variable', name=scalar_name)
822        return node['name']
823
824
825    @Variables.noUndo
826    def getMeteoScalarType(self, scalarName):
827        """
828        Return type of scalar for choice of color (for view)
829        """
830        self.isInList(scalarName, self.getMeteoScalarsNameList())
831        models = self.case.xmlGetNode('thermophysical_models')
832        node = models.xmlGetNode('atmospheric_flows', 'model')
833        n = node.xmlGetNode('variable', 'type', name=scalarName)
834        Model().isInList(n['type'], ('user', 'thermal', 'model'))
835        return n['type']
836
837
838    @Variables.noUndo
839    def getElectricalScalarType(self, scalarName):
840        """
841        Return type of scalar for choice of color (for view)
842        """
843        self.isInList(scalarName, self.getElectricalScalarsNameList())
844        models = self.case.xmlGetNode('thermophysical_models')
845        node = models.xmlGetNode('joule_effect', 'model')
846        n = node.xmlGetNode('variable', 'type', name=scalarName)
847        Model().isInList(n['type'], ('user', 'thermal', 'model'))
848        return n['type']
849
850
851#-------------------------------------------------------------------------------
852# DefineUsersScalars test case
853#-------------------------------------------------------------------------------
854
855
856class UserScalarTestCase(ModelTest):
857    """
858    Unittest.
859    """
860    def checkDefineUserScalarsModelInstantiation(self):
861        """Check whether the DefineUserScalarsModel class could be instantiated."""
862        model = None
863        model = DefineUserScalarsModel(self.case)
864
865        assert model != None, 'Could not instantiate DefineUserScalarsModel'
866
867
868    def checkAddNewUserScalar(self):
869        """Check whether the DefineUserScalarsModel class could add a scalar."""
870        model = DefineUserScalarsModel(self.case)
871        zone = '1'
872        model.addUserScalar(zone, 'toto')
873
874        doc = '''<additional_scalars>
875                    <variable label="toto" name="user_1" type="user">
876                            <initial_value zone_id="1">0.0 </initial_value>
877                            <min_value>-1e+12</min_value>
878                            <max_value>1e+12</max_value>
879                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
880                                    <initial_value>1.83e-05</initial_value>
881                            </property>
882                    </variable>
883                </additional_scalars>'''
884
885        assert model.scalar_node == self.xmlNodeFromString(doc),\
886           'Could not add a user scalar'
887
888    def checkRenameScalarLabel(self):
889        """Check whether the DefineUserScalarsModel class could set a label."""
890        model = DefineUserScalarsModel(self.case)
891        zone = '1'
892        model.addUserScalar(zone, 'toto')
893        model.addUserScalar(zone,'titi')
894        model.renameScalarLabel('titi', 'MACHIN')
895
896        doc = '''<additional_scalars>
897                    <variable label="toto" name="user_1" type="user">
898                            <initial_value zone_id="1">0.0</initial_value>
899                            <min_value>-1e+12</min_value>
900                            <max_value>1e+12</max_value>
901                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
902                                    <initial_value>1.83e-05</initial_value>
903                            </property>
904                    </variable>
905                    <variable label="MACHIN" name="user_2" type="user">
906                            <initial_value zone_id="1">0.0</initial_value>
907                            <min_value>-1e+12</min_value>
908                            <max_value>1e+12</max_value>
909                            <property choice="constant" label="Dscal2" name="diffusion_coefficient_2">
910                                    <initial_value>1.83e-05</initial_value>
911                            </property>
912                    </variable>
913                </additional_scalars>'''
914
915        assert model.scalar_node == self.xmlNodeFromString(doc),\
916           'Could not rename a label to one scalar'
917
918    def checkGetThermalScalarLabel(self):
919        """Check whether the DefineUserScalarsModel class could be get label of thermal scalar."""
920        model = DefineUserScalarsModel(self.case)
921        zone = '1'
922        model.addUserScalar(zone, 'usersca1')
923        from code_saturne.model.ThermalScalarModel import ThermalScalarModel
924        ThermalScalarModel(self.case).setThermalModel('temperature_celsius')
925        del ThermalScalarModel
926
927        doc = '''<additional_scalars>
928                    <variable label="usersca1" name="user_1" type="user">
929                            <initial_value zone_id="1">0.0</initial_value>
930                            <min_value>-1e+12</min_value>
931                            <max_value>1e+12</max_value>
932                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
933                                    <initial_value>1.83e-05</initial_value>
934                            </property>
935                    </variable>
936                    <variable label="TempC" name="temperature_celsius" type="thermal">
937                            <initial_value zone_id="1">20.0</initial_value>
938                            <min_value>-1e+12</min_value>
939                            <max_value>1e+12</max_value>
940                    </variable>
941                </additional_scalars>'''
942
943        model.renameScalarLabel("TempC", "Matemperature")
944
945        assert model.getThermalScalarLabel() == "Matemperature",\
946           'Could not get label of thermal scalar'
947
948    def checkSetAndGetScalarInitialValue(self):
949        """Check whether the DefineUserScalarsModel class could be set and get initial value."""
950        model = DefineUserScalarsModel(self.case)
951        zone = '1'
952        model.addUserScalar(zone, 'toto')
953        model.setScalarInitialValue(zone, 'toto', 0.05)
954
955        doc = '''<additional_scalars>
956                    <variable label="toto" name="user_1" type="user">
957                            <initial_value zone_id="1">0.05</initial_value>
958                            <min_value>-1e+12</min_value>
959                            <max_value>1e+12</max_value>
960                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
961                                    <initial_value>1.83e-05</initial_value>
962                            </property>
963                    </variable>
964                </additional_scalars>'''
965
966        assert model.scalar_node == self.xmlNodeFromString(doc),\
967            'Could not set initial value to user scalar'
968        assert model.getScalarInitialValue(zone, 'toto') == 0.05,\
969            'Could not get initial value to user scalar'
970
971    def checkSetAndGetScalarMinMaxValue(self):
972        """Check whether the DefineUserScalarsModel class could be set and get min and max value."""
973        model = DefineUserScalarsModel(self.case)
974        zone = '1'
975        model.addUserScalar(zone, 'toto')
976        model.addUserScalar(zone, 'titi')
977        model.setScalarInitialValue(zone, 'toto', 0.05)
978        model.setScalarMinValue('toto',0.01)
979        model.setScalarMaxValue('titi',100.)
980
981        doc = '''<additional_scalars>
982                    <variable label="toto" name="user_1" type="user">
983                            <initial_value zone_id="1">0.05</initial_value>
984                            <min_value>0.01</min_value>
985                            <max_value>1e+12</max_value>
986                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
987                                    <initial_value>1.83e-05</initial_value>
988                            </property>
989                    </variable>
990                    <variable label="titi" name="user_2" type="user">
991                            <initial_value zone_id="1">0.0</initial_value>
992                            <min_value>-1e+12</min_value>
993                            <max_value>100.</max_value>
994                            <property choice="constant" label="Dscal2" name="diffusion_coefficient_2">
995                                    <initial_value>1.83e-05</initial_value>
996                            </property>
997                    </variable>
998                </additional_scalars>'''
999
1000        assert model.scalar_node == self.xmlNodeFromString(doc),\
1001            'Could not set minimal or maximal value to user scalar'
1002        assert model.getScalarMinValue('toto') == 0.01,\
1003            'Could not get minimal value from user scalar'
1004        assert model.getScalarMaxValue('titi') == 100.,\
1005            'Could not get maximal value from user scalar'
1006
1007    def checkSetAndGetScalarVariance(self):
1008        """Check whether the DefineUserScalarsModel class could be set and get variance of scalar."""
1009        model = DefineUserScalarsModel(self.case)
1010        zone = '1'
1011        model.addUserScalar(zone, 'toto')
1012        model.addUserScalar(zone, 'titi')
1013        model.setScalarVariance('toto', 'titi')
1014
1015        doc = '''<additional_scalars>
1016                    <variable label="toto" name="user_1" type="user">
1017                            <initial_value zone_id="1">0.0</initial_value>
1018                            <min_value>0</min_value>
1019                            <max_value>1e+12</max_value>
1020                            <variance>titi</variance>
1021                    </variable>
1022                    <variable label="titi" name="user_2" type="user">
1023                            <initial_value zone_id="1">0.0</initial_value>
1024                            <min_value>-1e+12</min_value>
1025                            <max_value>1e+12</max_value>
1026                            <property choice="constant" label="Dscal2" name="diffusion_coefficient_2">
1027                                    <initial_value>1.83e-05</initial_value>
1028                            </property>
1029                    </variable>
1030                </additional_scalars>'''
1031
1032        assert model.scalar_node == self.xmlNodeFromString(doc),\
1033            'Could not set variance to user scalar'
1034        assert model.getScalarVariance('toto') == 'titi',\
1035            'Could not get variance of user scalar'
1036
1037    def checkGetVarianceLabelFromScalarLabel(self):
1038        """
1039        Check whether the DefineUserScalarsModel class could be get label of
1040        the scalar which has variancy.
1041        """
1042        model = DefineUserScalarsModel(self.case)
1043        zone = '1'
1044        model.addUserScalar(zone, 'toto')
1045        model.addUserScalar(zone, 'titi')
1046        model.setScalarVariance('toto', 'titi')
1047
1048        assert model.getVarianceLabelFromScalarLabel('titi') == 'toto',\
1049            'Could not get label of scalar whiwh has a variancy'
1050
1051    def checkGetScalarDiffusivityLabel(self):
1052        """
1053        Check whether the DefineUserScalarsModel class could be get label of
1054        diffusivity of user scalar.
1055        """
1056        model = DefineUserScalarsModel(self.case)
1057        zone = '1'
1058        model.addUserScalar(zone, 'premier')
1059        model.addUserScalar(zone, 'second')
1060
1061        doc = '''<additional_scalars>
1062                    <variable label="premier" name="user_1" type="user">
1063                            <initial_value zone_id="1">0.0</initial_value>
1064                            <min_value>0</min_value>
1065                            <max_value>1e+12</max_value>
1066                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
1067                                    <initial_value>1.83e-05</initial_value>
1068                            </property>
1069                    </variable>
1070                    <variable label="second" name="user_2" type="user">
1071                            <initial_value zone_id="1">0.0</initial_value>
1072                            <min_value>-1e+12</min_value>
1073                            <max_value>1e+12</max_value>
1074                            <property choice="constant" label="Dscal2" name="diffusion_coefficient_2">
1075                                    <initial_value>1.83e-05</initial_value>
1076                            </property>
1077                    </variable>
1078                </additional_scalars>'''
1079
1080        assert model.getScalarDiffusivityLabel('second') == "Dscal2",\
1081            'Could not get label of diffusivity of one scalar'
1082
1083    def checkSetandGetScalarDiffusivityInitialValue(self):
1084        """
1085        Check whether the DefineUserScalarsModel class could be set
1086        and get initial value of diffusivity.
1087        """
1088        model = DefineUserScalarsModel(self.case)
1089        zone = '1'
1090        model.addUserScalar(zone, 'premier')
1091        model.addUserScalar(zone, 'second')
1092        model.setScalarDiffusivityInitialValue('premier', 0.555)
1093
1094        doc = '''<additional_scalars>
1095                    <variable label="premier" name="user_1" type="user">
1096                            <initial_value zone_id="1">0.0</initial_value>
1097                            <min_value>-1e+12</min_value>
1098                            <max_value>1e+12</max_value>
1099                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
1100                                    <initial_value>0.555</initial_value>
1101                            </property>
1102                    </variable>
1103                    <variable label="second" name="user_2" type="user">
1104                            <initial_value zone_id="1">0.0</initial_value>
1105                            <min_value>-1e+12</min_value>
1106                            <max_value>1e+12</max_value>
1107                            <property choice="constant" label="Dscal2" name="diffusion_coefficient_2">
1108                                    <initial_value>1.83e-05</initial_value>
1109                            </property>
1110                    </variable>
1111                </additional_scalars>'''
1112
1113        assert model.scalar_node == self.xmlNodeFromString(doc),\
1114            'Could not set initial value of property of one user scalar'
1115        assert model.getScalarDiffusivityInitialValue('premier') == 0.555,\
1116            'Could not get initial value of property of one user scalar '
1117
1118    def checkSetandGetScalarDiffusivityChoice(self):
1119        """Check whether the DefineUserScalarsModel class could be set and get diffusivity's choice."""
1120        model = DefineUserScalarsModel(self.case)
1121        zone = '1'
1122        model.addUserScalar(zone, 'premier')
1123        model.addUserScalar(zone, 'second')
1124        model.setScalarDiffusivityChoice('premier', 'variable')
1125        doc = '''<additional_scalars>
1126                    <variable label="premier" name="user_1" type="user">
1127                            <initial_value zone_id="1">0.0</initial_value>
1128                            <min_value>-1e+12</min_value>
1129                            <max_value>1e+12</max_value>
1130                            <property choice="variable" label="Dscal1" name="diffusion_coefficient_1">
1131                                    <initial_value>1.83e-05</initial_value>
1132                            </property>
1133                    </variable>
1134                    <variable label="second" name="user_2" type="user">
1135                            <initial_value zone_id="1">0.0</initial_value>
1136                            <min_value>-1e+12</min_value>
1137                            <max_value>1e+12</max_value>
1138                            <property choice="constant" label="Dscal2" name="diffusion_coefficient_2">
1139                                    <initial_value>1.83e-05</initial_value>
1140                            </property>
1141                    </variable>
1142                </additional_scalars>'''
1143
1144        assert model.scalar_node == self.xmlNodeFromString(doc),\
1145            'Could not set choice of property of one user scalar'
1146        assert model.getScalarDiffusivityChoice('premier') == "variable",\
1147            'Could not get choice of property of one user scalar'
1148
1149    def checkDeleteScalarandGetScalarType(self):
1150        """
1151        Check whether the DefineUserScalarsModel class could be
1152        delete a user scalar and get type of the scalar.
1153        """
1154        model = DefineUserScalarsModel(self.case)
1155        zone = '1'
1156        model.addUserScalar(zone, 'premier')
1157
1158        from code_saturne.model.ThermalScalarModel import ThermalScalarModel
1159        ThermalScalarModel(self.case).setThermalModel('temperature_celsius')
1160        del ThermalScalarModel
1161
1162        model.addUserScalar(zone, 'second')
1163        model.addUserScalar(zone, 'troisieme')
1164        model.addUserScalar(zone, 'quatrieme')
1165
1166        assert model.getScalarType('premier') == 'user',\
1167            'Could not get type of one scalar'
1168
1169        model.deleteScalar('second')
1170
1171        doc = '''<additional_scalars>
1172                    <variable label="premier" name="user_1" type="user">
1173                            <initial_value zone_id="1">0.0</initial_value>
1174                            <min_value>-1e+12</min_value>
1175                            <max_value>1e+12</max_value>
1176                            <property choice="constant" label="Dscal1" name="diffusion_coefficient_1">
1177                                    <initial_value>1.83e-05</initial_value>
1178                            </property>
1179                    </variable>
1180                    <variable label="TempC" name="temperature_celsius" type="thermal">
1181                            <initial_value zone_id="1">20.0</initial_value>
1182                            <min_value>-1e+12</min_value>
1183                            <max_value>1e+12</max_value>
1184                    </variable>
1185                    <variable label="troisieme" name="user_3" type="user">
1186                            <initial_value zone_id="1">0.0</initial_value>
1187                            <min_value>-1e+12</min_value>
1188                            <max_value>1e+12</max_value>
1189                            <property choice="constant" label="Dscal4" name="diffusion_coefficient_3">
1190                                    <initial_value>1.83e-05</initial_value>
1191                            </property>
1192                    </variable>
1193                    <variable label="quatrieme" name="user_4" type="user">
1194                            <initial_value zone_id="1">0.0</initial_value>
1195                            <min_value>-1e+12</min_value>
1196                            <max_value>1e+12</max_value>
1197                            <property choice="constant" label="Dscal5" name="diffusion_coefficient_4">
1198                                    <initial_value>1.83e-05</initial_value>
1199                            </property>
1200                    </variable>
1201                </additional_scalars>'''
1202
1203        assert model.scalar_node == self.xmlNodeFromString(doc),\
1204            'Could not delete one scalar'
1205
1206
1207
1208def suite():
1209    """unittest function"""
1210    testSuite = unittest.makeSuite(UserScalarTestCase, "check")
1211    return testSuite
1212
1213
1214def runTest():
1215    """unittest function"""
1216    print("UserScalarTestTestCase")
1217    runner = unittest.TextTestRunner()
1218    runner.run(suite())
1219
1220
1221#-------------------------------------------------------------------------------
1222# End DefineUsersScalars
1223#-------------------------------------------------------------------------------
1224