# -*- 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 Page for the physical properties of the fluid.
These properties can be reference value or initial value

This module contens the following classes and function:
- FluidCaracteristicsModel
- FluidCaracteristicsView
- PageText
"""


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


import os, sys, unittest
import Tix
from Tkconstants import *


#-------------------------------------------------------------------------------
# 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
from Base.XMLmodel import XMLmodel


#-------------------------------------------------------------------------------
# Model class
#-------------------------------------------------------------------------------


class FluidCharacteristicsModel(Variables):
    """
    Class to manipulate Molecular Properties in xml file.
    """
    def __init__(self, case):
        """FluidCharacteristicsModel Constuctor."""
        self.case = case
        self.node_models = self.case.xmlGetNode('thermophysical_models')
        self.node_prop   = self.case.xmlGetNode('physical_properties')
        self.node_fluid  = self.node_prop.xmlInitNode('fluid_properties')

        self.node_density   = self.setNewFluidProperty(self.node_fluid, 'density')
        self.node_viscosity = self.setNewFluidProperty(self.node_fluid, 'molecular_viscosity')
        self.node_heat      = self.setNewFluidProperty(self.node_fluid, 'specific_heat')
        self.node_cond      = self.setNewFluidProperty(self.node_fluid, 'thermal_conductivity')


    def defaultFluidCharacteristicsValues(self):
        """Return in a dictionnary which contains default values"""
        default = {}

        #Initial values for properties: 20°C air at atmospheric pressure
        #.
        default['density']              = 1.17862
        default['molecular_viscosity']  = 1.83e-05
        default['specific_heat']        = 1017.24
        default['thermal_conductivity'] = 0.02495

        return default


    def getThermoPhysicalModel(self):
        """Get value of attribute "model" of thermophysical model node."""
        d = {}
        d['joule_effect'] = 'off'
        d['gas_combustion'] = 'off'
        d['pulverized_coal'] = 'off'
        d['thermal_scalar'] = 'off'

        doc = XMLmodel(self.case)
        node, model = doc.getThermalModel()
        d[doc.getThermoPhysicalModel()] = model

        return d['joule_effect'], d['thermal_scalar'], d['gas_combustion'], d['pulverized_coal']


    def getInitialValue(self, tag):
        """Get initial value of the markup tag."""
        node = self.node_fluid.xmlGetNode('property', name=tag)
        pp = node.xmlGetDouble('initial_value')
        if not pp:
            pp = self.defaultFluidCharacteristicsValues()[tag]
            self.setInitialValue(tag, pp)
        return pp


    def setInitialValue(self, tag, val):
        """Put initial value for the markup tag"""
        node = self.node_fluid.xmlGetNode('property', name=tag)
        node.xmlSetData('initial_value', val)


    def getInitialValueDensity(self):
        """Get initial value of density"""
        return self.getInitialValue('density')


    def setInitialValueDensity(self, val):
        """Put initial value for density"""
        self.setInitialValue('density', val)


    def getInitialValueViscosity(self):
        """Get initial value of viscosity"""
        return self.getInitialValue('molecular_viscosity')


    def setInitialValueViscosity(self, val):
        """Put initial value for viscosity"""
        self.setInitialValue('molecular_viscosity', val)


    def getInitialValueHeat(self):
        """Get initial value of specific heat"""
        return self.getInitialValue('specific_heat')


    def setInitialValueHeat(self, val):
        """Put initial value for specific heat"""
        self.setInitialValue('specific_heat', val)


    def getInitialValueCond(self):
        """Get initial value of conductivity"""
        return self.getInitialValue('thermal_conductivity')


    def setInitialValueCond(self, val):
        """Put initial value for conductivity"""
        self.setInitialValue('thermal_conductivity', val)


    def setListingAndRecordingStatus(self, node):
        """Put initial value for conductivity"""
        node.xmlInitNode('listing_printing')['status'] = 'off'
        node.xmlInitNode('postprocessing_recording')['status'] = 'off'


    def removeListingAndRecordingStatus(self, node):
        """Put initial value for conductivity"""
        if node.xmlGetNode('listing_printing'):
            node.xmlRemoveChild('listing_printing')
        if node.xmlGetNode('postprocessing_recording'):
            node.xmlRemoveChild('postprocessing_recording')


    def getChoiceNode(self, node):
        """Get choice of node"""
        return node['choice']


    def setChoiceNode(self, node, choice):
        """Put choice in xml file's node"""
        node['choice'] = choice


    def RemoveThermoConductNode(self):
        """Remove balise property for thermal_conductivity"""
        self.node_fluid.xmlRemoveChild('property', name='thermal_conductivity')


