#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""Pychemqt, Chemical Engineering Process simulator
Copyright (C) 2009-2017, Juan José Gómez Romera <jjgomera@gmail.com>

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 3 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, see <http://www.gnu.org/licenses/>."""


###############################################################################
#   Library for pump equipment definition
###############################################################################


import os

from PyQt5.QtWidgets import QApplication
from scipy import log, exp, optimize, polyval, roots, r_
from scipy.constants import g

from lib.unidades import (Pressure, Length, Power, VolFlow, Currency,
                          Dimensionless, DeltaP)
from lib.datasheet import pdf
from equipment.parents import equipment


class Pump(equipment):
    """Class to model a liquid pump

    Parameters:
        entrada: Corriente instance to define the input stream to equipment
        usarCurva:
            0   -   Use fixed parameters
            1   -   Use pump characteristic curve
        incognita: Index of variable to calculate if usarCurva is on
            0   -   Head
            1   -   Flow, in this case overwrite the input stream flow
        rendimiento: pump efficiency, necessary is not use characteristic curve
        deltaP: Pressure increase of pump, unnecessary is use the
            characteristic curve and the flow is the variable to calculate
        Pout: Output pressure of pump
        Carga: Head of pump
        curvaCaracteristica: array to define the characteristic curve of pump
            the format is: [Diameter, rpm, [Q1,..Qn], [h1,...,hn],
                            [Pot1,...,Potn], [NPSH1,...NPSHn]].
        diametro: nominal diameter of pump
        velocidad: rpm of pump

    Coste
        tipo_bomba
            0   -   Centrifugal pumps
            1   -   Reciprocating pumps
            2   -   Gear pumps
            3   -   Vertical mixed flow
            4   -   Vertical axial flow
        tipo_centrifuga
            0   -   One stage, 3550 rpm, VSC
            1   -   One stage, 1750 rpm, VSC
            2   -   One stage, 3550 rpm, HSC
            3   -   One stage, 1750 rpm, HSC
            4   -   Two stage, 3550 rpm, HSC
            5   -   Multistage, 3550 rpm, HSC
        Material
            0   -   Cast iron
            1   -   Case steel
            2   -   304 or 316 fittings
            3   -   Stainless steel 304 or 316
            4   -   Case Gould's alloy no. 20
            5   -   Nickel
            6   -   Monel
            7   -   ISO B
            8   -   ISO B
            9   -   Titanium
            10  -   Hastelloy C
            11  -   Ductile iron
            12  -   Bronze
        motor: Tipo de motor
            0   -   Open drip-proof
            1   -   Totally enclosed, fan-cooled
            2   -   Explosion-proof
        rpm
            0   -   3600 rpm
            1   -   1800 rpm
            2   -   1200 rpm

    >>> from lib.corriente import Corriente
    >>> c=Corriente(T=300, P=101325, caudalMasico=1, fraccionMolar=[1.])
    >>> bomba=Pump(entrada=c, rendimiento=0.75, deltaP=20*101325, tipo_bomba=1)
    >>> print("%0.5f" % bomba.power.hp)
    3.63596
    >>> print("%0.2f" % bomba.C_inst)
    3493.24
    """
    title = QApplication.translate("pychemqt", "Pump")
    help = ""
    kwargs = {
        "entrada": None,
        "usarCurva": 0,
        "incognita": 0,
        "rendimiento": 0.0,
        "deltaP": 0.0,
        "Pout": 0.0,
        "Carga": 0.0,
        "curvaCaracteristica": [],
        "diametro": 0.0,
        "velocidad": 0.0,

        "f_install": 2.8,
        "Base_index": 0.0,
        "Current_index": 0.0,
        "tipo_bomba": 0,
        "tipo_centrifuga": 0,
        "material": 0,
        "motor": 0,
        "rpm": 0}
    kwargsInput = ("entrada", )
    kwargsCheck = ("usarCurva", )
    kwargsValue = ("Pout", "deltaP", "rendimiento", "Carga", "diametro",
                   "velocidad")
    kwargsList = ("incognita", "tipo_bomba", "tipo_centrifuga", "material",
                  "motor", "rpm")
    calculateValue = ("PoutCalculada", "power", "headCalculada", "volflow",
                      "rendimientoCalculado")
    calculateCostos = ("C_bomba", "C_motor", "C_adq", "C_inst")
    indiceCostos = 7
    salida = [None]

    TEXT_BOMBA = (
        QApplication.translate("pychemqt", "Centrifugal"),
        QApplication.translate("pychemqt", "Reciprocating"),
        QApplication.translate("pychemqt", "Gear pump"),
        QApplication.translate("pychemqt", "Vertical mixed flow"),
        QApplication.translate("pychemqt", "Vertical axial flow"))
    TEXT_CENTRIFUGA = (
        QApplication.translate("pychemqt", "One stage, 3550 rpm, VSC"),
        QApplication.translate("pychemqt", "One stage, 1750 rpm, VSC"),
        QApplication.translate("pychemqt", "One stage, 3550 rpm, HSC"),
        QApplication.translate("pychemqt", "One stage, 1750 rpm, HSC"),
        QApplication.translate("pychemqt", "Two stage, 3550 rpm, HSC"),
        QApplication.translate("pychemqt", "Multistage, 3550 rpm, HSC"))
    TEXT_MATERIAL = (
        QApplication.translate("pychemqt", "Cast iron"),
        QApplication.translate("pychemqt", "Case steel"),
        QApplication.translate("pychemqt", "304 or 316 fittings"),
        QApplication.translate("pychemqt", "Stainless steel 304 or 316"),
        QApplication.translate("pychemqt", "Case Gould's alloy no. 20"),
        QApplication.translate("pychemqt", "Nickel"),
        QApplication.translate("pychemqt", "Monel (Ni-Cu)"),
        QApplication.translate("pychemqt", "ISO B"),
        QApplication.translate("pychemqt", "ISO C"),
        QApplication.translate("pychemqt", "Titanium"),
        QApplication.translate("pychemqt", "Hastelloy C (Ni-Fe-Mo)"),
        QApplication.translate("pychemqt", "Ductile iron"),
        QApplication.translate("pychemqt", "Bronze"))
    TEXT_MOTOR = (
        QApplication.translate("pychemqt", "Open drip-proof"),
        QApplication.translate("pychemqt", "Totally enclosed, fan-cooled"),
        QApplication.translate("pychemqt", "Explosion-proof"))
    TEXT_RPM = ("3600 RPM", "1800 RPM", "1200 RPM")

    @property
    def isCalculable(self):
        if self.kwargs["f_install"] and self.kwargs["Base_index"] and \
                self.kwargs["Current_index"]:
            self.statusCoste = True
        else:
            self.statusCoste = False

        if not self.kwargs["entrada"]:
            self.msg = QApplication.translate("pychemqt", "undefined input")
            self.status = 0
        else:
            P = self.kwargs["Pout"] or self.kwargs["deltaP"] \
                or self.kwargs["Carga"]
            if self.kwargs["usarCurva"]:
                if self.kwargs["incognita"]:
                    if P and self.kwargs["curvaCaracteristica"]:
                        self.msg = ""
                        self.status = 1
                        return True
                    elif P:
                        self.msg = QApplication.translate(
                            "pychemqt", "undefined pump curve")
                        self.status = 0
                    else:
                        self.msg = QApplication.translate(
                            "pychemqt", "undefined out pressure condition")
                        self.status = 0
                elif self.kwargs["curvaCaracteristica"]:
                    self.msg = ""
                    self.status = 1
                    return True
                else:
                    self.msg = QApplication.translate(
                        "pychemqt", "undefined pump curve")
                    self.status = 0
            else:
                if P and self.kwargs["rendimiento"]:
                    self.msg = ""
                    self.status = 1
                    return True
                elif P:
                    self.msg = QApplication.translate(
                        "pychemqt", "undefined efficiency")
                    self.status = 0
                else:
                    self.msg = QApplication.translate(
                        "pychemqt", "undefined out pressure condition")
                    self.status = 0

    def calculo(self):
        entrada = self.kwargs["entrada"]
        self.rendimientoCalculado = Dimensionless(self.kwargs["rendimiento"])

        if self.kwargs["Pout"]:
            DeltaP = Pressure(self.kwargs["Pout"]-entrada.P)
        elif self.kwargs["deltaP"]:
            DeltaP = Pressure(self.kwargs["deltaP"])
        elif self.kwargs["Carga"]:
            DeltaP = Pressure(self.kwargs["Carga"]*entrada.Liquido.rho*g)
        else:
            DeltaP = Pressure(0)

        if self.kwargs["usarCurva"]:
            b1 = self.kwargs["diametro"] != self.kwargs["curvaCaracteristica"][0]  # noqa
            b2 = self.kwargs["velocidad"] != self.kwargs["curvaCaracteristica"][1]  # noqa
            if b1 or b2:
                self.curvaActual = self.calcularCurvaActual()
            else:
                self.curvaActual = self.kwargs["curvaCaracteristica"]
            self.Ajustar_Curvas_Caracteristicas()

        if not self.kwargs["usarCurva"]:
            head = Length(DeltaP/g/entrada.Liquido.rho)
            power = Power(head*g*entrada.Liquido.rho*entrada.Q /
                          self.rendimientoCalculado)
            P_freno = Power(power*self.rendimientoCalculado)
        elif not self.kwargs["incognita"]:
            head = Length(polyval(self.CurvaHQ, entrada.Q))
            DeltaP = Pressure(head*g*entrada.Liquido.rho)
            power = Power(entrada.Q*DeltaP)
            P_freno = Power(polyval(self.CurvaPotQ, entrada.Q))
            self.rendimientoCalculado = Dimensionless(power/P_freno)
        else:
            head = Length(self.DeltaP/g/entrada.Liquido.rho)
            poli = [self.CurvaHQ[0], self.CurvaHQ[1], self.CurvaHQ[2]-head]
            Q = roots(poli)[0]
            power = Power(Q*self.DeltaP)
            entrada = entrada.clone(split=Q/entrada.Q)
            P_freno = Power(polyval(self.CurvaPotQ, Q))
            self.rendimientoCalculado = Dimensionless(power/P_freno)

        self.deltaP = DeltaP
        self.headCalculada = head
        self.power = power
        self.P_freno = P_freno
        self.salida = [entrada.clone(P=entrada.P+DeltaP)]
        self.Pin = entrada.P
        self.PoutCalculada = self.salida[0].P
        self.volflow = entrada.Q
        self.cp_cv = entrada.Liquido.cp_cv

    def Ajustar_Curvas_Caracteristicas(self):
        """Define the characteristic curve of pump, all input arrays must be
        of same dimension
            Q: volumetric flow, m3/s
            h: head, m
            Pot: power, hp
            NPSHr: net power suption head requered to avoid pump cavitation
        """
        Q = r_[self.curvaActual[2]]
        h = r_[self.curvaActual[3]]
        Pot = r_[self.curvaActual[4]]
        NPSH = r_[self.curvaActual[5]]

        # Function to fix
        def funcion(p, x):
            return p[0]*x**2+p[1]*x+p[2]

        # Residue
        def residuo(p, x, y):
            return funcion(p, x) - y

        inicio = r_[1, 1, 1]

        ajuste_h, exito_h = optimize.leastsq(residuo, inicio, args=(Q, h))
        self.CurvaHQ = ajuste_h

        ajuste_P, exito_P = optimize.leastsq(residuo, inicio, args=(Q, Pot))
        self.CurvaPotQ = ajuste_P

        def funcion_NPSH(p, x):
            return p[0]+p[1]*exp(p[2]*x)

        def residuo_NPSH(p, x, y):
            return funcion_NPSH(p, x) - y
        ajuste_N, ex = optimize.leastsq(residuo_NPSH, inicio, args=(Q, NPSH))
        self.CurvaNPSHQ = ajuste_N

    def calcularCurvaActual(self):
        """Calculate the actual characteristic curve at different rpm and
        diameter than the characteristic curve of pump using the affinity laws
        Ref: Perry 10.25, Table 10.7"""
        D1 = self.kwargs["curvaCaracteristica"][0]
        N1 = self.kwargs["curvaCaracteristica"][1]
        D2 = self.kwargs["diametro"]
        N2 = self.kwargs["velocidad"]

        Q1 = r_[self.kwargs["curvaCaracteristica"][2]]
        h1 = r_[self.kwargs["curvaCaracteristica"][3]]
        Pot1 = r_[self.kwargs["curvaCaracteristica"][4]]
        npsh1 = r_[self.kwargs["curvaCaracteristica"][5]]
        Q2 = Q1*D2/D1*N2/N1
        h2 = h1*N2**2/N1**2*D2**2/D1**2
        Pot2 = Pot1*N2**3/N1**3*D2**3/D1**3

        # This relation is not so exact than others
        npsh2 = npsh1*N2**2/N1**2*D2**2/D1**2

        return [D2, N2, Q2, h2, Pot2, npsh2]

    def coste(self):
        HP = self.power.hp
        LnHP = log(self.power.hp)
        Q = self.kwargs["entrada"].Q.galUSmin
        CI = self.kwargs["Current_index"]
        BI = self.kwargs["Base_index"]

        # Coste Bomba
        if self.kwargs["tipo_bomba"] == 0:  # Centrifugal pumps
            QH = log(Q*self.power.hp**0.5)
            Fm = [1., 1.35, 1.15, 2., 2., 3.5, 3.3, 4.95, 4.6, 9.7, 2.95,
                  1.15, 1.90]
            B1 = [0., 5.1029, 0.0632, 2.0290, 13.7321, 9.8849]
            B2 = [0., -1.2217, 0.2744, -0.2371, -2.8304, -1.6164]
            B3 = [0., 0.0771, -0.0253, 0.0102, 0.1542, 0.0834]

            fm = Fm[self.kwargs["material"]]
            b1 = B1[self.kwargs["tipo_centrifuga"]]
            b2 = B2[self.kwargs["tipo_centrifuga"]]
            b3 = B3[self.kwargs["tipo_centrifuga"]]

            Ft = exp(b1 + b2 * QH + b3 * QH**2)
            Cb = fm*Ft*1.55*exp(8.833-0.6019*QH+0.0519*QH**2)

        elif self.kwargs["tipo_bomba"] == 1:  # Reciprocating pumps
            if self.kwargs["material"] == 0:  # Case iron
                Cb = 40.*Q**0.81
            elif self.kwargs["material"] == 3:  # 316 Staineless steel
                Cb = 410.*Q**0.52
            elif self.kwargs["material"] == 12:  # Bronze
                Cb = 410.*1.4*Q**0.52
            elif self.kwargs["material"] == 5:  # Nickel
                Cb = 410.*1.86*Q**0.52
            elif self.kwargs["material"] == 6:  # Monel
                Cb = 410.*2.20*Q**0.52
            else:  # Material not available. Assume case iron
                Cb = 40.*Q**0.81

        elif self.kwargs["tipo_bomba"] == 2:  # Gear pumps
            Cb = 1000*exp(-0.0881+0.1986*log(Q)+0.0291*log(Q)**2)
        elif self.kwargs["tipo_bomba"] == 3:  # Vertical mixed flow
            Cb = 0.036*Q**0.82*1000
        elif self.kwargs["tipo_bomba"] == 4:  # Vertical axial flow
            Cb = 0.02*Q**0.78*1000

        C_bomba = Cb*CI/BI

        # Coste motor
        if self.kwargs["motor"] == 0:  # Open, drip-proof
            if self.kwargs["rpm"] == 0 and HP <= 7.5:
                a1, a2, a3 = 4.8314, 0.0966, 0.10960
            elif self.kwargs["rpm"] == 0 and 7.5 < HP <= 250.:
                a1, a2, a3 = 4.1514, 0.5347, 0.05252
            elif self.kwargs["rpm"] == 0 and HP > 250.:
                a1, a2, a3 = 4.2432, 1.03251, -0.03595
            elif self.kwargs["rpm"] == 1 and HP <= 7.5:
                a1, a2, a3 = 4.7075, -0.01511, 0.22888
            elif self.kwargs["rpm"] == 1 and 7.5 < HP <= 250:
                a1, a2, a3 = 4.5212, 0.47242, 0.04820
            elif self.kwargs["rpm"] == 1 and HP > 250.:
                a1, a2, a3 = 7.4044, -0.06464, 0.05448
            elif self.kwargs["rpm"] == 2 and HP <= 7.5:
                a1, a2, a3 = 4.9298, 0.30118, 0.12630
            elif self.kwargs["rpm"] == 2 and 7.5 < HP <= 250:
                a1, a2, a3 = 5.0999, 0.35861, 0.06052
            elif self.kwargs["rpm"] == 2 and HP > 250.:
                a1, a2, a3 = 4.6163, 0.88531, -0.02188
        elif self.kwargs["motor"] == 1:  # Totally enclosed, fan-cooled
            if self.kwargs["rpm"] == 0 and HP <= 7.5:
                a1, a2, a3 = 5.1058, 0.03316, 0.15374
            elif self.kwargs["rpm"] == 0 and 7.5 < HP <= 250.:
                a1, a2, a3 = 3.8544, 0.83311, 0.02399
            elif self.kwargs["rpm"] == 0 and HP > 250.:
                a1, a2, a3 = 5.3182, 1.08470, -0.05695
            elif self.kwargs["rpm"] == 1 and HP <= 7.5:
                a1, a2, a3 = 4.9687, -0.00930, 0.22616
            elif self.kwargs["rpm"] == 1 and HP > 7.5:
                a1, a2, a3 = 4.5347, 0.57065, 0.04609
            elif self.kwargs["rpm"] == 2 and HP <= 7.5:
                a1, a2, a3 = 5.1532, 0.28931, 0.14357
            elif self.kwargs["rpm"] == 2 and HP > 7.5:
                a1, a2, a3 = 5.3858, 0.31004, 0.07406
        elif self.kwargs["motor"] == 2:  # Explosion-proof
            if self.kwargs["rpm"] == 0 and HP <= 7.5:
                a1, a2, a3 = 5.3934, -0.00333, 0.15475
            elif self.kwargs["rpm"] == 0 and HP > 7.5:
                a1, a2, a3 = 4.4442, 0.60820, 0.05202
            elif self.kwargs["rpm"] == 1 and HP <= 7.5:
                a1, a2, a3 = 5.2851, 0.00048, 0.19949
            elif self.kwargs["rpm"] == 1 and HP > 7.5:
                a1, a2, a3 = 4.8178, 0.51086, 0.05293
            elif self.kwargs["rpm"] == 2 and HP <= 7.5:
                a1, a2, a3 = 5.4166, 0.31216, 0.10573
            elif self.kwargs["rpm"] == 2 and HP > 7.5:
                a1, a2, a3 = 5.5655, 0.31284, 0.07212

        CI = self.kwargs["Current_index"]
        BI = self.kwargs["Base_index"]
        C_motor = 1.2*exp(a1+a2*LnHP+a3*LnHP**2)*CI/BI

        self.C_bomba = Currency(C_bomba)
        self.C_motor = Currency(C_motor)
        self.C_adq = Currency(C_bomba+C_motor)
        self.C_inst = Currency(self.C_adq*self.kwargs["f_install"])

    def propTxt(self):
        txt = "#---------------"
        txt += QApplication.translate("pychemqt", "Calculate properties")
        txt += "-----------------#"+os.linesep
        txt += self.propertiesToText(range(8))

        if self.statusCoste:
            txt += os.linesep+"#---------------"
            txt += QApplication.translate(
                "pychemqt", "Preliminary Cost Estimation")
            txt += "-----------------#" + os.linesep
            txt += self.propertiesToText(range(8, 11))
            txt += self.propertiesToText(11, linesep=False)
            if self.kwargs["tipo_bomba"] == 0:
                txt += ", "
                txt += self.TEXT_CENTRIFUGA[self.kwargs["tipo_centrifuga"]]
            txt += os.linesep
            txt += self.propertiesToText(range(13, 19))

        return txt

    @classmethod
    def propertiesEquipment(cls):
        l = [(QApplication.translate("pychemqt", "Input Pressure"),
              "Pin", Pressure),
             (QApplication.translate("pychemqt", "Output Pressure"),
              "PoutCalculada", Pressure),
             (QApplication.translate("pychemqt", "Head"), "headCalculada",
              Length),
             (QApplication.translate("pychemqt", "Brake horsepower"),
              "P_freno", Power),
             (QApplication.translate("pychemqt", "Volumetric Flow"),
              "volflow", VolFlow),
             (QApplication.translate("pychemqt", "Power"), "power", Power),
             (QApplication.translate("pychemqt", "Efficiency"),
              "rendimientoCalculado", Dimensionless),
             ("Cp/Cv", "cp_cv", Dimensionless),
             (QApplication.translate("pychemqt", "Base index"),
              "Base_index", float),
             (QApplication.translate("pychemqt", "Current index"),
              "Current_index", float),
             (QApplication.translate("pychemqt", "Install factor"),
              "f_install", float),
             (QApplication.translate("pychemqt", "Pump Type"),
              ("TEXT_BOMBA", "tipo_bomba"), str),
             (QApplication.translate("pychemqt", "Centrifuge Type"),
              ("TEXT_CENTRIFUGA", "tipo_centrifuga"), str),
             (QApplication.translate("pychemqt", "Material"),
              ("TEXT_MATERIAL", "material"), str),
             (QApplication.translate("pychemqt", "Motor Type"),
              ("TEXT_MOTOR", "motor"), str),
             (QApplication.translate("pychemqt", "Motor RPM"),
              ("TEXT_RPM", "rpm"), str),
             (QApplication.translate("pychemqt", "Pump Cost"),
              "C_bomba", Currency),
             (QApplication.translate("pychemqt", "Motor Cost"),
              "C_motor", Currency),
             (QApplication.translate("pychemqt", "Purchase Cost"),
              "C_adq", Currency),
             (QApplication.translate("pychemqt", "Installed Cost"),
              "C_inst", Currency)]
        return l

    def writeStatetoJSON(self, state):
        """Write instance parameter to file"""
        state["deltaP"] = self.deltaP
        state["rendimientoCalculado"] = self.rendimientoCalculado
        state["headCalculada"] = self.headCalculada
        state["power"] = self.power
        state["P_freno"] = self.P_freno
        state["Pin"] = self.Pin
        state["PoutCalculada"] = self.PoutCalculada
        state["volflow"] = self.volflow
        state["statusCoste"] = self.statusCoste
        state["cp_cv"] = self.cp_cv

        if self.statusCoste:
            state["C_bomba"] = self.C_bomba
            state["C_motor"] = self.C_motor
            state["C_adq"] = self.C_adq
            state["C_inst"] = self.C_inst

        if self.kwargs["usarCurva"]:
            pass

    def readStatefromJSON(self, state):
        """Load instance parameter from saved file"""
        self.deltaP = DeltaP(state["deltaP"])
        self.rendimientoCalculado = Dimensionless(state["rendimientoCalculado"])  # noqa
        self.headCalculada = Length(state["headCalculada"])
        self.power = Power(state["power"])
        self.P_freno = Power(state["P_freno"])
        self.Pin = Pressure(state["Pin"])
        self.PoutCalculada = Pressure(state["PoutCalculada"])
        self.volflow = VolFlow(state["volflow"])
        self.cp_cv = Dimensionless(state["cp_cv"])
        self.statusCoste = state["statusCoste"]

        if self.statusCoste:
            self.C_bomba = Currency(state["C_bomba"])
            self.C_motor = Currency(state["C_motor"])
            self.C_adq = Currency(state["C_adq"])
            self.C_inst = Currency(state["C_inst"])

        if self.kwargs["usarCurva"]:
            pass
        self.salida = [None]

    def datamap2xls(self):
        datamap = (("PoutCalculada", "value", "H15"),
                   ("PoutCalculada", "unit", "I15"),
                   ("Pin", "value", "H16"),
                   ("Pin", "unit", "I16"), )
        return datamap

    def export2pdf(self):
        bomba = pdf("Bomba")
        bomba.bomba(self)
        bomba.dibujar()
        os.system("atril datasheet.pdf")

    def export2xls(self):
        import xlwt
        font0 = xlwt.Font()
        font0.bold = True
        font0.height = 300
        print((font0.height))

        style0 = xlwt.XFStyle()
        style0.font = font0

        style1 = xlwt.XFStyle()
        style1.num_format_str = 'D-MMM-YY'

        wb = xlwt.Workbook()
        ws = wb.add_sheet('A Test Sheet')

        ws.write(0, 0, 'Test', style0)
        ws.write(2, 0, 1)
        ws.write(2, 1, 1)
        ws.write(2, 2, xlwt.Formula("A3+B3"))

        wb.save('datasheet.xls')
        os.system("gnumeric datasheet.xls")

if __name__ == '__main__':
    import doctest
    doctest.testmod()

    # from lib.corriente import Corriente
    # agua=Corriente(T=300, P=1e5, caudalMasico=1, fraccionMasica=[1])
    # bomba=Pump()
    # Q=r_[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]/3600. #en m³/s
    # h=r_[15.5, 15.4, 15.3, 15.1, 14.8, 14.5, 14.1, 13.5, 12.7, 11.6]
    # Pot=r_[0.5, 0.53, 0.57, 0.61, 0.66, 0.71, 0.77, 0.83, 0.89, 0.97]*1000
    # NHPS=r_[0]*9
    # bomba(entrada=agua, usarCurva=1, calculo=1, DeltaP=5e5,
    #       curvaCaracteristica=[3.5, 1500, Q, h, Pot, NHPS])
    # print(bomba.headCalculada, "m")
    # print bomba.entrada.caudal_volumetrico.m3h, "m3h"
    # print bomba.rendimiento*100,  "%"