# -*- coding: iso-8859-1 -*-
#
#-------------------------------------------------------------------------------
#                    Code_Saturne version 1.3
#                    ------------------------
#
#
#     This file is part of the Code_Saturne User Interface, element of the
#     Code_Saturne CFD tool.
#
#     Copyright (C) 1998-2007 EDF S.A., France
#
#     contact: saturne-support@edf.fr
#
#     The Code_Saturne User Interface is free software; you can redistribute it
#     and/or modify it under the terms of the GNU General Public License
#     as published by the Free Software Foundation; either version 2 of
#     the License, or (at your option) any later version.
#
#     The Code_Saturne User Interface is distributed in the hope that it will be
#     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
#     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with the Code_Saturne Kernel; if not, write to the
#     Free Software Foundation, Inc.,
#     51 Franklin St, Fifth Floor,
#     Boston, MA  02110-1301  USA
#
#-------------------------------------------------------------------------------


"""
This module defines the thermal scalar management.

This module contains the following classes and function:
- ThermalScalarModel
- ThermalScalarView
- PageText
- ThermalScalarTestCase
"""


#-------------------------------------------------------------------------------
# Library modules import
#-------------------------------------------------------------------------------


import Tix, unittest
from Tkconstants import *
import sys

#-------------------------------------------------------------------------------
# Application modules import
#-------------------------------------------------------------------------------


from Base.Common import *
import Base.Toolbox as Tool
import Base.Dialog as Dialog
import Base.TkPage as TkPage
from Base.XMLvariables import Variables


#-------------------------------------------------------------------------------
# Thermal scalar model class
#-------------------------------------------------------------------------------


class ThermalScalarModel(Variables):
    """
    The thermal scalar could be temperature
    (Celsius degrees or Kelvin) either enthalpy.
    """
    def __init__(self, case):
        """
        Constuctor.
        """
        self.case = case

        # TODO: the InitZoneView class !
        zone_label = "1"
        self.zone = zone_label

        self.node_models   = self.case.xmlGetNode('thermophysical_models')
        self.node_bc       = self.case.xmlGetNode('boundary_conditions')
        self.node_therm    = self.node_models.xmlInitChildNode('thermal_scalar', 'model')
        self.node_user_sca = self.case.xmlGetNode('additional_scalars')
        self.node_prop     = self.case.xmlGetNode('physical_properties').xmlGetNode('fluid_properties')

        self.node_coal  = self.node_models.xmlGetChildNode('pulverized_coal', 'model')
        self.node_joule = self.node_models.xmlGetChildNode('joule_effect',    'model')
        self.node_gas   = self.node_models.xmlGetChildNode('gas_combustion',  'model')
        self.node_ray   = self.node_models.xmlGetChildNode('radiative_transfer', 'model')

        self.old_scaTh = "off"

        self.thermalModel = ('off',
                             'temperature_celsius',
                             'temperature_kelvin',
                             'enthalpy')


    def defaultThermalScalarValues(self):
        """
        Return in a dictionnary which contains default values
        """
        default = {}
        default['thermal_scalar'] = "off"

        return default


    def getAllThermalScalarModel(self):
        """
        Return all defined thermal scalar in a tuple
        """
        return self.thermalModel


    def thermalScalarModelsList(self):
        """
        Create a tuple with the thermal scalar allowed by the analysis
        features (multi-phases model, and reactive flow models).
        """
        thermalScalarList = self.thermalModel

        for node in (self.node_gas, self.node_coal, self.node_joule):
            if node:
                if node['model'] != 'off':
                    thermalScalarList = ('off')

        return thermalScalarList


    def setThermalScalar(self, thermal_scalar):
        """
        Update the thermal scalar markup from the XML document.
        """
        if thermal_scalar not in self.thermalScalarModelsList():
            sys.exit(1)

        if thermal_scalar in ('temperature_celsius',
                              'temperature_kelvin',
                              'enthalpy'):

            self.old_scaTh = self.node_therm['model']
            self.node_therm['model'] = thermal_scalar
            self.setNewThermalScalar(self.node_therm, thermal_scalar, self.zone)
            self.setNewFluidProperty(self.node_prop, 'thermal_conductivity')

            l, u = self.getThermalScalarLabel()
            from DefineBoundaryRegions import DefBCModel
            for nature in ('inlet', 'outlet'):
                for bc in self.node_bc.xmlGetChildNodeList(nature):
                    DefBCModel(self.case).setCondTherm(bc, 'dirichlet', thermal_scalar, l, '0')
            del DefBCModel
        else:
            self.node_therm['model'] = 'off'
            self.RemoveThermTimeStep()

        # delete thermal scalar variance if the new thermal scalar
        # is different from the previous one
        #
        if thermal_scalar != self.old_scaTh:

            if self.old_scaTh == "off":
                old_label = ""
            else:
                old_label = Tool.dicoLabel(self.old_scaTh)

            self.cancelThermalVariance(old_label)

            nodeList1 = self.node_user_sca.xmlGetNodeList('scalar', type='todelete')
            for node in nodeList1:
                node.xmlRemoveNode()