#-------------------------------------------------------------------------------
# View class
#-------------------------------------------------------------------------------


class FluidCharacteristicsView(TkPage.Page):
    """
    Class to open Molecular Properties Page.
    """
    def _tkControlVariables(self):
        """
        Tkinter variables declaration.
        """
        self.density   = Tix.StringVar()
        self.viscosity = Tix.StringVar()
        self.heat      = Tix.StringVar()
        self.cond      = Tix.StringVar()
        self.rho       = Tix.DoubleVar()
        self.nu        = Tix.DoubleVar()
        self.cp        = Tix.DoubleVar()
        self.al        = Tix.DoubleVar()


    def _pageControl(self):
        """
        Xml node declaration and supplementary default value settings.
        """
        self.mdl = FluidCharacteristicsModel(self.case)


    def getState(self, i, var, node, key, event=None):
        """
        Input variable state
        """
        self.stbar.busy()

        t = PageText()

        modl_joul, modl_thermo, modl_gas, modl_coal = self.mdl.getThermoPhysicalModel()

        if modl_gas != 'off' or modl_coal != 'off':
            if i == 1 or i == 2:
                self.b[i].disable('variable')
                self.b[i].config(state=DISABLED)
                self.mdl.setChoiceNode(node, 'constant')
                self.neta[i] = 0
                self.stbar.clear()

        elif i == 3 and modl_joul == 'off':
            if modl_thermo == 'off':
                pass
            else:
                self.mdl.setChoiceNode(node, var.get())
                if self.mdl.getChoiceNode(node) == 'variable':
                    self.stbar.set(t.MSG_USPHYV)
                    self.neta[i] = 1
                    self.mdl.removeListingAndRecordingStatus(node)

        else:
            self.mdl.setChoiceNode(node, var.get())

        if modl_joul != 'off':
            self.b[i].disable('constant')
            self.b[i].config(state=DISABLED)
            self.mdl.setChoiceNode(node, 'variable')
            self.mdl.removeListingAndRecordingStatus(node)
            self.neta[i] = 2

        else:
            if var.get() == 'variable':
                self.neta[i] = 1
                Tix.Label(self.w2[i], text=t.VALREF, width=15, anchor=E).grid(row=0, column=0, padx=10, pady=2,sticky=E)
            else:
                self.neta[i] = 0
                Tix.Label(self.w2[i], text=t.VALREF, width=15, anchor=E).grid(row=0, column=0, padx=10, pady=2, sticky=E)

        # we test for printing message to not forget subroutines
        #
        icompt=0
        for n in range(0,self.nbeta):
            if self.neta[n] == 1:
                icompt = 1
                self.stbar.set(t.MSG_USPHYV)
            elif self.neta[n] == 2:
                icompt = 2
                self.stbar.set(t.MSG_USELPH)
        if icompt == 0: self.stbar.clear()


        if var.get() == 'variable':
            self.mdl.removeListingAndRecordingStatus(node)
        else:
            self.mdl.setListingAndRecordingStatus(node)

        self.stbar.idle()



    def getRho(self, event=None):
        """
        Update the density
        """
        self.stbar.busy()

        modl_joul, modl_thermo, modl_gas, modl_coal = self.mdl.getThermoPhysicalModel()
        if modl_gas != 'off' or modl_coal != 'off':
            return

        if self.check2.hasType(self.e1[0], self.rho):
            self.mdl.setInitialValueDensity(self.rho.get())

        self.stbar.idle()


    def getNu(self, event=None):
        """
        Update the molecular viscosity
        """
        self.stbar.busy()

        if self.check2.hasType(self.e1[1],self.nu):	
            self.mdl.setInitialValueViscosity(self.nu.get())

        self.stbar.idle()


    def getCp(self, event=None):
        """
        Update the specific heat
        """
        self.stbar.busy()

        if self.check2.hasType(self.e1[2],self.cp):	
            self.mdl.setInitialValueHeat(self.cp.get())

        self.stbar.idle()


    def getAl(self, event=None):
        """
        Update the thermal conductivity
        """
        self.stbar.busy()

        modl_joul, modl_thermo, modl_gas, modl_coal = self.mdl.getThermoPhysicalModel()

        if self.check2.hasType(self.e1[3],self.al):
            # here, if we need of thermal conductivity when gas_combustion or pulverized coal,
            #we must add test to not forget self.lf[3]
            if modl_joul == 'off' and modl_thermo == 'off':
                self.lf[3].pack_forget()
            else:
                self.mdl.setInitialValueCond(self.al.get())

        self.stbar.idle()


    def _createWidgets(self):
        """
        Create the Page layout.
        """
        t = PageText()

        self.lf  = [0]*4
        self.w1  = [0]*4
        self.w2  = [0]*4
        self.b   = [0]*4
        self.e1  = [0]*4
        unite    = [0]*4
        text     = [0]*4
        lab1     = [0]*4

        for i, t1, t2, eta, var, unit, command, node, key, key2 \
                in [(0, t.DENSITY_TITLE,   'r',  self.density,   self.rho, 'kg/m3',  self.getRho, self.mdl.node_density,   'IROVAR', 'RO0'),
                    (1, t.VISCOSITY_TITLE, 'm',  self.viscosity, self.nu,  'kg/m/s', self.getNu,  self.mdl.node_viscosity, 'IVIVAR', 'VISCL0'),
                    (2, t.HEAT_TITLE,      t.CP, self.heat,      self.cp,  'J/kg/K', self.getCp,  self.mdl.node_heat,      'ICP'   , 'CP0'),
                    (3, t.AL_TITLE,        'l',  self.cond,      self.al,  'W/m/K',  self.getAl,  self.mdl.node_cond,      'IVISLS', 'VISLS0*CP0')]:

            self.lf[i] = Tix.LabelFrame(self.myPage, bg=self.bg, bd=2, label=t1, relief=FLAT)
            self.lf[i].label.config(font=fT)
            self.lf[i].pack(side=TOP, fill=X,padx=10, pady=10)

            self.w1[i] = Tix.Frame(self.lf[i].frame, relief=FLAT, width=20)
            self.w1[i].grid(row=0,column=0,padx=2,pady=2,sticky=W)
            self.b[i] = Tix.OptionMenu(self.w1[i], options='menubutton.width 6')
            self.b[i].menubutton.config(bd=2, relief=RAISED)
            self.b[i].grid(row=0, column=0, pady=10, padx=10, sticky=W)
            self.balloon.bind_widget(self.b[i], balloonmsg=t.KEYWORD+key)

            self.b[i].add_command('constant', label=t.CST)
            self.b[i].add_command('variable', label=t.VAR)
            self.b[i].config(variable=eta, command=TkPage.Callback(self.getState,i,eta,node,key))

            self.w2[i] = Tix.Frame(self.lf[i].frame, relief=FLAT)
            self.w2[i].grid(row=0,column=2,padx=2,pady=2,sticky=E)

            text[i] = Tix.Frame(self.w2[i],relief=FLAT)
            text[i].grid(row=0,column=1,padx=2,pady=2,sticky=E)

            if i == 2:
                lab1[i] = Tix.Label(text[i],text=t2)
                lab1[i].grid(row=0,column=0,padx=2,pady=2,sticky=W)
            else:
                lab1[i] = Tix.Label(text[i],font=fG,text=t2)
                lab1[i].grid(row=0,column=0,padx=2,pady=2,sticky=W)
            self.balloon.bind_widget(lab1[i], balloonmsg=t.KEYWORD+key2)

            self.e1[i] = Tix.Entry(text[i], bd=2, width=10, textvariable=var)
            self.e1[i].grid(row=0, column=1, padx=2, pady=10)
            self.e1[i].event_add("<<Event>>", "<Return>", "<Leave>", "<FocusOut>")
            self.e1[i].bind("<<Event>>", command)
            self.balloon.bind_widget(self.e1[i], balloonmsg=t.KEYWORD+key2)

            unite[i]=Tix.Label(text[i], text=unit)
            unite[i].grid(row=0, column=2, padx=2, pady=2, sticky=E)


    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.
        """
        t = PageText()
        #for count number of "eta" = variable to print message "usphyv"
        self.neta = [0]*4

        # OptionMenu initialization
        #

        modl_joul, modl_thermo, modl_gas, modl_coal = self.mdl.getThermoPhysicalModel()

        if modl_joul == 'off' and modl_thermo == 'off':
            self.lf[3].pack_forget()
            self.mdl.RemoveThermoConductNode()
            list = [(0,self.mdl.node_density), (1,self.mdl.node_viscosity), (2,self.mdl.node_heat)]
            self.nbeta = 3
        else:
            list = [ (0,self.mdl.node_density),
                     (1,self.mdl.node_viscosity),
                     (2,self.mdl.node_heat),
                     (3,self.mdl.node_cond)]
            self.nbeta = 4

        for i, node in list:
            choice = self.mdl.getChoiceNode(node)
            if choice:
                if modl_joul == 'off' and modl_thermo == 'off':
                    self.b[i].config(value=choice)
                else:
                    self.b[i].config(value=choice)

            else:
                if modl_joul == 'off' and modl_thermo == 'off':
                    self.b[i].config(value='constant')
                    self.mdl.setChoiceNode(node, 'constant')
                elif modl_thermo != 'off':
                    self.b[i].config(value='constant')
                    self.mdl.setChoiceNode(node, 'constant')

            if modl_joul != 'off':
                    self.b[i].config(value='variable')
                    self.b[i].disable('constant')
                    self.mdl.setChoiceNode(node, 'variable')

            if modl_gas != 'off' or modl_coal != 'off':
                if i == 0:
                    self.b[0].configure(state=DISABLED)
                    self.e1[0].config(state=DISABLED, bg='grey')

                    self.w1[0].grid_forget()
                    self.mdl.setChoiceNode(node, 'variable')
                    rho_dis = Tix.Label(self.lf[0].frame, text=t.PERFCT_GAS, fg='blue')
                    rho_dis.grid(row=0,column=0)
                else:
                    self.b[i].config(value='constant')
                    self.mdl.setChoiceNode(node, 'constant')

        # Entry initialization
        #
        if modl_gas != 'off' or modl_coal != 'off':
            self.rho.set('')
        else:
            val_rho = self.mdl.getInitialValueDensity()
            if val_rho:
                self.rho.set(val_rho)
            else:
                self.rho.set('1.17862')
                self.mdl.setInitialValueDensity('1.17862')

        val_nu = self.mdl.getInitialValueViscosity()
        if val_nu:
            self.nu.set(val_nu)
        else:
            self.nu.set('0.0000183')
            self.mdl.setInitialValueViscosity('0.0000183')

        val_cp = self.mdl.getInitialValueHeat()
        if val_cp:
            self.cp.set(val_cp)
        else:
            self.cp.set('1017.24')
            self.mdl.setInitialValueHeat('1017.24')

        if len(list) == 4:
            val_al= self.mdl.getInitialValueCond()
            if val_al:
                self.al.set(val_al)
            else:
                self.al.set('0.02495')
                self.mdl.setInitialValueCond('0.02495')


#-------------------------------------------------------------------------------
# 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.AL_TITLE          = "Conductivité Thermique"
            self.CP                = "Cp"
            self.CST               = "constant"
            self.DENSITY_TITLE     = "Masse Volumique"
            self.HEAT_TITLE        = "Chaleur Spécifique"
            self.KEYWORD           = "Mot clef Code Saturne : "
            self.PERFCT_GAS        = "Calcul par la loi\n des gaz parfaits"
            self.PRESSION          = "Pression"
            self.VALINI            = "Valeur\ninitiale"
            self.VALREF            = "Valeur de\nréférence"
            self.VAR               = "variable"
            self.VISCOSITY_TITLE   = "Viscosité dynamique"
        else:
            self.AL_TITLE          = "Thermal Conductivity"
            self.CP                = "Cp"
            self.CST               = "constant"
            self.DENSITY_TITLE     = "Density"
            self.HEAT_TITLE        = "Specific Heat"
            self.KEYWORD           = "Code_Saturne key word: "
            self.PERFCT_GAS        = "Calculation by\n perfect gas law"
            self.PRESSION          = "Pressure"
            self.VALINI            = "Initial\nvalue"
            self.VALREF            = "Referency\nvalue"
            self.VAR               = "variable"
            self.VISCOSITY_TITLE   = "Viscosity"

        # 2) Messages
        #
        if Tool.GuiParam.lang == 'fr':
            self.MSG_USELPH = "Intervention obligatoire dans le sous-programme "\
                              "uselph.F"
            self.MSG_USPHYV = "Intervention obligatoire dans le sous-programme "\
                              "usphyv.F"
        else:
            self.MSG_USELPH = "You have to complete the sub-routine uselph.F"
            self.MSG_USPHYV = "You have to complete the sub-routine usphyv.F"


#-------------------------------------------------------------------------------
# FluidCharacteristicsModel test case
#-------------------------------------------------------------------------------


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


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


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


    def checkGetInitialValue(self):
        """Check whether the getInitialValue for the properties could be get"""
        mdl = FluidCharacteristicsModel(self.case)
        tag = 'density'
        v = mdl.getInitialValue(tag)
        assert v == mdl.defaultFluidCharacteristicsValues()[tag], \
                 'Could not get property initial value'


    def checkSetInitialValue(self):
        """Check whether the setInitialValue for the properties could be get"""
        mdl = FluidCharacteristicsModel(self.case)
        tag = 'molecular_viscosity'
        w = 123.0
        mdl.setInitialValue(tag, w)
        v = mdl.getInitialValue(tag)
        assert v == w, 'Could not set property initial value'


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


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


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


syntax highlighted by Code2HTML, v. 0.9.1