/************************************************
    Psychrometric Calculator - JavaScript Object
    TechniSolve Software
    Bruce Wernick PrEng BScEng
    Copyright 2006
************************************************/

function psat(t) {
// Saturation pressure using the Magnus formula
  return 0.6105*Math.exp(17.27*t/(237.3+t));
}

function pvap(pa,db,wb) {
// vapor pressure, Barenbrug equation
  return (psat(wb)*(371.4+0.24*db-0.6*wb)-0.24*(db-wb)*pa)/(371.4+0.04*db-0.4*wb);
}

function pvap_pawa(pa,wa) {
  return wa*pa/(wa+0.622);
}

function humidity(pa,pv) {
  return 0.622*pv/(pa-pv);
}

function humidity_dbha(db,ha) {
  return (ha-1.005*db)/(2500.8+1.884*db);
}

function relhumidity(pv,ps) {
  return pv/ps;
}  

function enthalpy(db,wa) {
  return 1.005*db+wa*(2500.8+1.884*db);
}

function drybulb_hawa(ha,wa) {
  return (ha-wa*2500.8)/(1.005+wa*1.884);
}

function dewpoint(pv) {
  var x=Math.log(pv/0.6105);
  return 237.3*x/(17.27-x);
}

function density(pa,pv,db) {
  return (pa-0.378*pv)/(0.287045*(273.15+db));
}

function specheat(wa) {
  return 1.005+wa*1.884;
}

function pv_error(x) {
// broyden error function
  return psy.pv-pvap(psy.pa,psy.db,x);
}

function wetbulb(wb) {
// wet bulb from Barenbrug pv
  return broyden(pv_error,wb);
}

function psycalc() {
  with(psy) {

    // get property combination  
    var k=air.combin.selectedIndex;
  
    // get the values from the form
  
    air.pa.value=rangecheck("Pressure",air.pa.value,101.325,70,120,3);
    pa=parseFloat(air.pa.value);

    if ((k>=0) && (k<=2)) {
      air.db.value=rangecheck("Dry Bulb",air.db.value,25.0,-60.0,99.0,2);
      db=parseFloat(air.db.value);
    }

    if (k==0) {
      air.wb.value=rangecheck("Wet Bulb",air.wb.value,17.0,-60.0,db,2);
      wb=parseFloat(air.wb.value);
    }

    if ((k==1) || (k==3)) {
      air.ha.value=rangecheck("Enthalpy",air.ha.value,47.54,-60.0,200,2);
      ha=parseFloat(air.ha.value);
    }

    if ((k==2) || (k==3)) {
      air.wa.value=rangecheck("Humidity",air.wa.value,8.797,0,50,3);
      wa=1e-3*parseFloat(air.wa.value);
    }
    
    // calc properties based on selected combination
    switch(k) {
      case 0: // dbwb
        ps=psat(db);
        pv=pvap(pa,db,wb);
        wa=humidity(pa,pv);
        ha=enthalpy(db,wa);
        break;
      case 1: // dbha
        ps=psat(db);
        wa=humidity_dbha(db,ha);
        pv=pvap_pawa(pa,wa);
        wb=wetbulb(wb);
        break;
      case 2: // dbwa
        ps=psat(db);
        ha=enthalpy(db,wa);
        pv=pvap_pawa(pa,wa);
        wb=wetbulb(wb);
        break;
      case 3: // hawa
        db=drybulb_hawa(ha,wa);
        ps=psat(db);
        pv=pvap_pawa(pa,wa);
        wb=wetbulb(wb);
        break;
    }

    rh=relhumidity(pv,ps);
    td=dewpoint(pv);
    ro=density(pa,pv,db);
    cp=specheat(wa);

    // update the form
    air.db.value=roundup(db,2);
    air.wb.value=roundup(wb,2);
    air.wa.value=roundup(1e3*wa,3);
    air.ha.value=roundup(ha,2);
    air.rh.value=roundup(1e2*rh,1);
    air.td.value=roundup(td,1);
    air.pv.value=roundup(pv,3);
    air.ps.value=roundup(ps,3);
    air.ro.value=roundup(ro,3);
    air.cp.value=roundup(cp,3);
  }
  return;
}

function airclass(pa,db,wb) {
// air properties constructor function
  this.pa=pa;
  this.db=db;
  this.wb=wb;
  this.ha=0;
  this.wa=0;
  this.rh=0;
  this.td=0;
  this.pv=0;
  this.ps=0;
  this.ro=0;
  this.cp=0;
  this.calc=psycalc;
}

var psy = new airclass(101.325,25.0,17.0);

function resetform() {
// Reset to typical values
  air.pa.value="101.325";
  air.db.value="25.0";
  air.wb.value="17.0";
  air.combin[0].selected=true;
  get_option();
  psy.calc();
  return;
}

function get_option() {
  air.db.disabled="disabled";
  air.wb.disabled="disabled";
  air.ha.disabled="disabled";
  air.wa.disabled="disabled";
  var k=air.combin.selectedIndex;
  switch(k) {
    case 0: air.db.disabled=""; air.wb.disabled=""; break;
    case 1: air.db.disabled=""; air.ha.disabled=""; break;
    case 2: air.db.disabled=""; air.wa.disabled=""; break;
    case 3: air.ha.disabled=""; air.wa.disabled=""; break;
  }
  return;
}
