# -*- 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 XML data model in which the user defines the physical
options of the treated case. This module defines also a very usefull
function for the NavigatorTree display updating, taking into account
the current options selected by the user.

This module contains the following classes and function:
- configureTree
- XMLmodel
- XMLmodelTestCase
"""

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


import sys, unittest


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


from XMLvariables import Variables
import Toolbox


#-------------------------------------------------------------------------------
# Function for the TreeNavigator update (Warning : this function is called
# at each time when the Tree is browsed)
#-------------------------------------------------------------------------------


def configureTree(tree, case):
    """
    This function allows to configure the entry with the options contained
    in the case.
    """    
    tree.hlist.hide_entry('lagran')
    tree.hlist.hide_entry('models/flame')
    tree.hlist.hide_entry('models/species')
    tree.hlist.hide_entry('models/pucoal')
    tree.hlist.hide_entry('models/joule')
    tree.hlist.hide_entry('models/radiat')
    tree.hlist.hide_entry('output/solutray')
    tree.hlist.hide_entry('mtentr')
    tree.hlist.hide_entry('mtphys')

    if Toolbox.GuiParam.matisse :
        tree.hlist.show_entry('mtentr')
        tree.hlist.show_entry('mtphys')
        tree.hlist.hide_entry('models')
        tree.hlist.hide_entry('proper')
        tree.hlist.hide_entry('envirt/envelo')
        tree.hlist.hide_entry('scalar')
        tree.hlist.hide_entry('bounda')
        tree.hlist.hide_entry('numpar')
        tree.hlist.hide_entry('managt/rstart')
        return

    # Multi-phase flow
    #
    nodeLagr = case.xmlInitNode('lagrangian', 'model')

    if nodeLagr['model'] in ('one_way','two_ways','frozen'):
        tree.hlist.show_entry('lagran')
    else:
        nodeLagr['model'] = 'off'

    # Check if the folder 'models' shows something or not
    # 
    if tree.getmode('models') == 'open': return

    # Reactive flow
    #
    node0 =  case.xmlInitNode('thermophysical_models')
    node1 = node0.xmlInitNode('gas_combustion',     'model')
    node2 = node0.xmlInitNode('pulverized_coal',    'model')
    node3 = node0.xmlInitNode('joule_effect',       'model')
    node4 = node0.xmlInitNode('thermal_scalar',     'model')
    node5 = node0.xmlInitNode('radiative_transfer', 'model')

    if node1['model'] in ('ebu', 'd3p'):
        tree.hlist.show_entry('models/flame')
        tree.hlist.show_entry('models/radiat')
        tree.hlist.show_entry('output/solutray')
        tree.hlist.hide_entry('models/therma')
        node2.xmlSetAttribute(model='off')
        node3.xmlSetAttribute(model='off')
        node4.xmlSetAttribute(model='off')

    elif node2['model'] in ('coal_homo', 'coal_lagr'):
        tree.hlist.show_entry('models/species')
        tree.hlist.show_entry('models/pucoal')
        tree.hlist.show_entry('models/radiat')
        tree.hlist.show_entry('output/solutray')
        tree.hlist.hide_entry('models/therma')
        node1.xmlSetAttribute(model='off')
        node3.xmlSetAttribute(model='off')
        node4.xmlSetAttribute(model='off')

    elif node3['model'] in ('joule', 'arc'):
        tree.hlist.show_entry('models/joule')
        tree.hlist.show_entry('models/radiat')
        tree.hlist.show_entry('output/solutray')
        tree.hlist.hide_entry('models/therma')
        node1.xmlSetAttribute(model='off')
        node2.xmlSetAttribute(model='off')
        node4.xmlSetAttribute(model='off')

    else:
        tree.hlist.show_entry('models/therma')
        node1.xmlSetAttribute(model='off')
        node2.xmlSetAttribute(model='off')
        node3.xmlSetAttribute(model='off')
        if node4.xmlGetAttribute('model') != 'off':
            tree.hlist.show_entry('models/radiat')
            if node5.xmlGetAttribute('model') != 'off':
                tree.hlist.show_entry('output/solutray')
        else:
            node4.xmlSetAttribute(model='off')


#-------------------------------------------------------------------------------
# class XMLmodel
#-------------------------------------------------------------------------------


class XMLmodel(Variables):
    """
    This class initialize the XML contents of the case.
    """
    def __init__(self, case):
        """
        """
        self.case = case
        self.root = self.case.root()
        self.node_models = self.case.xmlGetNode('thermophysical_models')


    def getTurbModel(self):
        """
        This method return the turbilence model, but does not manage
        default values. Therefore...
        """
        nodeTurb = self.node_models.xmlGetNode('turbulence', 'model')
        return nodeTurb, nodeTurb['model']


    def getTurbVariable(self):
        """
        """
        nodeTurb, model = self.getTurbModel()
        nodeList = []

        if model in ('k-epsilon', 'k-epsilon-PL'):
            nodeList.append(nodeTurb.xmlGetNode('variable', name='turb_k'))
            nodeList.append(nodeTurb.xmlGetNode('variable', name='turb_eps'))

        elif model in ('Rij-epsilon', 'Rij-SSG'):
            for var in ('component_R11', 'component_R22', 'component_R33',
                        'component_R12', 'component_R13', 'component_R23',
                        'turb_eps'):
                nodeList.append(nodeTurb.xmlGetNode('variable', name=var))

        elif model in ('v2f-phi'):
            for var in ('turb_k', 'turb_eps', 'turb_phi', 'turb_fb'):
                nodeList.append(nodeTurb.xmlGetNode('variable', name=var))

        elif model in ('k-omega-SST'):
            nodeList.append(nodeTurb.xmlGetNode('variable', name='turb_k'))
            nodeList.append(nodeTurb.xmlGetNode('variable', name='turb_omega'))

        return nodeList


    def getTurbProperty(self):
        """
        """
        nodeTurb, model = self.getTurbModel()
        nodeList = []

        if model in ('mixing_length',
                     'k-epsilon',
                     'k-epsilon-PL',
                     'k-omega-SST',
                     'v2f-phi',
                     'Rij-epsilon',
                     'Rij-SSG'):
            nodeList.append(nodeTurb.xmlGetNode('property', name='turb_viscosity'))

        elif model in ('LES_Smagorinsky', 'LES_dynamique'):
            nodeList.append(nodeTurb.xmlGetNode('property', name='smagorinsky_constant'))

        return nodeList


    def getTurbNodeList(self):
        """
        """
        nodeList = []
        for node in self.getTurbVariable(): nodeList.append(node)
        for node in self.getTurbProperty(): nodeList.append(node)

        return nodeList


    def getThermalModel(self):
        """
        """
        modelList = []
        node1 = self.node_models.xmlGetNode('gas_combustion',  'model')
        node2 = self.node_models.xmlGetNode('pulverized_coal', 'model')
        node3 = self.node_models.xmlGetNode('joule_effect',    'model')
        node4 = self.node_models.xmlGetNode('thermal_scalar',  'model')

        for node in (node1, node2, node3, node4):
            if node:
                if node['model'] != 'off':
                    modelList.append(node['model'])
                    nodeThermal = node

        if len(modelList) > 1:
            raise ValueError, "Erreur de model thermique dans le fichier XML"
        elif modelList == []:
            modelList.append('off')
            nodeThermal = None

        return nodeThermal, modelList[0]


    def getThermoPhysicalModel(self):
        """
        """
        nodeThermal, model = self.getThermalModel()
        if not nodeThermal:
            return 'off'
        else:
            return nodeThermal.el.tagName


    def getPuCoalScalProper(self):
        nodList = []
        node = self.node_models.xmlGetNode('pulverized_coal', 'model')
        model = node['model']
        varList = []
        if model != 'off':
            nodList = []
            for var in ('scalar','property'):
                nodList = node.xmlGetNodeList(var)
                for nodvar in nodList: varList.append(nodvar)

        return varList


    def getPuCoalScalars(self):
        nodList = []
        node = self.node_models.xmlGetNode('pulverized_coal', 'model')
        model = node['model']
        if model != 'off':
            nodList = node.xmlGetNodeList('scalar')

        return nodList


    def getAllVarScalProper(self):
        """
        We put in a list all variables scalars and properties nodes
        """
        varList = []
        node1 = self.node_models.xmlGetNode('gas_combustion',  'model')
        node2 = self.node_models.xmlGetNode('pulverized_coal', 'model')
        node3 = self.node_models.xmlGetNode('joule_effect',    'model')
        node4 = self.node_models.xmlGetNode('thermal_scalar',  'model')
        node5 = self.case.xmlGetNode('additional_scalars')

        node6 = self.node_models.xmlGetNode('velocity_pressure')
        node7 = self.node_models.xmlGetNode('turbulence')


        nodepp = self.case.xmlGetNode('physical_properties')
        #node8 = nodepp.xmlGetNode('fluid_properties')
        node8 = nodepp.xmlInitNode('fluid_properties')

        nodets = self.case.xmlGetNode('analysis_control')
        #node9 = nodets.xmlGetNode('time_parameters')
        node9 = nodets.xmlInitNode('time_parameters')

        nodepn = self.case.xmlGetNode('numerical_parameters')
        node10 = nodepn.xmlInitNode('velocity_pressure_coupling')

        nodList = []
        for node in (node1, node2, node3, node4, node5, 
                     node6, node7, node8, node9, node10):
            for var in ('scalar','variable','property'):
                nodList = node.xmlGetNodeList(var)
                for nodvar in nodList: varList.append(nodvar)

        return varList


    def getRadiativeModel(self):
        """
        """
        node  = self.node_models.xmlGetNode('radiative_transfer', 'model')
        if node :
            return node, node['model']
        else:
            return None, 'off'


    def getThermalScalar(self):
        """
        A modifier avec la prise en compte des scalaires modèles
        """
        nodeThermal, model = self.getThermalModel()
        nodeList = []

        if model != 'off' and nodeThermal:
            nodeList = nodeThermal.xmlGetNodeList('scalar', 'label', name=model)

        return nodeList


    def getThermalScalarLabel(self):
        """
        A modifier avec la prise en compte des scalaires modèles
        """
        nodeThermal, model = self.getThermalModel()

        var=""
        if model != 'off' and nodeThermal:
            node = nodeThermal.xmlGetNode('scalar', name=model)
            try:
                var = node['label']
            except:
                var = None

        return var


    def getAdditionalScalar(self):
        """
        """
        node0 = self.case.xmlGetNode('additional_scalars')
        return node0.xmlGetNodeList('scalar', type='user')


    def getAdditionalScalarProperty(self):
        """
        """
        nodeList = []
        for node in self.getAdditionalScalar():
            L = node.xmlGetNode('property',
                                name='diffusion_coefficient',
                                choice='variable')
            if L: nodeList.append(L)

        return nodeList


    def getFluidProperty(self):
        """
        """
        nodeList = []
        nodeThermal, model = self.getThermalModel()
        node0 = self.case.xmlGetNode('physical_properties')
        node1 = node0.xmlGetNode('fluid_properties')

        if node1:
            for prop in ('density', 'molecular_viscosity', 'specific_heat'):
                L = node1.xmlGetNode('property', name=prop, choice='variable')
                if L: nodeList.append(L)

            if model != 'off':
                L = node1.xmlGetNode('property', name='thermal_conductivity', choice='variable')
                if L: nodeList.append(L)

        return nodeList


    def getWeightMatrixProperty(self):
        """
        """
        nodeList = []
        node0 = self.case.xmlGetNode('numerical_parameters')
        node1 = node0.xmlGetNode('velocity_pressure_coupling', 'status')
        if node1:
            if node1['status'] == 'on':
                nodeList = node0.xmlGetNodeList('property')
        return nodeList


    def getTimeProperty(self):
        """
        """
        nodeList = []
        node0 = self.case.xmlGetNode('analysis_control')
        node1 = node0.xmlGetNode('time_parameters')

        if node1:
            if node1.xmlGetInt('time_passing'):
                node2 = node1.xmlGetNode('property', name='local_time_step')
                if node2:
                    nodeList.append(node2)

            for prop in ('courant_number', 'fourier_number'):
                L = node1.xmlGetNode('property', name=prop)
                if L: nodeList.append(L)
        
        return nodeList


    def getAllProperty(self):
        """
        """
        nodeList = []
        for node in self.getFluidVariable(): nodeList.append(node)
        for node in self.getTurbProperty(): nodeList.append(node)
        for node in self.getTimeProperty(): nodeList.append(node)

        return nodeList


#-------------------------------------------------------------------------------
# XMLmodel test case
#-------------------------------------------------------------------------------


class XMLmodelTestCase(unittest.TestCase):
    """
    """
    def setUp(self):
        """
        This method is executed before all "check" methods.
        """
        from Base.XMLengine import Case
        from Base.XMLinitialize import XMLinit
        Toolbox.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 checkXMLmodelInstantiation(self):
        """
        Check whether the Case class could be instantiated
        """
        xmldoc = None
        xmldoc = XMLmodel(self.case)
        assert xmldoc != None, 'Could not instantiate XMLmodel'

    def checkGetThermalModel(self):
        """
        Check whether the thermal model could be get.
        """
        doc = XMLmodel(self.case)
        node_coal = self.case.xmlGetNode('pulverized_coal', 'model')
        node_coal['model'] = "toto"
        nodeThermal, model = doc.getThermalModel()

        assert nodeThermal == node_coal, \
               'Could not use the getThermalModel method'
        assert model == "toto", \
               'Could not use the getThermalModel method'

    def checkGetThermoPhysicalModel(self):
        """
        Check whether the specific thermophysical model could be get.
        """
        doc = XMLmodel(self.case)
        node_coal = self.case.xmlGetNode('pulverized_coal', 'model')
        node_coal['model'] = "toto"
        model = doc.getThermoPhysicalModel()

        assert model == node_coal.el.tagName, \
               'Could not use the getTermoPhysicalModel method'

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

def runTest():
    print "XMLmodelTestCase to be completed..."
    runner = unittest.TextTestRunner()
    runner.run(suite())


#-------------------------------------------------------------------------------
# End of XMLmodel
#-------------------------------------------------------------------------------


syntax highlighted by Code2HTML, v. 0.9.1