#            nodeList2 = self.node_bc.xmlGetNodeList('scalar', type='todelete')
#            for node in nodeList2:
#                node.xmlRemoveNode()


    def thermalRadiativeModel(self):
        """
        """
        if self.node_ray['model'] != 'off':
            return 0
        else:
            return 1


    def getThermalScalar(self):
        """
        Return the current thermal scalar.
        """
        model = self.node_therm['model']
        if model not in self.thermalScalarModelsList():
            model = self.defaultThermalScalarValues()['thermal_scalar']
            self.setThermalScalar(model)

        return model


    def getThermalScalarLabel(self):
        """
        Return the label of the thermal scalar and its unity.
        """
        model = self.getThermalScalar()
        if model != 'off':
            node = self.node_therm.xmlGetNode('scalar',
                                              name=model,
                                              type='thermal')
            if not node: sys.exit(1)

            namesca = node['label']
            if model == "temperature_celsius":
                unit = "°C"
            elif model == "temperature_kelvin":
                unit = "Kelvin"
            elif model == "enthalpy":
                unit = "J/kg"
            else:
                sys.exit(1)
        else:
            namesca = 'off'
            unit = None

        return namesca, unit


    def cancelThermalVariance(self, label):
        """
        Delete the current selected entries from the Hlist and
        of course from the XML file.
        """
        if not label : return

        nodeList0 = self.node_user_sca.xmlGetNodeList('scalar')
#        nodeList1 = self.node_bc.xmlGetNodeList('scalar')

        for node0 in nodeList0:
            if node0.xmlGetString('variance') == label:
                node0['type'] = 'todelete'
                self.cancelThermalVariance(node0['label'])


    def RemoveThermTimeStep(self):
        """
        Remove node 'thermal_time_step' in time_parameters    
        we call function from TimeStepModel
        """
        from TimeStep import TimeStepModel
        TimeStepModel(self.case).RemoveThermalTimeStepNode()
        del TimeStepModel


    def turnOffThermalScalar(self):
        """
        When a reactive flow model is turned on, the thermal scalar
        is is set to off.
        """
        if self.node_therm['model'] == 'off':
            self.node_ray['model'] = 'off'
            self.RemoveThermTimeStep()


    def setInitialValue(self, nameZone, value):
        """
        set initial value on the nameZone zone
        """
        node_scal = self.node_therm.xmlGetChildNode('scalar')
        node_init = node_scal.xmlInitChildNode('initial_value', zone=nameZone)
        node_init.xmlSetTextNode(value)


#-------------------------------------------------------------------------------
# Main view class
#-------------------------------------------------------------------------------


class ThermalScalarView(TkPage.Page):
    """
    Class to open Thermal Scalar Transport Page.
    """
    def _dependsPages(self, name):
        """
        Construction of the list of dependencies Pages.
        """
