# -*- coding: utf-8 -*-

#-------------------------------------------------------------------------------

# This file is part of Code_Saturne, a general-purpose CFD tool.
#
# Copyright (C) 1998-2014 EDF S.A.
#
# This program 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.
#
# This program 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
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301, USA.

#-------------------------------------------------------------------------------

"""
This module defines the coal combustion thermal flow modelling management.

This module contains the following classes and function:
- CoalCombustionModel
- CoalCombustionTestCase
"""

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

import sys, unittest

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

from Base.Common import *
import Base.Toolbox as Tool
import Pages.IdentityAndPathesModel as IdentityAndPathesModel
from Base.XMLvariables import Variables, Model
from Base.XMLmodel import ModelTest
from Pages.FluidCharacteristicsModel import FluidCharacteristicsModel
from Pages.ThermalScalarModel import ThermalScalarModel
from Pages.ThermalRadiationModel import ThermalRadiationModel
from Pages.LocalizationModel import LocalizationModel
from Pages.Boundary import Boundary

#-------------------------------------------------------------------------------
# Solid fuel combustion model class
#-------------------------------------------------------------------------------

class CoalCombustionModel(Variables, Model):
    """
    """
    def __init__(self, case):
        """
        Constructor.
        """
        self.case = case

        self.node_models = self.case.xmlGetNode('thermophysical_models')
        self.node_lagr   = self.case.xmlGetNode('lagrangian', 'model')
        self.node_turb   = self.node_models.xmlGetNode('turbulence',   'model')
        self.node_fuel   = self.node_models.xmlInitNode('solid_fuels', 'model')

        self.coalCombustionModel = ('off', 'homogeneous_fuel', 'homogeneous_fuel_moisture',
                                    'homogeneous_fuel_moisture_lagr')


    def defaultValues(self):
        """
        Private method
        Return in a dictionnary which contains default values.
        """
        default = {}
        default['model']                                 = "off"
        default['diameter']                              = 0.000122
        default['mass_percent']                          = 0.1
        default['C_compo_dry']                           = 70.9
        default['H_compo_dry']                           = 4.6
        default['O_compo_dry']                           = 10.8
        default['N_compo_dry']                           = 0
        default['S_compo_dry']                           = 0
        default['C_coke_compo_dry']                      = 100
        default['H_coke_compo_dry']                      = 0.
        default['O_coke_compo_dry']                      = 0.
        default['N_coke_compo_dry']                      = 0.
        default['S_coke_compo_dry']                      = 0.
        default['O2_oxi']                                = 1
        default['N2_oxi']                                = 3.76
        default['H2O_oxi']                               = 0
        default['CO2_oxi']                               = 0
        default['PCIChoice']                             = 'LHV'
        default['PCIType']                               = 'dry_basis'
        default['diameter_type']                         = 'automatic'
        default['stoichiometric_coefficient']            = 'user_define'
        default['PCI']                                   = 0
        default['density']                               = 1200
        default['volatile_matter']                       = 0.
        default['ashes_enthalpy']                        = 0
        default['ashes_thermal_capacity']                = 1800
        default['rate_of_ashes_on_mass']                 = 11.5
        default['specific_heat_average']                 = 1800
        default['thermal_conductivity']                  = 1.e-5
        default['moisture']                              = 0.
        default['Y1']                                    = 0.416
        default['Y2']                                    = 0.582
        default['A1_pre-exponential_factor']             = 370000
        default['A2_pre-exponential_factor']             = 1.3e13
        default['E1_energy_of_activation']               = 74000
        default['E2_energy_of_activation']               = 250000
        default['HCN_NH3_partitionning_reaction_1']      = 0.5
        default['HCN_NH3_partitionning_reaction_2']      = 0.5
        default['pre-exp_constant']                      = 38.
        default['E_activation']                          = 15.96
        default['order_reaction']                        = "1"
        default['nitrogen_fraction']                     = 1
        default['nitrogen_concentration']                = 0.015
        default['nitrogen_in_char_at_low_temperatures']  = 0.8
        default['nitrogen_in_char_at_high_temperatures'] = 0.2
        default['percentage_HCN_char_combustion']        = 1.
        default['mean_devolatilisation_rate']            = 0
        default['refusal_value']                         = 0.001
        default['oxidant_type']                          = 'molar'
        default['fuel_type']                             = 'coal'
        default['NOx_formation']                         = 'on'
        default['CO2_Kinetics']                          = 'off'
        default['H2O_Kinetics']                          = 'off'
        default['improved_NOx_model']                    = 'off'
        default['reburning']                             = 'unused'

        return default


    def __coalCombustionModelsList(self):
        """
        Private method
        Create a tuple with the coal combustion models allowed
        by the calculation features.
        """
        coalCombustionList = self.coalCombustionModel

        if self.node_lagr and self.node_lagr['model'] != 'off':
            coalCombustionList = ('off', 'homogeneous_fuel_moisture_lagr')

        if self.node_turb != None:
            if self.node_turb['model'] not in ('k-epsilon',
                                               'k-epsilon-PL',
                                               'Rij-epsilon',
                                               'Rij-SSG',
                                               'Rij-EBRSM',
                                               'v2f-BL-v2/k',
                                               'k-omega-SST',
                                               'Spalart-Allmaras'):
                coalCombustionList = ('off',)
        else:
            coalCombustionList = ('off',)

        return coalCombustionList


    def __getVariableList(self):
        """
        Private method
        Create list of variables for a class
        """
        modelVariables =  ["n_p_", "x_p_coal_", "x_p_char_", "x_p_h_"]
        if self.getCoalCombustionModel() == 'homogeneous_fuel_moisture' or self.getCoalCombustionModel() == 'homogeneous_fuel_moisture_lagr':
            modelVariables.append("x_p_wt_")

        return modelVariables


    def __getPropertiesList(self):
        """
        Private method
        Create list of properties for a class
        """
        modelProperties = ["t_coal", "w_solid_coal", "rho_coal", "diameter_coal", "dissapear_rate_coal",
                                "m_transfer_v1_coal",  "m_transfer_v2_coal", "het_ts_o2_coal"]
        if self.getCoalCombustionModel() == 'homogeneous_fuel_moisture' or self.getCoalCombustionModel() == 'homogeneous_fuel_moisture_lagr':
            modelProperties.append("dry_ts_coal")

        if self.getCO2KineticsStatus() == 'on':
            modelProperties.append("het_ts_co2_coal")

        if self.getH2OKineticsStatus() == 'on':
            modelProperties.append("het_ts_h2o_coal")

        return modelProperties


    def __createModelVariableList(self):
        """
        Private method
        Create list of scalar for all fuels and classes
        """
        coalsNumber = self.getCoalNumber()      # total number of solid fuel
        classesNumber = self.getClassesNumber() # total number of class (diameter)

        lst = []

        # list of coal variables
        baseNames = ["fr_mv1_", "fr_mv2_"]
        for baseName in baseNames:
            for coal in range(0, coalsNumber):
                name = '%s%2.2i' % (baseName, coal+1)
                lst.append(name)

        # list of class variables
        baseNames = self.__getVariableList()
        for baseName in baseNames:
            for classe in range(0, classesNumber):
                name = '%s%2.2i' % (baseName, classe+1)
                lst.append(name)

        lst.append("fr_het_o2")

        if self.getCO2KineticsStatus() == "on":
            lst.append("fr_het_co2")

        if self.getH2OKineticsStatus() == "on":
            lst.append("fr_het_h2o")

        if self.getNOxFormationStatus() == "on":
            lst.append("x_c_hcn")
            lst.append("x_c_no")
            lst.append("x_c_h_ox")
            lst.append("x_c_nh3")

        if self.getCoalCombustionModel() == 'homogeneous_fuel_moisture' or self.getCoalCombustionModel() == 'homogeneous_fuel_moisture_lagr':
            lst.append("fr_h2o")

        if self.getOxidantNumber() >= 2:
            lst.append("fr_oxyd2")

        if self.getOxidantNumber() == 3:
            lst.append("fr_oxyd3")

        # ieqco2 fix to true
        lst.append("x_c_co2")

        lst.append("f1f2_variance")

        return lst


    def __createModelVariableMinMaxList(self):
        """
        Private method
        Create list of scalar for all fuels and classes for special min/max initialization
        """
        coalsNumber = self.getCoalNumber()      # total number of solid fuel
        classesNumber = self.getClassesNumber() # total number of class (diameter)

        lst = []

        # list of class variables
        baseNames =  ["x_p_h_"]
        for baseName in baseNames:
            for classe in range(0, classesNumber):
                name = '%s%2.2i' % (baseName, classe+1)
                lst.append(name)

        if self.getNOxFormationStatus() == "on":
            lst.append("x_c_h_ox")

        return lst


    def __createModelScalars(self):
        """
        Private method
        Create and update model scalar
        """
        previous_list = []
        nodes = self.node_fuel.xmlGetChildNodeList('variable')
        for node in nodes:
            previous_list.append(node['name'])

        new_list = self.__createModelVariableList()
        for name in previous_list:
            if name not in new_list:
                self.node_fuel.xmlRemoveChild('variable',  name = name)

        for name in new_list:
            if name not in previous_list:
                self.setNewVariable(self.node_fuel, name, tpe="model", label=name)


    def __createModelPropertiesList(self):
        """
        Private method
        Create list of properties for all fuels and classes
        """
        classesNumber = self.getClassesNumber()

        lst = ["t_gas", "rho_gas", "ym_chx1m", "ym_chx2m",
               "ym_co", "ym_o2", "ym_co2", "ym_h2o", "ym_n2",
               "ym_h2s", "ym_h2", "ym_hcn", "ym_nh3", "ym_so2",
               "xm", "balance_c", "balance_o", "balance_h"]

        baseNames = self.__getPropertiesList()

        for baseName in baseNames:
            for classe in range(0, classesNumber):
                name = '%s%2.2i' % (baseName, classe+1)
                lst.append(name)

        lst.append("intensity")

        if self.getNOxFormationStatus() == "on":
            lst.append("exp1")
            lst.append("exp2")
            lst.append("exp3")
            lst.append("exp4")
            lst.append("exp5")
            lst.append("f_hcn_dev")
            lst.append("f_hcn_het")
            lst.append("f_nh3_dev")
            lst.append("f_nh3_het")
            lst.append("f_no_hcn")
            lst.append("f_no_nh3")
            lst.append("f_no_het")
            lst.append("f_no_the")
            lst.append("c_no_hcn")
            lst.append("c_no_nh3")
            lst.append("f_hcn_rb")
            lst.append("c_no_rb")
            lst.append("exp_rb")

        return lst


    def __createModelProperties(self):
        """
        Private method
        Create and update model properties
        """
        previous_list = []
        nodes = self.node_fuel.xmlGetChildNodeList('property')
        for node in nodes:
            previous_list.append(node['name'])

        new_list = self.__createModelPropertiesList()
        for name in previous_list:
            if name not in new_list:
                self.node_fuel.xmlRemoveChild('property',  name = name)

        for name in new_list:
            if name not in previous_list:
                self.setNewProperty(self.node_fuel, name)


    def createModel(self) :
        """
        Private method
        Create scalars and properties when coal combustion is selected
        """
        self.node_fuel.xmlInitNode('CO2_kinetics', status = self.defaultValues()['CO2_Kinetics'])
        self.node_fuel.xmlInitNode('H2O_kinetics', status = self.defaultValues()['H2O_Kinetics'])
        self.node_fuel.xmlInitNode('NOx_formation', status = self.defaultValues()['NOx_formation'])
        self.__createModelScalars()
        self.__createModelProperties()


    def __updateWetScalarsAndProperty(self, model):
        """
        Private method
        Delete scalars x_p_wt_ and fr_h2o and property dry_ts_coal
        if model isn't 'homogeneous_fuel_moisture'
        """
        # TODO a supprimer doit etre appele si on change le modele uniquement
        if model != 'homogeneous_fuel_moisture' and self.getCoalCombustionModel() != 'homogeneous_fuel_moisture_lagr':
            nod = self.node_fuel.xmlGetNode('variable', type="model", name="fr_h2o")
            if nod:
                nod.xmlRemoveNode()
            for node in self.node_fuel.xmlGetNodeList('variable', type="model"):
                if node['name'][:6] == "x_p_wt_":
                    node.xmlRemoveNode()
            for node in self.node_fuel.xmlGetNodeList('property'):
                if node['name'][:6] == "dry_ts_coal":
                    node.xmlRemoveNode()


    def __updateSolidFuelCombustionDensity(self, model):
        """
        Private method
        Update the coal combustion model markup from the XML document.
        """
        self.isInList(model, self.__coalCombustionModelsList())

        mdl = FluidCharacteristicsModel(self.case)

        if model != 'off':
            mdl.setPropertyMode('density', 'variable')
            if mdl.getPropertyMode('density') == 'constant':
                mdl.setPropertyMode('density', 'variable')


    def __createCoalModelScalars(self, coalsNumber, coalClassesNumber, classesNumber):
        """
        Private method
        Create new scalars for one coal
        """
        # add new scalars
        baseNames = self.__getVariableList()

        for baseName in baseNames:
            for classe in range(classesNumber - coalClassesNumber, classesNumber):
                name = '%s%2.2i' % (baseName, classe+1)
                self.setNewVariable(self.node_fuel, name, tpe="model", label=name)

        baseNames = ["fr_mv1_", "fr_mv2_"]
        for baseName in baseNames:
            name = '%s%2.2i' % (baseName, coalsNumber)
            self.setNewVariable(self.node_fuel, name, tpe="model", label=name)


    def __createCoalModelProperties(self, coalsNumber, coalClassesNumber, classesNumber):
        """
        Private method
        Create new properties for one coal
        """
        # create new properties
        baseNames = self.__getPropertiesList()

        for baseName in baseNames:
            for classe in range(classesNumber - coalClassesNumber, classesNumber):
                name = '%s%2.2i' % (baseName, classe+1)
                self.setNewProperty(self.node_fuel, name)


    def __createClassModelProperties(self, classNum, classesNumber):
        """
        Private method
        Create class of model properties
        """
        baseNames = self.__getPropertiesList()

        # Rename other classes
        nodeList = self.node_fuel.xmlGetNodeList('property')
        if nodeList != None:
            for node in nodeList:
                oldName = node['name']
                if oldName[:-2] in baseNames :
                    oldNum = int(oldName[-2:])
                    if oldNum in range(classNum, classesNumber + 1):
                        name = '%s%2.2i' % (oldName[:-2], oldNum + 1)
                        node['name'] = name
                        if node['label'] == oldName:
                            node['label'] = name
        #
        # create new properties
        for i in range(len(baseNames)):
            name = '%s%2.2i' % (baseNames[i], classNum)
            self.setNewProperty(self.node_fuel, name)


    def __createClassModelScalars(self, classNum, classesNumber):
        """
        Private method
        Create a new coal and associated scalars
        """
        baseNames = self.__getVariableList()

        # Rename other classes
        nodeList = self.node_fuel.xmlGetNodeList('variable')
        if nodeList != None:
            for node in nodeList:
                oldName = node['name']
                if oldName[:-2] in baseNames :
                    oldNum = int(oldName[-2:])
                    if oldNum in range(classNum, classesNumber + 1):
                        name = '%s%2.2i' % (oldName[:-2], oldNum+1)
                        node['name'] = name
                        if node['label'] == oldName:
                            node['label'] = name

        # create new scalars
        for i in range(len(baseNames)):
            name = '%s%2.2i' % (baseNames[i], classNum)
            self.setNewVariable(self.node_fuel, name, tpe="model", label=name)


    @Variables.undoGlobal
    def setCoalCombustionModel(self, model):
        """
        Update the coal combustion model markup from the XML document.
        """
        self.isInList(model, self.__coalCombustionModelsList())

        self.node_fuel['model']  = model
        self.__updateScalarAndProperty(model)

        if model == 'off':
            ThermalScalarModel(self.case).setThermalModel('off')
        else:
            ThermalScalarModel(self.case).setThermalModel('enthalpy')


    def __updateScalarAndProperty(self, model):
        """
        Update scalars and properties depending on model
        """
        if model == 'off':
            for tag in ('variable',
                        'property',
                        'reference_mass_molar',
                        'reference_temperature'):
                for node in self.node_fuel.xmlGetNodeList(tag):
                    node.xmlRemoveNode()

            for zone in LocalizationModel('BoundaryZone', self.case).getZones():
                if zone.getNature() == "inlet":
                    Boundary("coal_inlet", zone.getLabel(), self.case).deleteCoals()

            self.node_fuel.xmlRemoveChild('oxidants')
            self.node_fuel.xmlRemoveChild('solid_fuel')
            self.node_fuel.xmlRemoveChild('CO2_kinetics')
            self.node_fuel.xmlRemoveChild('H2O_kinetics')
            self.node_fuel.xmlRemoveChild('NOx_formation')
            self.node_ray = self.node_models.xmlInitNode('radiative_transfer')
            self.node_ray.xmlRemoveChild('absorption_coefficient')

        else:
            self.createModel()
            self.createCoal()
            self.createOxidant()
            self.createCoalModelScalarsAndProperties()

            if model != 'homogeneous_fuel_moisture' and self.getCoalCombustionModel() != 'homogeneous_fuel_moisture_lagr':
                self.__updateWetScalarsAndProperty(model)


    @Variables.noUndo
    def getCoalCombustionModel(self):
        """
        Return the current coal combustion model.
        """
        model = self.node_fuel['model']

        if model not in self.__coalCombustionModelsList():
            model = self.defaultValues()['model']
            self.setCoalCombustionModel(model)
        else:
            self.__updateSolidFuelCombustionDensity(model)

        return model


    def createCoalModelScalarsAndProperties(self):
        """
        Create new scalars and new properties for one coal
        """
        coalsNumber = self.getCoalNumber()
        coalClassesNumber = self.getClassNumber(coalsNumber)
        classesNumber = self.getClassesNumber()

        # add new scalars and properties
        self.__createCoalModelScalars(coalsNumber, coalClassesNumber, classesNumber)
        self.__createCoalModelProperties(coalsNumber, coalClassesNumber, classesNumber)


    def createClassModelScalarsAndProperties(self, coalNumber):
        """
        Create class of model scalars and properties for one given coal
        """
        self.isInt(coalNumber)

        classNum = 0
        for coal in range(0, coalNumber):
            node= self.node_fuel.xmlGetNode('solid_fuel', fuel_id = str(coal + 1))
            diameter_type = self.getDiameterType(coal + 1)

            if diameter_type == 'automatic':
                classNum += len(node.xmlGetNodeList('diameter', 'class_id'))
            else:
                classNum += len(node.xmlGetNodeList('mass_percent', 'class_id'))

        classesNumber = self.getClassesNumber()

        # create new scalars
        self.__createClassModelScalars(classNum, classesNumber)
        self.__createClassModelProperties(classNum, classesNumber)


    def deleteCoalModelScalarsAndProperties(self, coalNumber):
        """
        Delete scalars and properties for one coal
        """
        self.isInt(coalNumber)

        for classId in range(self.getClassNumber(coalNumber), 0, -1):
            self.deleteClass(coalNumber, classId)

        # Remove fuel scalars
        baseNames = [ "fr_mv1_", "fr_mv2_"]
        nodeList = self.node_fuel.xmlGetNodeList('variable')
        if nodeList != None:
            for node in nodeList :
                nameNode = node['name']
                for baseName in baseNames:
                    name = '%s%2.2i' % (baseName, coalNumber)
                    if (nameNode == name):
                        node.xmlRemoveNode()

        # Rename other fuels
        nodeList = self.node_fuel.xmlGetNodeList('variable')
        if nodeList != None:
            for node in nodeList:
                oldName = node['name']
                if oldName[:-2] in baseNames :
                    oldNum = int(oldName[-2:])
                    if oldNum in range(coalNumber + 1, self.getCoalNumber() + 1):
                        name = '%s%2.2i' % (oldName[:-2], oldNum - 1)
                        node['name'] = name
                        if node['label'] == oldName:
                            node['label'] = name


    def deleteClassModelScalars(self, coalNumber, classeNumber):
        """
        delete scalar model for a define coalNumber and class number
        """
        self.isInt(coalNumber)
        self.isInt(classeNumber)

        classNum = 0
        if (coalNumber >= 1) :
            for coal in range(0, coalNumber - 1):
                classNum += self.getClassNumber(coal + 1)

        # global class number
        classNum += classeNumber

        # total class number
        classesNumber = self.getClassesNumber()

        # list of variables for a class
        baseNames = self.__getVariableList()

        # Remove coal classes
        nodeList = self.node_fuel.xmlGetNodeList('variable')
        if nodeList != None:
            for node in nodeList :
                nodeName = node['name']
                for baseName in baseNames:
                    name = '%s%2.2i' % (baseName, classNum)
                    if (nodeName == name):
                        node.xmlRemoveNode()

        # Rename other classes
        nodeList = self.node_fuel.xmlGetNodeList('variable')
        if nodeList != None:
            for node in nodeList:
                oldName = node['name']
                if oldName[:-2] in baseNames :
                    oldNum = int(oldName[-2:])
                    if oldNum in range(classNum + 1, classesNumber + 1):
                        name = '%s%2.2i' % (oldName[:-2], oldNum - 1)
                        node['name'] = name
                        if node['label'] == oldName:
                            node['label'] = name


    def deleteClassModelProperties(self, coalNumber, classeNumber):
        """
        delete properties model for a define coalNumber and class number
        """
        self.isInt(coalNumber)
        self.isInt(classeNumber)

        classNum = 0
        if (coalNumber >= 1) :
            for coal in range(0, coalNumber - 1):
                classNum += self.getClassNumber(coal + 1)
        # global class number
        classNum += classeNumber

        # total class number
        classesNumber = self.getClassesNumber()

        # list of properties for a class
        baseNames = self.__getPropertiesList()

        # Remove coal classes
        nodeList = self.node_fuel.xmlGetNodeList('property')
        if nodeList != None:
            for node in nodeList :
                nodeName = node['name']
                for baseName in baseNames:
                    name = '%s%2.2i' % (baseName, classNum)
                    if (nodeName == name):
                        node.xmlRemoveNode()

        # Rename other classes
        nodeList = self.node_fuel.xmlGetNodeList('property')
        if nodeList != None:
            for node in nodeList:
                oldName = node['name']
                if oldName[:-2] in baseNames :
                    oldNum = int(oldName[-2:])
                    if oldNum in range(classNum + 1, classesNumber + 1):
                        name = '%s%2.2i' % (oldName[:-2], oldNum - 1)
                        node['name'] = name
                        if node['label'] == oldName:
                            node['label'] = name


    @Variables.noUndo
    def getFuelNameList(self):
        """
        Return the fuel name list
        """
        fuel = []
        for node in self.node_fuel.xmlGetNodeList('solid_fuel'):
            fuel.append(node['name'])
        return fuel


    @Variables.noUndo
    def getFuelIdList(self):
        """
        return list of fuel Id's
        """
        fuel = []
        for node in self.node_fuel.xmlGetNodeList('solid_fuel'):
            fuel.append(node['fuel_id'])
        return fuel


    @Variables.noUndo
    def getLabelIdList(self):
        """
        return list of fuel label
        """
        fuel = []
        for node in self.node_fuel.xmlGetNodeList('solid_fuel'):
            fuel.append(node['name'])
        return fuel


    @Variables.noUndo
    def getCoalNumber(self):
        """
        return number of solid fuel
        """
        nb = len(self.node_fuel.xmlGetNodeList('solid_fuel'))
        return nb


    @Variables.noUndo
    def getClassIdList(self, fuelId):
        """
        return list of class_id for define fuel id
        """
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_classe = solid_fuel.xmlInitNode('class')
        diameter_type = self.getDiameterType(fuelId)
        class_list= []
        if diameter_type == 'automatic':
            for node in node_classe.xmlGetNodeList('diameter'):
                class_list.append(node['class_id'])
        elif diameter_type == 'rosin-rammler_law':
            for node in node_classe.xmlGetNodeList('mass_percent'):
                class_list.append(node['class_id'])
        return class_list


    @Variables.noUndo
    def getClassNumber(self, fuelId):
        """
        return number of class for define fuel id
        """
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_class = solid_fuel.xmlInitNode('class')
        diameter_type = self.getDiameterType(fuelId)
        nb = 0
        if diameter_type == 'automatic':
            nb = len(node_class.xmlGetNodeList('diameter'))
        elif diameter_type == 'rosin-rammler_law':
            nb = len(node_class.xmlGetNodeList('mass_percent'))
        return nb


    @Variables.noUndo
    def getClassesNumber(self):
        """
        return global number of class for fuel(s)
        """
        return len(self.case.xmlGetNodeList('diameter', 'class_id'))


    @Variables.noUndo
    def getRefusalIdList(self, fuelId):
        """
        return number of refusal for define fuel id
        """
        v = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        class_list= []
        for node in v.xmlGetNodeList('refusal'):
            class_list.append(node['id'])
        return class_list


    @Variables.noUndo
    def getRefusalNumber(self, id):
        """
        return global number of refusal
        """
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = id)
        nb = len(solid_fuel.xmlGetNodeList('refusal'))
        return nb


    @Variables.noUndo
    def getOxidantNumber(self):
        """
        return global number oxidant
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        nb = len(node_oxi.xmlGetNodeList('oxidant'))
        return nb


    @Variables.noUndo
    def getOxidantIdList(self):
        """
        return list of oxidant Id's
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        oxidant = []
        for node in node_oxi.xmlGetNodeList('oxidant'):
            oxidant.append(node['ox_id'])
        return oxidant


    @Variables.noUndo
    def createCoal(self):
        """
        create a new solid fuel
        """
        number = self.getCoalNumber()
        new = number + 1
        solid_fuel = self.node_fuel.xmlInitNode('solid_fuel', fuel_id = new)
        self.isLowerOrEqual(number, 3)
        self.createClass(new)
        char_comb = solid_fuel.xmlInitNode('char_combustion')
        char_comb.xmlInitNode('specie', nature= "O2")
        char_comb.xmlInitNode('specie', nature= "CO2")
        char_comb.xmlInitNode('specie', nature= "H2O")
        solid_fuel.xmlInitNode('nox_formation')


    def deleteSolidFuel(self, fuelId):
        """
        delete a solid fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.deleteCoalModelScalarsAndProperties(fuelId)
        node = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node.xmlRemoveNode()

        # update boundary conditions (1/2)
        for zone in LocalizationModel('BoundaryZone', self.case).getZones():
            label = zone.getLabel()
            nature = zone.getNature()
            if nature == "inlet":
                bc = Boundary("coal_inlet", label, self.case)
                bc.deleteCoalFlow(fuelId, self.getCoalNumber())

        self.__updateFuelId()


    def __updateFuelId(self):
        """
        """
        n = 0
        for node in self.node_fuel.xmlGetNodeList('solid_fuel'):
            if int(node['fuel_id']) > 0 :
                n = n + 1
                node['fuel_id'] = str(n)


    def createOxidant(self):
        """
        create a new oxidant
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        number = self.getOxidantNumber()
        new = number + 1
        node_oxi.xmlInitNode('oxidant', ox_id = new)
        self.isLowerOrEqual(number, 3)
        # update list of scalar
        self.__createModelScalars()
        self.__createModelProperties()


    def deleteOxidant(self, number):
        """
        delete an oxidant
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        self.isInList(str(number), self.getOxidantIdList())
        node = node_oxi.xmlGetNode('oxidant', ox_id = number)
        node.xmlRemoveNode()

        # Update boundary conditions
        for zone in LocalizationModel('BoundaryZone', self.case).getZones():
            label = zone.getLabel()
            nature = zone.getNature()
            if nature == "inlet":
                bc = Boundary("coal_inlet", label, self.case)
                oxi_max = bc.getOxidantNumber()
                if oxi_max >= number:
                    bc.setOxidantNumber(oxi_max-1)

        self.__updateOxidantId()


    def __updateOxidantId(self):
        """
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        n = 0
        for node in node_oxi.xmlGetNodeList('oxidant'):
            if int(node['ox_id']) > 0 :
                n = n + 1
                node['ox_id'] = str(n)


    @Variables.noUndo
    def getElementComposition(self, oxId, element):
        """
        return contribution of an element for a define oxidant
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        self.isInList(str(oxId), self.getOxidantIdList())
        oxidant = node_oxi.xmlGetNode('oxidant', ox_id = oxId)
        name = element + "_composition"
        value = oxidant.xmlGetDouble(name)
        if value == None:
            defName = element + "_oxi"
            value = self.defaultValues()[defName]
            self.setElementComposition(oxId, element, value)
        return value


    @Variables.undoLocal
    def setElementComposition(self, oxId, element, value):
        """
        set contribution of an element for a define oxidant
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        self.isInList(str(oxId), self.getOxidantIdList())
        self.isPositiveFloat(value)
        oxidant = node_oxi.xmlGetNode('oxidant', ox_id = oxId)
        name = element + "_composition"
        oxidant.xmlSetData(name, value)


    @Variables.noUndo
    def getOxidant(self, oxId):
        """
        return an oxidant
        """
        self.isInList(str(oxId), self.getOxidantIdList())
        O2  = self.getElementComposition(oxId, "O2")
        N2  = self.getElementComposition(oxId, "N2")
        H2O = self.getElementComposition(oxId, "H2O")
        CO2 = self.getElementComposition(oxId, "CO2")
        oxi = [id, O2, N2, H2O, CO2]
        return oxi


    @Variables.noUndo
    def getDiameterType(self, fuelId):
        """
        return diameter model for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)

        value = solid_fuel.xmlGetString('diameter_type')
        if value == '':
            value = self.defaultValues()['diameter_type']
            self.setDiameterType(fuelId, value)
        return value


    @Variables.undoGlobal
    def setDiameterType(self, fuelId, choice):
        """
        put diameter model for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(choice, ('automatic', 'rosin-rammler_law'))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        old_type = solid_fuel.xmlGetString('diameter_type')
        solid_fuel.xmlSetData('diameter_type', choice)
        if old_type != '':
            if old_type != choice:
                if old_type == 'rosin-rammler_law':
                    for node in solid_fuel.xmlGetNodeList('refusal'):
                        node.xmlRemoveNode()
                solid_fuel.xmlRemoveChild('class')
                # one class needed
                self.createClass(fuelId)

                if choice == 'rosin-rammler_law':
                    self.createRefusal(fuelId)


    def createClass(self, fuelId):
        """
        create a new diameter class for define fuel Id
        """
        number = self.getClassNumber(fuelId)
        new = number + 1
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_class = solid_fuel.xmlInitNode('class')
        diameter_type = self.getDiameterType(fuelId)
        if diameter_type == 'automatic':
            node_class.xmlInitNode('diameter', class_id = new)
            self.getDiameter(fuelId, new)
        elif diameter_type == 'rosin-rammler_law':
            node_class.xmlInitNode('mass_percent', class_id = new)
            self.getMassPercent(fuelId, new)

        # Update boundary conditions
        for zone in LocalizationModel('BoundaryZone', self.case).getZones():
            if zone.getNature() == "inlet":
                b = Boundary("coal_inlet", zone.getLabel(), self.case)
                b.updateCoalRatios(fuelId)


    def deleteClass(self, fuelId,  number):
        """
        delete a diameter class for a define fuel Id
        """
        self.isInList(str(number), self.getClassIdList(fuelId))

        self.deleteClassModelProperties(fuelId, number)
        self.deleteClassModelScalars(fuelId, number)

        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_class = solid_fuel.xmlInitNode('class')
        diameter_type = self.getDiameterType(fuelId)
        if diameter_type == 'automatic':
            node = node_class.xmlGetNode('diameter', class_id = number)
            node.xmlRemoveNode()
        elif diameter_type == 'rosin-rammler_law':
            node = node_class.xmlGetNode('mass_percent', class_id = number)
            node.xmlRemoveNode()

            # delete refusal if needed
            refusal_number = self.getRefusalNumber(fuelId)
            class_number = self.getClassNumber(fuelId)
            if refusal_number > class_number:
                for num in range (class_number + 1, refusal_number + 1):
                    self.deleteRefusal(fuelId, num)

        self.__updateClassId(fuelId)


    def __updateClassId(self, fuelId):
        """
        """
        n = 0
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_class = solid_fuel.xmlInitNode('class')
        diameter_type = self.getDiameterType(fuelId)
        if diameter_type == 'automatic':
            for node in node_class.xmlGetNodeList('diameter'):
                if int(node['class_id']) > 0 :
                    n = n + 1
                    node['class_id'] = str(n)
        elif diameter_type == 'rosin-rammler_law':
            for node in node_class.xmlGetNodeList('mass_percent'):
                if int(node['class_id']) > 0 :
                    n = n + 1
                    node['class_id'] = str(n)


    def createRefusal(self, fuelId):
        """
        create de new refusal for define fuel Id
        """
        number = 0
        number = self.getRefusalNumber(fuelId)
        new = number + 1
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        solid_fuel.xmlInitNode('refusal', id = new)
        self.getRefusalDiameter(fuelId, new)
        self.getRefusalValue(fuelId, new)


    def deleteRefusal(self, fuelId,  number):
        """
        delete a refusal for define fuel Id
        """
        self.isInList(str(number), self.getRefusalIdList(fuelId))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlGetNode('refusal', id = number)
        node.xmlRemoveNode()
        self.__updateRefusalId(fuelId)


    def __updateRefusalId(self, fuelId):
        """
        """
        n = 0
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        for node in solid_fuel.xmlGetNodeList('refusal'):
            if int(node['id']) > 0 :
                n = n + 1
                node['id'] = str(n)


    @Variables.noUndo
    def getRefusalDiameter(self, fuelId, refusal_number):
        """
        Return the refusal diameter for a define fuel Id  and refusal Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(str(refusal_number), self.getRefusalIdList(fuelId))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_refusal = solid_fuel.xmlGetNode('refusal', id = refusal_number)
        value = node_refusal.xmlGetDouble('diameter')
        if value == None:
            value = self.defaultValues()['diameter']
            self.setRefusalDiameter(fuelId, refusal_number, value)
        return value


    @Variables.undoLocal
    def setRefusalDiameter(self, fuelId, refusal_number, value):
        """
        Put the refusal diameter for a define fuel Id  and refusal Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(str(refusal_number), self.getRefusalIdList(fuelId))
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_refusal = solid_fuel.xmlGetNode('refusal', id = refusal_number)
        node_refusal.xmlSetData('diameter', value)


    @Variables.noUndo
    def getRefusalValue(self, fuelId, refusal_number):
        """
        Return the refusal value for a define fuel Id  and refusal Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(str(refusal_number), self.getRefusalIdList(fuelId))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_refusal = solid_fuel.xmlGetNode('refusal', id = refusal_number)
        value = node_refusal.xmlGetDouble('value')
        if value == None:
            value = self.defaultValues()['refusal_value']
            self.setRefusalValue(fuelId, refusal_number, value)
        return value


    @Variables.noUndo
    def getRefusal(self, fuelId, refusal_number):
        """
        Return all characteristics of a refusal
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(str(refusal_number), self.getRefusalIdList(fuelId))
        diameter = self.getRefusalDiameter(fuelId, refusal_number)
        value = self.getRefusalValue(fuelId, refusal_number)
        return [refusal_number, diameter, value]


    @Variables.undoLocal
    def setRefusalValue(self, fuelId, refusal_number, value):
        """
        Put the refusal value for a define fuel Id  and refusal Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(str(refusal_number), self.getRefusalIdList(fuelId))
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_refusal = solid_fuel.xmlGetNode('refusal', id = refusal_number)
        node_refusal.xmlSetData('value', value)


    @Variables.noUndo
    def getDiameter(self, fuelId, class_number):
        """
        Return diameter for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_class = solid_fuel.xmlGetNode('class')
        value = node_class.xmlGetDouble('diameter', class_id = class_number)
        if value == None:
            value = self.defaultValues()['diameter']
            self.setDiameter(fuelId, class_number, value)
        return value


    @Variables.undoLocal
    def setDiameter(self, fuelId, class_number, value):
        """
        Put diameter for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_class = solid_fuel.xmlGetNode('class')
        node_class.xmlSetData('diameter', value, class_id = class_number)


    @Variables.noUndo
    def getMassPercent(self, fuelId, class_number):
        """
        Return mass percent for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_classe = solid_fuel.xmlGetNode('class')
        value = node_classe.xmlGetDouble('mass_percent', class_id = class_number)
        if value == None:
            value = self.defaultValues()['mass_percent']
            self.setMassPercent(fuelId, class_number, value)
        return value


    @Variables.undoLocal
    def setMassPercent(self, fuelId, class_number, value):
        """
        Put mass percent for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node_class = solid_fuel.xmlGetNode('class')
        node_class.xmlSetData('mass_percent', value, class_id = class_number)


    @Variables.noUndo
    def getFuelLabel(self, fuelId):
        """
        Return label for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        label = solid_fuel['name']
        if label == None:
            label = self.__getDefaultLabel()
            self.setFuelLabel(fuelId, label)
        return label


    def __getDefaultLabel(self):
        """
        Determine a default label for a fuel
        """
        name = "SolidFuel_" + str(self.getCoalNumber())
        if name in self.getFuelNameList():
            labelNumber = 1
            name = "SolidFuel_" + str(labelNumber)
            while name in self.getFuelNameList():
                labelNumber += 1
                name = "SolidFuel_" + str(labelNumber)
        return name


    @Variables.undoLocal
    def setFuelLabel(self, fuelId, label):
        """
        Set a fuel label
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        solid_fuel['name']= label


    @Variables.noUndo
    def getFuelType(self, fuelId):
        """
        Return the type for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        fuel_type = solid_fuel['type']
        if fuel_type == None:
            fuel_type = self.defaultValues()['fuel_type']
            self.setFuelType(fuelId, fuel_type)
        return fuel_type


    @Variables.undoLocal
    def setFuelType(self, fuelId, fuel_type):
        """
        Set the type for a define fuel Id
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(fuel_type, ('biomass', 'coal' ))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        solid_fuel['type']= fuel_type


    @Variables.noUndo
    def getComposition(self, fuelId, element):
        """
        Return composition for a define fuel Id and an element
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        name = element + "_composition_on_dry"
        composition = solid_fuel.xmlGetDouble(name)
        if composition == None:
            defName = element + "_compo_dry"
            composition = self.defaultValues()[defName]
            self.setComposition(fuelId, element, composition)
        return composition


    @Variables.undoLocal
    def setComposition(self, fuelId, element, composition):
        """
        Set composition for a define fuel Id and an element
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(composition)
        name = element + "_composition_on_dry"
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        solid_fuel.xmlSetData(name, composition)


    @Variables.noUndo
    def getCokeComposition(self, fuelId, element):
        """
        Return composition for a define fuel Id and an element
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        name = element + "_coke_composition_on_dry"
        composition = solid_fuel.xmlGetDouble(name)
        if composition == None:
            defName = element + "_coke_compo_dry"
            composition = self.defaultValues()[defName]
            self.setCokeComposition(fuelId, element, composition)
        return composition


    @Variables.undoLocal
    def setCokeComposition(self, fuelId, element, composition):
        """
        Set composition for a define fuel Id and an element
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(composition)
        name = element + "_coke_composition_on_dry"
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        solid_fuel.xmlSetData(name, composition)


    @Variables.noUndo
    def getPCIValue(self, fuelId):
        """
        Return PCI Value for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('Heating_model')
        value = node.xmlGetDouble('value')
        if value == None:
            value = self.defaultValues()['PCI']
            self.setPCIValue(fuelId, value)
        return value


    @Variables.undoLocal
    def setPCIValue(self, fuelId, value):
        """
        Set PCI Value for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('Heating_model')
        node.xmlSetData('value', value)


    @Variables.noUndo
    def getPCIChoice(self, fuelId):
        """
        Return PCI choice for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('Heating_model')
        PCIChoice = node['choice']
        if PCIChoice == None:
            PCIChoice = self.defaultValues()['PCIChoice']
            self.setPCIChoice(fuelId, PCIChoice)
        return PCIChoice


    @Variables.undoLocal
    def setPCIChoice(self, fuelId, choice):
        """
        Set PCI choice for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(choice, ('LHV', 'HHV', 'IGT_correlation'))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('Heating_model')
        node['choice'] = choice
        if choice == 'IGT_correlation':
            node.xmlRemoveChild('value')
            node.xmlRemoveChild('type')


    @Variables.noUndo
    def getPCIType(self, fuelId):
        """
        Return PCI type for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('Heating_model')
        value = node.xmlGetString('type')
        if value == None:
            value = self.defaultValues()['PCIType']
            self.setPCIType(fuelId, value)
        return value


    @Variables.undoLocal
    def setPCIType(self, fuelId, choice):
        """
        Set PCI type for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(choice, ('dry_basis', 'dry_ash_free', 'as_received'))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('Heating_model')
        node.xmlSetData('type', choice)


    @Variables.noUndo
    def getProperty(self, fuelId, name):
        """
        Return value for a define fuel Id and property
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        value = solid_fuel.xmlGetDouble(name)
        if value == None:
            value = self.defaultValues()[name]
            self.setProperty(fuelId, name, value)
        return value


    @Variables.undoLocal
    def setProperty(self, fuelId, name, value):
        """
        Set value for a define fuel Id and property
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        solid_fuel.xmlSetData(name, value)


    @Variables.noUndo
    def getY1Y2(self, fuelId):
        """
        Return Y1Y2 value for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        node = devolatilisation.xmlInitNode('stoichiometric_coefficient')
        choice = node['type']
        if choice == None:
            choice = self.defaultValues()['stoichiometric_coefficient']
            self.setY1Y2(fuelId, choice)
        return choice


    @Variables.undoLocal
    def setY1Y2(self, fuelId, choice):
        """
        Set Y1Y2 value for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(choice, ('user_define', 'automatic_CHONS', 'automatic_formula'))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('stoichiometric_coefficient')
        node['type'] = choice
        node.xmlRemoveChild('Y1')
        node.xmlRemoveChild('Y2')


    @Variables.noUndo
    def getY1StoichiometricCoefficient(self, fuelId):
        """
        Return Y1 stoichiometric coefficient for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(self.getY1Y2(fuelId),('user_define', 'automatic_formula'))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        node = devolatilisation.xmlInitNode('stoichiometric_coefficient')
        value = devolatilisation.xmlGetDouble('Y1')
        if value == None:
            choice = self.getY1Y2(fuelId)
            if choice == 'automatic_formula':
                value = self.__Y1AutomaticFormula(fuelId)
            else:
                value = self.defaultValues()['Y1']
            self.setY1StoichiometricCoefficient(fuelId, value)
        return value


    @Variables.undoLocal
    def setY1StoichiometricCoefficient(self, fuelId, value):
        """
        Set Y1 stoichiometric coefficient for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(self.getY1Y2(fuelId),('user_define', 'automatic_formula'))
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        node = solid_fuel.xmlInitNode('stoichiometric_coefficient')
        node.xmlSetData('Y1', value)


    @Variables.noUndo
    def getY2StoichiometricCoefficient(self, fuelId):
        """
        Return Y2 stoichiometric coefficient for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(self.getY1Y2(fuelId),('user_define', 'automatic_formula'))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        node = devolatilisation.xmlInitNode('stoichiometric_coefficient')
        value = devolatilisation.xmlGetDouble('Y2')
        if value == None:
            choice = self.getY1Y2(fuelId)
            if choice == 'automatic_formula':
                value = self.__Y2AutomaticFormula(fuelId)
            else:
                value = self.defaultValues()['Y2']
            self.setY2StoichiometricCoefficient(fuelId, value)
        return value


    @Variables.undoLocal
    def setY2StoichiometricCoefficient(self, fuelId, value):
        """
        Set Y2 stoichiometric coefficient for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(self.getY1Y2(fuelId),('user_define', 'automatic_formula'))
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        node = solid_fuel.xmlInitNode('stoichiometric_coefficient')
        node.xmlSetData('Y2', value)

    def __Y1AutomaticFormula(self, fuelId):
        """
        Return Y1 automatic value for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        volatile_matter = self.getProperty(fuelId, "volatile_matter")
        ash_ratio = self.getProperty(fuelId, "rate_of_ashes_on_mass")
        moisture = self.getProperty(fuelId, "moisture")
        Y1 = (volatile_matter / 100) / (1 - ash_ratio / 100 - moisture / 100)
        return Y1

    def __Y2AutomaticFormula(self, fuelId):
        """
        Return Y2 automatic value for a fuel
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        Y1 = self.__Y1AutomaticFormula(fuelId)
        Y2 = 1.4 * Y1
        return Y2


    @Variables.noUndo
    def getHCNParameter(self, fuelId, param):
        """
        Return value for a define fuel Id and nitrogen partition parameter
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        value = devolatilisation.xmlGetDouble(param)
        if value == None:
            value = self.defaultValues()[param]
            self.setHCNParameter(fuelId, param, value)
        return value


    @Variables.undoLocal
    def setHCNParameter(self, fuelId, param, value):
        """
        Set value for a define fuel Id and nitrogen partition parameter
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        devolatilisation.xmlSetData(param, value)


    @Variables.noUndo
    def getDevolatilisationParameter(self, fuelId, param):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        value = devolatilisation.xmlGetDouble(param)
        if value == None:
            value = self.defaultValues()[param]
            self.setDevolatilisationParameter(fuelId, param, value)
        return value


    @Variables.undoLocal
    def setDevolatilisationParameter(self, fuelId, param, value):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        devolatilisation = solid_fuel.xmlInitNode('devolatilisation_parameters')
        devolatilisation.xmlSetData(param, value)


    @Variables.noUndo
    def getPreExponentialConstant(self, fuelId, specie):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        char_comb = solid_fuel.xmlGetNode('char_combustion')
        specie_node = char_comb.xmlGetNode('specie', nature = specie)
        value = specie_node.xmlGetDouble('pre-exponential_constant')
        if value == None:
            value = self.defaultValues()['pre-exp_constant']
            self.setPreExponentialConstant(fuelId, specie, value)
        return value


    @Variables.undoLocal
    def setPreExponentialConstant(self, fuelId, specie, value):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        char_comb = solid_fuel.xmlGetNode('char_combustion')
        specie_node = char_comb.xmlGetNode('specie', nature = specie)
        specie_node.xmlSetData('pre-exponential_constant', value)


    @Variables.noUndo
    def getEnergyOfActivation(self, fuelId, specie):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        char_comb = solid_fuel.xmlGetNode('char_combustion')
        specie_node = char_comb.xmlGetNode('specie', nature = specie)
        value = specie_node.xmlGetDouble('energy_of_activation')
        if value == None:
            value = self.defaultValues()['E_activation']
            self.setEnergyOfActivation(fuelId, specie, value)
        return value


    @Variables.undoLocal
    def setEnergyOfActivation(self, fuelId, specie, value):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        char_comb = solid_fuel.xmlGetNode('char_combustion')
        specie_node = char_comb.xmlGetNode('specie', nature= specie)
        specie_node.xmlSetData('energy_of_activation', value)


    @Variables.noUndo
    def getOrderOfReaction(self, fuelId, specie):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        char_comb = solid_fuel.xmlGetNode('char_combustion')
        specie_node = char_comb.xmlGetNode('specie', nature = specie)
        node = specie_node.xmlInitNode('order_of_reaction')
        choice = node['choice']
        if choice == None:
            choice = self.defaultValues()['order_reaction']
            self.setOrderOfReaction(fuelId, specie, choice)
        return choice


    @Variables.undoLocal
    def setOrderOfReaction(self, fuelId, specie, choice):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isInList(choice, ("1", "0.5"))
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        char_comb = solid_fuel.xmlGetNode('char_combustion')
        specie_node = char_comb.xmlGetNode('specie', nature = specie)
        node = specie_node.xmlInitNode('order_of_reaction')
        node['choice'] = choice


    @Variables.noUndo
    def getNOxFormationParameter(self, fuelId, parameter):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlInitNode('nox_formation')
        value = node.xmlGetDouble(parameter)
        if value == None:
            value = self.defaultValues()[parameter]
            self.setNOxFormationParameter(fuelId, parameter, value)
        return value


    @Variables.undoLocal
    def setNOxFormationParameter(self, fuelId, parameter, value):
        """
        """
        self.isInList(str(fuelId), self.getFuelIdList())
        self.isPositiveFloat(value)
        solid_fuel = self.node_fuel.xmlGetNode('solid_fuel', fuel_id = fuelId)
        node = solid_fuel.xmlGetNode('nox_formation')
        node.xmlSetData(parameter, value)


    @Variables.noUndo
    def getOxidantType(self):
        """
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        value = node_oxi.xmlGetString('oxidant_type')
        if value == '':
            value = self.defaultValues()['oxidant_type']
            self.setOxidantType(value)
        return value


    @Variables.undoLocal
    def setOxidantType(self, choice):
        """
        """
        node_oxi = self.node_fuel.xmlInitNode('oxidants')
        self.isInList(choice, ('volumic_percent', 'molar' ))
        node_oxi.xmlSetData('oxidant_type', choice)


    @Variables.noUndo
    def getReburning(self, fuelId):
        """
        """
        fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
        node = fuelNode.xmlGetNode("nox_formation")
        value = node.xmlGetString('reburning_model')
        if value == '':
            value = self.defaultValues()['reburning']
            self.setReburning(fuelId, value)
        return value


    @Variables.undoLocal
    def setReburning(self, fuelId, choice):
        """
        """
        self.isInList(choice, ('unused', 'chen', 'dimitriou'))
        fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
        node = fuelNode.xmlGetNode("nox_formation")
        node.xmlSetData('reburning_model', choice)


    @Variables.undoGlobal
    def setNOxFormationStatus(self, status):
        """
        put NOx formation status
        """
        self.isOnOff(status)

        node = self.node_fuel.xmlGetNode('NOx_formation')
        node['status'] = status
        if status == "off":
            for fuelId in range (1, self.getCoalNumber() + 1):
                fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
                devol_node = fuelNode.xmlGetNode("devolatilisation_parameters")
                nox_node = fuelNode.xmlGetNode("nox_formation")
                nox_node.xmlRemoveChild('nitrogen_fraction')
                nox_node.xmlRemoveChild('nitrogen_concentration')
                devol_node.xmlRemoveChild('HCN_NH3_partitionning_reaction_1')
                devol_node.xmlRemoveChild('HCN_NH3_partitionning_reaction_2')
        else:
            for fuelId in range (1, self.getCoalNumber() + 1):
                fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
                self.getNOxFormationParameter(fuelId, 'nitrogen_fraction')
                self.getNOxFormationParameter(fuelId, 'nitrogen_concentration')
                self.getNOxFormationParameter(fuelId, 'nitrogen_in_char_at_low_temperatures')
                self.getNOxFormationParameter(fuelId, 'nitrogen_in_char_at_high_temperatures')
                self.getNOxFormationParameter(fuelId, 'percentage_HCN_char_combustion')
                self.getHCNParameter(fuelId, 'HCN_NH3_partitionning_reaction_1')
                self.getHCNParameter(fuelId, 'HCN_NH3_partitionning_reaction_2')
        # update list of scalar
        self.__createModelScalars()
        self.__createModelProperties()


    @Variables.noUndo
    def getNOxFormationStatus(self):
        """
        get NOx formation status
        """
        node = self.node_fuel.xmlGetNode('NOx_formation')
        status = node['status']

        return status


    @Variables.undoGlobal
    def setNOxFormationFeature(self, fuelId, status):
        """
        put NOx formation status
        """
        self.isOnOff(status)

        fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
        node_nox = fuelNode.xmlGetNode("nox_formation")
        node = node_nox.xmlInitNode('improved_NOx_model')
        node['status'] = status


    @Variables.noUndo
    def getNOxFormationFeature(self, fuelId):
        """
        get NOx formation feature status
        """
        fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
        node_nox = fuelNode.xmlGetNode("nox_formation")
        node = node_nox.xmlGetNode('improved_NOx_model')
        if node == None:
            self.setNOxFormationFeature(fuelId, self.defaultValues()['improved_NOx_model'])
            node = node_nox.xmlGetNode('improved_NOx_model')
        status = node['status']

        return status


    @Variables.undoGlobal
    def setCO2KineticsStatus(self, status):
        """
        put CO2 Kinetics status
        """
        self.isOnOff(status)

        node = self.node_fuel.xmlGetNode('CO2_kinetics')
        node['status'] = status
        if status == "off":
            for fuelId in range (1, self.getCoalNumber() + 1):
                fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
                combu_node = fuelNode.xmlGetNode("char_combustion")
                co2_node = combu_node.xmlGetNode("specie", nature = "CO2")
                co2_node.xmlRemoveChild('pre-exponential_constant')
                co2_node.xmlRemoveChild('energy_of_activation')
                co2_node.xmlRemoveChild('order_of_reaction')
        else:
            for fuelId in range (1, self.getCoalNumber() + 1):
                self.getPreExponentialConstant(fuelId, "CO2")
                self.getEnergyOfActivation(fuelId, "CO2")
                self.getOrderOfReaction(fuelId, "CO2")
        # update list of scalar
        self.__createModelScalars()
        self.__createModelProperties()


    @Variables.noUndo
    def getCO2KineticsStatus(self):
        """
        get CO2 Kinetics status
        """
        node = self.node_fuel.xmlGetNode('CO2_kinetics')
        status = node['status']

        return status


    @Variables.undoGlobal
    def setH2OKineticsStatus(self, status):
        """
        put H2O Kinetics status
        """
        self.isOnOff(status)

        node = self.node_fuel.xmlGetNode('H2O_kinetics')
        node['status'] = status
        if status == "off":
            for fuelId in range (1, self.getCoalNumber() + 1):
                fuelNode = self.node_fuel.xmlGetNode("solid_fuel", fuel_id = fuelId)
                combu_node = fuelNode.xmlGetNode("char_combustion")
                h2o_node = combu_node.xmlGetNode("specie", nature = "H2O")
                h2o_node.xmlRemoveChild('pre-exponential_constant')
                h2o_node.xmlRemoveChild('energy_of_activation')
                h2o_node.xmlRemoveChild('order_of_reaction')
        else:
            for fuelId in range (1, self.getCoalNumber() + 1):
                self.getPreExponentialConstant(fuelId, "H2O")
                self.getEnergyOfActivation(fuelId, "H2O")
                self.getOrderOfReaction(fuelId, "H2O")
        # update list of scalar
        self.__createModelScalars()
        self.__createModelProperties()


    @Variables.noUndo
    def getH2OKineticsStatus(self):
        """
        get H2O Kinetics status
        """
        node = self.node_fuel.xmlGetNode('H2O_kinetics')
        status = node['status']

        return status


