# -*- coding: utf-8 -*-
"""
hexayurt climate control

@author: Luke
"""
import numpy as np
from matplotlib import pyplot

######### assumed parameters ##########
#in imperial units, deltaT / R yields btu/hr-ft^2
R_1inch = 3.85
R_1inch_thermasheath = 6
R_1_5inch = 5.78
R_1_5inch_thermasheath = 9.6

R_tape = 0.05 #this was a typical value for paper.
tape_sqft = 1.0 #total area of gaps in insulation in an assembled yurt (complete guess).

# I estimated wall-> air convective transfer as 20 W/m^2/K based on this page: http://www.engineeringtoolbox.com/convective-heat-transfer-d_430.html
# and I converted with this http://www.unitconverter.org/heat-transfer-coefficient-conversion-chart.html
R_convection = 1.0/3.5 

cfmsAndRValuesToPlot = [(0.0,R_1inch),
                        (60.0,R_1inch), 
                        (70.0,R_1inch),
                        (60.0,R_1_5inch_thermasheath), 
                        (70.0,R_1_5inch_thermasheath),]
ASSUMED_HUMIDITY_CHANGE = 0.8

yurt_sqft = 12*4.0*8.0
shadowedTemperature = 90.0 #temperature of panels in shadow
shadowed_sqft = yurt_sqft * 0.5 #rough estimate of panel area in shadow
sunlitTemperature = shadowedTemperature + 20.0 #a guess at the outside temperature of panels in sunlight
sunlit_sqft = yurt_sqft * 0.5 #rough estimate of panel area in direct sunlight

initialInsideTemperature = 78.



humanBtuHrIn = 1 * 4.0 * 60. #one person's body heat. Ends up negligible.

######### physical constants ##########
POUNDS_PER_GALLON = 8.34
btuPerPoundEvaporate = 1042 #water's heat of evaporation at 90F, per https://www.engineeringtoolbox.com/water-properties-d_1573.html
wtPercentWater_fullHumidity_80F = 0.0200
wtPercentWater_fullHumidity_90F = 0.0272
wtPercentWater = np.array([ #source: http://www.engineeringtoolbox.com/water-vapor-air-d_854.html
(30.,0.0030),
(40.,0.0047),
(50.,0.0069),
(60.,0.0100),
(70.,0.0143),
(80.,0.0200),
(90.,0.0272),
])
lbAirPerFt3_90F = 0.072

C_air_JoulesPerKg = 1005
joulesPerBTU = 1055.05
kgPerPount = 0.453
C_air_btuPerLb = C_air_JoulesPerKg / joulesPerBTU * kgPerPount





def printBTU(btuPerHr, title):
    BTUHR_PER_WATT = 3.412141633
    watts = btuPerHr / BTUHR_PER_WATT
    print title+": %0.1f btu/hr = %0.1fW" % (btuPerHr,watts)

def equilibriumEvaporation(inletTemp, humidityChange):
    """ Calculates outlet temperature of the swamp cooler, evaporated water per ft^3 air, and btu removed per ft^3 air.
    Accounts for the fact that as air cools, it absorbs less water. Assumes no heat exchange with the yurt during evaporation.
    If we can absorb yurt heat during evaporation we'll be able to put more water into the air."""
    assumedOutletTemp = inletTemp
    outletTempError = 9999
    while abs(outletTempError) > 0.2:
        wtPercentWater_fullHumidity = np.interp([assumedOutletTemp], wtPercentWater[:,0],wtPercentWater[:,1])[0]
        assumedWtPercentWater = wtPercentWater_fullHumidity * humidityChange
        btuRemovedPerPoundAir = btuPerPoundEvaporate * assumedWtPercentWater
        finalTemp = inletTemp - btuRemovedPerPoundAir / C_air_btuPerLb
        outletTempError = finalTemp - assumedOutletTemp
        assumedOutletTemp += np.sign(outletTempError)*0.1
    print "cooler outlet temp=",assumedOutletTemp,"degF"
    print "for incoming air at %0.1fF, evaporation can decrease temp by up to %0.1fF" % (inletTemp,btuRemovedPerPoundAir /  C_air_btuPerLb)
    return (assumedWtPercentWater, btuRemovedPerPoundAir)