#        self.case[name]['depends'] = ['models/initia',
#                                      'bounda/scalar']
        self.case[name]['depends'] = ['models/initia']


    def _tkControlVariables(self):
        """
        Tkinter variables declaration.
        """
        self.scalar = Tix.StringVar()


    def _pageControl(self):
        """
        Instantiate the thermal scalar modelling class.
        """
        self.thermal = ThermalScalarModel(self.case)


    def putThermalScalar(self, event=None):
        """
        Update the thermal scalar markup.
        """
        self.stbar.busy()
        th = self.scalar.get()

        self.thermal.setThermalScalar(th)

        if th in ('temperature_celsius', 'temperature_kelvin', 'enthalpy'):
            if self.myTree.tree.getmode('models') == 'close':
                self.myTree.tree.hlist.show_entry('models/radiat')

                if not self.thermal.thermalRadiativeModel():
                    self.myTree.tree.hlist.show_entry('output/solutray')
                else:
                    self.myTree.tree.hlist.hide_entry('output/solutray')

        else:
            if self.myTree.tree.getmode('models') == 'close':
                self.myTree.tree.hlist.hide_entry('models/radiat')
                self.myTree.tree.hlist.hide_entry('output/solutray')

        self.stbar.idle()


    def _createWidgets(self):
        """
        Create the Page layout.
        """
        t = PageText()
            
        lf = Tix.LabelFrame(self.myPage, bd=2, label=t.THERMAL_SCALAR, relief=FLAT)
        lf.label.config(font=fT)
        lf.pack(side=TOP, fill=X, padx=10, pady=10)

        # Button for the thermal scalar
        #
        self.b = Tix.OptionMenu(lf.frame, options='menubutton.width 45')
        self.b.menubutton.config(bd=2, relief=RAISED)
        self.balloon.bind_widget(self.b, statusmsg=t.MSG_SCALAR,
                                 balloonmsg=t.KEYWORD+' ISCALT, ISCSTH')
        
        self.b.pack(side=TOP, pady=15, padx=10)

        self.b.add_command('off', label=t.NO_SCALAR)
        self.b.add_separator('')
        self.b.add_command('temperature_celsius', label=t.TEMP_CELSIUS)
        self.b.add_command('temperature_kelvin', label=t.TEMP_KELVIN)
        self.b.add_command('enthalpy', label=t.ENTHALPY)

        self.b.config(variable=self.scalar , command= self.putThermalScalar)


    def _initializeWidgets(self):
        """
        Extract resquested informations from XML document.
        This informations are used to initialize the widgets.
        For this page default values of all widgets are necessary
        included in the XML file.
        """
        # Update the thermal scalar list with the analysis features
        #
        for sca in self.thermal.thermalModel:
            if sca not in self.thermal.thermalScalarModelsList():
                self.b.disable(sca)

        # Select the thermal scalar model
        #
        model = self.thermal.getThermalScalar()
        self.b.config(value=model)


#-------------------------------------------------------------------------------
# Text and messages for this page
#-------------------------------------------------------------------------------


class PageText:
    """
    Storage of all texts and messages for this page.
    """
    def __init__(self):
        
        # 1) Texts
        #
        if Tool.GuiParam.lang == 'fr':
            self.ENTHALPY          = "Enthalpie (J/kg)"
            self.KEYWORD           = "Mots clé Code_Saturne : "
            self.NO_SCALAR         = "Pas de scalaire thermique"
            self.TEMP_CELSIUS      = "Température (degrés Celsius)"
            self.TEMP_KELVIN       = "Température (Kelvin)"
            self.THERMAL_SCALAR    = "Transport d'un scalaire thermique"
        else:
            self.ENTHALPY          = "Enthalpy (J/kg)"
            self.KEYWORD           = "Code_Saturne key words: "
            self.NO_SCALAR         = "No thermal scalar"
            self.TEMP_CELSIUS      = "Temperature (Celsius degrees)"
            self.TEMP_KELVIN       = "Temperature (Kelvin)"
            self.THERMAL_SCALAR    = "Thermal scalar conservation"

        # 2) Messages
        #
        if Tool.GuiParam.lang == 'fr':
            self.MSG_SCALAR     = "Sélectionner le scalaire thermique"
        else:
            self.MSG_SCALAR     = "Select the thermal scalar"