#-------------------------------------------------------------------------------
# SolidFuel combustion test case
#-------------------------------------------------------------------------------

class CoalCombustionModelTestCase(ModelTest):
    """
    """

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

    def checkSetAndGetCoalCombustionModel(self):
        """Check whether the CoalCombustionModel class could be set and get combustion model"""
        model = CoalCombustionModel(self.case)
        model.setCoalCombustionModel('coal_homo')

        doc = '''<solid_fuels model="coal_homo">
                    <variable label="NP_CP01" name="n_p_01" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCH_CP01" name="x_p_coal_01" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCK_CP01" name="x_p_char_01" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="ENT_CP01" name="x_p_h_01" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV101" name="fr_mv1_01" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV201" name="fr_mv2_01" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_HET" name="het_fraction" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_GAZ" name="t_gas"/>
                    <property label="ROM_GAZ" name="rho_gas"/>
                    <property label="YM_CHx1m" name="ym_chx1m"/>
                    <property label="YM_CHx2m" name="ym_chx2m"/>
                    <property label="YM_CO" name="ym_co"/>
                    <property label="YM_O2" name="ym_o2"/>
                    <property label="YM_CO2" name="ym_co2"/>
                    <property label="YM_H2O" name="ym_h2o"/>
                    <property label="YM_N2" name="ym_n2"/>
                    <property label="XM" name="xm"/>
                    <property label="Temp_CP01" name="t_coal01"/>
                    <property label="Frm_CP01" name="w_solid_coal01"/>
                    <property label="Rho_CP01" name="rho_coal01"/>
                    <property label="Dia_CK01" name="diameter_coal01"/>
                    <property label="Ga_DCH01" name="dissapear_rate_coal01"/>
                    <property label="Ga_DV101" name="m_transfer_v1_coal01"/>
                    <property label="Ga_DV201" name="m_transfer_v2_coal01"/>
                    <property label="Ga_HET_O201" name="het_ts_o2_coal01"/>
                    <property label="ntLuminance_4PI" name="ntLuminance_4PI"/>
            </solid_fuels>'''

        assert model.node_fuel == self.xmlNodeFromString(doc),\
           'Could not set a model of combustion'
        assert model.getCoalCombustionModel() == 'coal_homo',\
           'Could not get a model of combustion'


    def checkCreateSolidFuelModelScalarsAndProperties(self):
        """
        Check whether the CoalCombustionModel class could be
        created new variables and properties for one new coal
        """
        model = CoalCombustionModel(self.case)
        model.setCoalCombustionModel('coal_homo')

        model.createCoalModelScalarsAndProperties(coalThermoChModel)

        doc = '''<solid_fuels model="coal_homo">
                    <variable label="NP_CP01" name="n_p_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCH_CP01" name="x_p_coal_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCK_CP01" name="x_p_char_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="ENT_CP01" name="x_p_h_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV101" name="fr_mv1_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV201" name="fr_mv2_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_HET" name="het_fraction" type="model"><flux_reconstruction status="off"/></variable>
                    <property label="Temp_GAZ" name="t_gas"/>
                    <property label="ROM_GAZ" name="rho_gas"/>
                    <property label="YM_CHx1m" name="ym_chx1m"/>
                    <property label="YM_CHx2m" name="ym_chx2m"/>
                    <property label="YM_CO" name="ym_co"/>
                    <property label="YM_O2" name="ym_o2"/>
                    <property label="YM_CO2" name="ym_co2"/>
                    <property label="YM_H2O" name="ym_h2o"/>
                    <property label="YM_N2" name="ym_n2"/>
                    <property label="XM" name="xm"/>
                    <property label="Temp_CP01" name="t_coal01"/>
                    <property label="Frm_CP01" name="w_solid_coal01"/>
                    <property label="Rho_CP01" name="rho_coal01"/>
                    <property label="Dia_CK01" name="diameter_coal01"/>
                    <property label="Ga_DCH01" name="dissapear_rate_coal01"/>
                    <property label="Ga_DV101" name="m_transfer_v1_coal01"/>
                    <property label="Ga_DV201" name="m_transfer_v2_coal01"/>
                    <property label="Ga_HET_O201" name="het_ts_o2_coal01"/>
                    <property label="ntLuminance_4PI" name="ntLuminance_4PI"/>
                    <variable label="NP_CP02" name="n_p_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCH_CP02" name="x_p_coal_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCK_CP02" name="x_p_char_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="ENT_CP02" name="x_p_h_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV102" name="fr_mv1_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV202" name="fr_mv2_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_CP02" name="t_coal02"/>
                    <property label="Frm_CP02" name="w_solid_coal02"/>
                    <property label="Rho_CP02" name="rho_coal02"/>
                    <property label="Dia_CK02" name="diameter_coal02"/>
                    <property label="Ga_DCH02" name="dissapear_rate_coal02"/>
                    <property label="Ga_DV102" name="m_transfer_v1_coal02"/>
                    <property label="Ga_DV202" name="m_transfer_v2_coal02"/>
                    <property label="Ga_HET_O202" name="het_ts_o2_coal02"/>
            </solid_fuels>'''

        assert model.node_fuel == self.xmlNodeFromString(doc),\
            'Could not create newvariables and properties for new coal'


    def checkCreateClassModelScalarsAndProperties(self):
        """
        Check whether the CoalCombustionModel class could be
        created a new class of variables and properties for one coal
        """
        model = CoalCombustionModel(self.case)
        model.setCoalCombustionModel('coal_homo')

        model.createClassModelScalarsAndProperties(coalThermoChModel, 2)

        doc = '''<solid_fuels model="coal_homo">
                    <variable label="NP_CP01" name="n_p_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCH_CP01" name="x_p_coal_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCK_CP01" name="x_p_char_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="ENT_CP01" name="x_p_h_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV101" name="fr_mv1_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV201" name="fr_mv2_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_HET" name="het_fraction" type="model"><flux_reconstruction status="off"/></variable>
                    <property label="Temp_GAZ" name="t_gas"/>
                    <property label="ROM_GAZ" name="rho_gas"/>
                    <property label="YM_CHx1m" name="ym_chx1m"/>
                    <property label="YM_CHx2m" name="ym_chx2m"/>
                    <property label="YM_CO" name="ym_co"/>
                    <property label="YM_O2" name="ym_o2"/>
                    <property label="YM_CO2" name="ym_co2"/>
                    <property label="YM_H2O" name="ym_h2o"/>
                    <property label="YM_N2" name="ym_n2"/>
                    <property label="XM" name="xm"/>
                    <property label="Temp_CP01" name="t_coal01"/>
                    <property label="Frm_CP01" name="w_solid_coal01"/>
                    <property label="Rho_CP01" name="rho_coal01"/>
                    <property label="Dia_CK01" name="diameter_coal01"/>
                    <property label="Ga_DCH01" name="dissapear_rate_coal01"/>
                    <property label="Ga_DV101" name="m_transfer_v1_coal01"/>
                    <property label="Ga_DV201" name="m_transfer_v2_coal01"/>
                    <property label="Ga_HET_O201" name="het_ts_o2_coal01"/>
                    <property label="ntLuminance_4PI" name="ntLuminance_4PI"/>
                    <variable label="NP_CP03" name="n_p_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCH_CP03" name="x_p_coal_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCK_CP03" name="x_p_char_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="ENT_CP03" name="x_p_h_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV102" name="fr_mv1_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV202" name="fr_mv2_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_CP02" name="t_coal02"/>
                    <property label="Frm_CP02" name="w_solid_coal02"/>
                    <property label="Rho_CP02" name="rho_coal02"/>
                    <property label="Dia_CK02" name="diameter_coal02"/>
                    <property label="Ga_DCH02" name="dissapear_rate_coal02"/>
                    <property label="Ga_DV102" name="m_transfer_v1_coal02"/>
                    <property label="Ga_DV202" name="m_transfer_v2_coal02"/>
                    <property label="Ga_HET_O202" name="het_ts_o2_coal02"/>
                    <variable label="NP_CP04" name="n_p_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCH_CP04" name="x_p_coal_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCK_CP04" name="x_p_char_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="ENT_CP04" name="x_p_h_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV103" name="fr_mv1_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV203" name="fr_mv2_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_CP03" name="t_coal03"/>
                    <property label="Frm_CP03" name="w_solid_coal03"/>
                    <property label="Rho_CP03" name="rho_coal03"/>
                    <property label="Dia_CK03" name="diameter_coal03"/>
                    <property label="Ga_DCH03" name="dissapear_rate_coal03"/>
                    <property label="Ga_DV103" name="m_transfer_v1_coal03"/>
                    <property label="Ga_DV203" name="m_transfer_v2_coal03"/>
                    <property label="Ga_HET_O203" name="het_ts_o2_coal03"/>
                    <variable label="NP_CP02" name="n_p_02" type="model"/>
                    <variable label="XCH_CP02" name="x_p_coal_02" type="model"/>
                    <variable label="XCK_CP02" name="x_p_char_02" type="model"/>
                    <variable label="ENT_CP02" name="x_p_h_02" type="model"/>
                    <property label="Temp_CP04" name="t_coal04"/>
                    <property label="Frm_CP04" name="w_solid_coal04"/>
                    <property label="Rho_CP04" name="rho_coal04"/>
                    <property label="Dia_CK04" name="diameter_coal04"/>
                    <property label="Ga_DCH04" name="dissapear_rate_coal04"/>
                    <property label="Ga_DV104" name="m_transfer_v1_coal04"/>
                    <property label="Ga_DV204" name="m_transfer_v2_coal04"/>
                    <property label="Ga_HET_O204" name="het_ts_o2_coal04"/>
                </solid_fuels>'''

        assert model.node_fuel == self.xmlNodeFromString(doc),\
           'Could not create a new class of variables and properties for one coal'


    def checkDeleteSolidFuelModelScalarsAndProperties(self):
        """
        Check whether the CoalCombustionModel class could be
        deleted class of variables and properties for one given coal
        """
        model = CoalCombustionModel(self.case)
        model.setCoalCombustionModel('coal_homo')

        model.createClassModelScalarsAndProperties(coalThermoChModel, 2)
        model.deleteCoalModelScalarsAndProperties(coalThermoChModel, 1)

        doc = '''<solid_fuels model="coal_homo">
                    <variable label="NP_CP01" name="n_p_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCH_CP01" name="x_p_coal_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCK_CP01" name="x_p_char_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="ENT_CP01" name="x_p_h_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV101" name="fr_mv1_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV201" name="fr_mv2_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_HET" name="het_fraction" type="model"><flux_reconstruction status="off"/></variable>
                    <property label="Temp_GAZ" name="t_gas"/>
                    <property label="ROM_GAZ" name="rho_gas"/>
                    <property label="YM_CHx1m" name="ym_chx1m"/>
                    <property label="YM_CHx2m" name="ym_chx2m"/>
                    <property label="YM_CO" name="ym_co"/>
                    <property label="YM_O2" name="ym_o2"/>
                    <property label="YM_CO2" name="ym_co2"/>
                    <property label="YM_H2O" name="ym_h2o"/>
                    <property label="YM_N2" name="ym_n2"/>
                    <property label="XM" name="xm"/>
                    <property label="Temp_CP01" name="t_coal01"/>
                    <property label="Frm_CP01" name="w_solid_coal01"/>
                    <property label="Rho_CP01" name="rho_coal01"/>
                    <property label="Dia_CK01" name="diameter_coal01"/>
                    <property label="Ga_DCH01" name="dissapear_rate_coal01"/>
                    <property label="Ga_DV101" name="m_transfer_v1_coal01"/>
                    <property label="Ga_DV201" name="m_transfer_v2_coal01"/>
                    <property label="Ga_HET_O201" name="het_ts_o2_coal01"/>
                    <property label="ntLuminance_4PI" name="ntLuminance_4PI"/>
                    <variable label="NP_CP02" name="n_p_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCH_CP02" name="x_p_coal_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCK_CP02" name="x_p_char_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="ENT_CP02" name="x_p_h_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_CP02" name="t_coal02"/>
                    <property label="Frm_CP02" name="w_solid_coal02"/>
                    <property label="Rho_CP02" name="rho_coal02"/>
                    <property label="Dia_CK02" name="diameter_coal02"/>
                    <property label="Ga_DCH02" name="dissapear_rate_coal02"/>
                    <property label="Ga_DV102" name="m_transfer_v1_coal02"/>
                    <property label="Ga_DV202" name="m_transfer_v2_coal02"/>
                    <property label="Ga_HET_O202" name="het_ts_o2_coal02"/>
                    <variable label="NP_CP04" name="n_p_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCH_CP04" name="x_p_coal_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCK_CP04" name="x_p_char_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="ENT_CP04" name="x_p_h_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV102" name="fr_mv1_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV202" name="fr_mv2_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_CP04" name="t_coal04"/>
                    <property label="Frm_CP04" name="w_solid_coal04"/>
                    <property label="Rho_CP04" name="rho_coal04"/>
                    <property label="Dia_CK04" name="diameter_coal04"/>
                    <property label="Ga_DCH04" name="dissapear_rate_coal04"/>
                    <property label="Ga_DV104" name="m_transfer_v1_coal04"/>
                    <property label="Ga_DV204" name="m_transfer_v2_coal04"/>
                    <property label="Ga_HET_O204" name="het_ts_o2_coal04"/>
                </solid_fuels>'''

        assert model.node_fuel == self.xmlNodeFromString(doc),\
           "Could not delete one coal's variables and properties"


    def checkDeleteClassModelScalarsAndProperties(self):
        """
        Check whether the CoalCombustionModel class could be
        deleted class of variables and properties for one given coal
        """
        model = CoalCombustionModel(self.case)
        model.setCoalCombustionModel('coal_homo')

        model.createClassModelScalarsAndProperties(coalThermoChModel, 2)
        model.deleteClassModelScalars(coalThermoChModel, 2, 1)

        doc = '''<solid_fuels model="coal_homo">
                    <variable label="NP_CP01" name="n_p_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCH_CP01" name="x_p_coal_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="XCK_CP01" name="x_p_char_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="ENT_CP01" name="x_p_h_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV101" name="fr_mv1_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_MV201" name="fr_mv2_01" type="model"><flux_reconstruction status="off"/></variable>
                    <variable label="Fr_HET" name="het_fraction" type="model"><flux_reconstruction status="off"/></variable>
                    <property label="Temp_GAZ" name="t_gas"/>
                    <property label="ROM_GAZ" name="rho_gas"/>
                    <property label="YM_CHx1m" name="ym_chx1m"/>
                    <property label="YM_CHx2m" name="ym_chx2m"/>
                    <property label="YM_CO" name="ym_co"/>
                    <property label="YM_O2" name="ym_o2"/>
                    <property label="YM_CO2" name="ym_co2"/>
                    <property label="YM_H2O" name="ym_h2o"/>
                    <property label="YM_N2" name="ym_n2"/>
                    <property label="XM" name="xm"/>
                    <property label="Temp_CP01" name="t_coal01"/>
                    <property label="Frm_CP01" name="w_solid_coal01"/>
                    <property label="Rho_CP01" name="rho_coal01"/>
                    <property label="Dia_CK01" name="diameter_coal01"/>
                    <property label="Ga_DCH01" name="dissapear_rate_coal01"/>
                    <property label="Ga_DV101" name="m_transfer_v1_coal01"/>
                    <property label="Ga_DV201" name="m_transfer_v2_coal01"/>
                    <property label="Ga_HET_O201" name="het_ts_o2_coal01"/>
                    <property label="ntLuminance_4PI" name="ntLuminance_4PI"/>
                    <variable label="Fr_MV102" name="fr_mv1_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV202" name="fr_mv2_02" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_CP03" name="t_coal03"/>
                    <property label="Frm_CP03" name="w_solid_coal03"/>
                    <property label="Rho_CP03" name="rho_coal03"/>
                    <property label="Dia_CK03" name="diameter_coal03"/>
                    <property label="Ga_DCH03" name="dissapear_rate_coal03"/>
                    <property label="Ga_DV103" name="m_transfer_v1_coal03"/>
                    <property label="Ga_DV203" name="m_transfer_v2_coal03"/>
                    <property label="Ga_HET_O203" name="het_ts_o2_coal03"/>
                    <variable label="NP_CP04" name="n_p_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCH_CP04" name="x_p_coal_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="XCK_CP04" name="x_p_char_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="ENT_CP04" name="x_p_h_04" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV103" name="fr_mv1_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <variable label="Fr_MV203" name="fr_mv2_03" type="model">
                            <flux_reconstruction status="off"/>
                    </variable>
                    <property label="Temp_CP04" name="t_coal04"/>
                    <property label="Frm_CP04" name="w_solid_coal04"/>
                    <property label="Rho_CP04" name="rho_coal04"/>
                    <property label="Dia_CK04" name="diameter_coal04"/>
                    <property label="Ga_DCH04" name="dissapear_rate_coal04"/>
                    <property label="Ga_DV104" name="m_transfer_v1_coal04"/>
                    <property label="Ga_DV204" name="m_transfer_v2_coal04"/>
                    <property label="Ga_HET_O204" name="het_ts_o2_coal04"/>
                    <variable label="NP_CP02" name="n_p_02" type="model"/>
                    <variable label="XCH_CP02" name="x_p_coal_02" type="model"/>
                    <variable label="XCK_CP02" name="x_p_char_02" type="model"/>
                    <variable label="ENT_CP02" name="x_p_h_02" type="model"/>
                    <property label="Temp_CP02" name="t_coal02"/>
                    <property label="Frm_CP02" name="w_solid_coal02"/>
                    <property label="Rho_CP02" name="rho_coal02"/>
                    <property label="Dia_CK02" name="diameter_coal02"/>
                    <property label="Ga_DCH02" name="dissapear_rate_coal02"/>
                    <property label="Ga_DV102" name="m_transfer_v1_coal02"/>
                    <property label="Ga_DV202" name="m_transfer_v2_coal02"/>
                    <property label="Ga_HET_O202" name="het_ts_o2_coal02"/>
            </solid_fuels>'''

        assert model.node_fuel == self.xmlNodeFromString(doc),\
           "Could not delete one class of variables and properties for one given coal"


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


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

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