(outletWtPercentWater, btuRemovedPerPoundAirInTheseConditions) = equilibriumEvaporation(inletTemp=shadowedTemperature, humidityChange=ASSUMED_HUMIDITY_CHANGE)

def runSwampCooler(outsideAirDegF, insideAirDegF, cfm, verbose = False):
    btuRemovedPerPoundAir = btuRemovedPerPoundAirInTheseConditions#btuPerPoundEvaporate * achievableWtPercentWater
    
    swampCoolerCFHr = cfm * 60.0
    btuLetInPerPoundAir = C_air_btuPerLb * (outsideAirDegF - insideAirDegF)
    coolerBtuHrIn = swampCoolerCFHr * lbAirPerFt3_90F * btuLetInPerPoundAir
    coolerBtuHrRemoved = swampCoolerCFHr * lbAirPerFt3_90F * btuRemovedPerPoundAir
    coolerNetBtu = coolerBtuHrIn - coolerBtuHrRemoved
    gallonsPerHour = swampCoolerCFHr * lbAirPerFt3_90F * outletWtPercentWater / POUNDS_PER_GALLON
    if verbose and cfm > 0:
        print "cooler uses 1 gallon per %0.1f hr" % (1.0/gallonsPerHour)
        print "cooler lets in %0.1f btu/hr and absorbs %0.1f btu/hr.\nnet %0.1fbtu/hr. The hot inlet air is robbing %0.1f%% of the cooling effect." % (coolerBtuHrIn, coolerBtuHrRemoved, coolerNetBtu, 100.*(coolerBtuHrIn/coolerBtuHrRemoved))
    return (coolerNetBtu, gallonsPerHour)


def simulate(swampCoolerCFM, panelR):
    print "------ "+str(swampCoolerCFM)+"cfm ----------"
    insideTemperature = initialInsideTemperature
    times = []
    temps = []
    deltaT = 0.01
    for hr in np.arange(0.0,4.0,deltaT):
        times.append(hr)
        temps.append(insideTemperature)
        
        btuHrIn = ((shadowedTemperature - insideTemperature) / (panelR+R_convection) * shadowed_sqft +
                    (sunlitTemperature - insideTemperature) / (panelR+R_convection) * sunlit_sqft)
        
        tapeBtuHrIn = (sunlitTemperature - insideTemperature) / (R_tape+R_convection) * tape_sqft #multiply a wrong number x a guess.
        
        #### swamp cooler ######
        (coolerNetBtu, gallonsPerHour) = runSwampCooler(outsideAirDegF=shadowedTemperature, insideAirDegF=insideTemperature, cfm=swampCoolerCFM, verbose = (hr==0.0))
        
        if hr == 0:
            printBTU(btuHrIn,"    At t=0, heat in through insulation")
            printBTU(tapeBtuHrIn,"    through tape")
            printBTU(humanBtuHrIn,"    human generates")
            totalBTU = btuHrIn+tapeBtuHrIn+humanBtuHrIn
            printBTU(totalBTU,"    total heat in")
            
        btuPerGallonHeatCapacity = 1.0 * POUNDS_PER_GALLON
        yurtHeatCapacity = btuPerGallonHeatCapacity * 10
        insideTemperature += (btuHrIn + tapeBtuHrIn + humanBtuHrIn + coolerNetBtu) * deltaT / yurtHeatCapacity
    print "    Final temp = %0.1fF" % (insideTemperature)
    return (times,temps)

#1.15V in heat gun output for PC fan, 1.6V for blower
#2.1V in lab for PC fan, 2.5V in lab for blower
#3.9V in output of cooler in both cases

def v2h(v):
    print (v - 0.75)/3.0

"""
1 blower, 1 hole: 62CFM
1 blower, 3 holes: 86CFM with or without water, 
    1 filter: 3.6V humidity with 2.4V humidity in
    2 filters: 
"""

if __name__=="__main__":
    pyplot.figure()
    pyplot.title("hexayurt interior temp with outside = %.0fF"%(shadowedTemperature))
    for cfm,R in cfmsAndRValuesToPlot:
        (times, temps) = simulate(swampCoolerCFM = cfm, panelR = R)
        pyplot.plot(times,temps, label = "%.0f cfm, R=%.2f" % (cfm,R) )
    pyplot.xlabel("hour of direct sun")
    pyplot.ylabel("degF")
    pyplot.legend()
    pyplot.show()