#-------------------------------------------------------------------------------
# Turbulence test case
#-------------------------------------------------------------------------------


class ThermalScalarTestCase(unittest.TestCase):
    """
    """
    def setUp(self):
        """
        This method is executed before all "check" methods.
        """
##        from Base.XMLengine import Case
##        self.case = Case()
        from Base.XMLengine import Case, XMLDocument
        from Base.XMLinitialize import XMLinit
        Tool.GuiParam.lang = 'en'
        self.case = Case(None)
        XMLinit(self.case)
        self.doc = XMLDocument()


    def tearDown(self):
        """
        This method is executed after all "check" methods.
        """
        del self.case


    def checkThermalInstantiation(self):
        """
        Check whether the ThermalScalarModel class could be instantiated
        """
        model = None
        model = ThermalScalarModel(self.case)
        
        assert model != None, 'Could not instantiate ThermalScalarModel'


    def checkThermalScalarModelsList(self):
        """
        Check whether the ThermalScalarModelsList could be get
        """
        mdl = ThermalScalarModel(self.case)
        mdl.node_gas['model'] = 'on'
##        assert mdl.thermalScalarModelsList() == ('enthalpy'),\
        assert mdl.thermalScalarModelsList() == ('off'),\
            'Could not use the thermalScalarModelsList method'


    def checkSetTemperatureKelvin(self):
        """
        Check whether the temperature kelvin thermal scalar could be set
        """
        mdl = ThermalScalarModel(self.case)
        mdl.node_therm.xmlRemoveChild('scalar')
        mdl.node_prop.xmlRemoveChild('property')
        mdl.setThermalScalar('temperature_kelvin')

        truc = mdl.node_therm.toString()

        doc = '<thermal_scalar model="temperature_kelvin">'\
                '<scalar label="Temp.K" name="temperature_kelvin" type="thermal">'\
                    '<initial_value zone="1">293.15</initial_value>'\
                    '<min_value>-1e+12</min_value>'\
                    '<max_value>1e+12</max_value>'\
                '</scalar>'\
               '</thermal_scalar>'
        assert doc == truc, 'Could not set the temperature kelvin thermal scalar'

        truc = mdl.node_prop.toString()

        doc = '<fluid_properties>'\
                '<property choice="constant" label="Th. cond" name="thermal_conductivity">'\
                '<listing_printing status="off"/>'\
                '<postprocessing_recording status="off"/>'\
                '</property>'\
              '</fluid_properties>'

        assert doc == truc, 'Could not set the thermal conductivity property'


    def checkGetThermalScalar(self):
        """
        Check whether the thermal scalar could be get
        """
        mdl = ThermalScalarModel(self.case)
        mdl.setThermalScalar('enthalpy')

        assert mdl.getThermalScalar() == 'enthalpy', \
            'Could not get the thermal scalar'


    def checkGetThermalScalarLabel(self):
        """
        Check whether the thermal scalar label and unity could be get
        """
        mdl = ThermalScalarModel(self.case)
        mdl.setThermalScalar('enthalpy')
        node = mdl.node_therm.xmlGetNode('scalar', name='enthalpy')
        node['label'] = "H"
        n, u = mdl.getThermalScalarLabel()

        assert (n,u) == ('H','J/kg') , \
            'Could not get the thermal scalar label and unity'


def suite():
    testSuite = unittest.makeSuite(ThermalScalarTestCase, "check")
    return testSuite

    
def runTest():
    print "ThermalScalarTestCase"
    runner = unittest.TextTestRunner()
    runner.run(suite())


#-------------------------------------------------------------------------------
# End
#-------------------------------------------------------------------------------


syntax highlighted by Code2HTML, v. 0.9.1