UNPKG

psychart

Version:

View air conditions on a psychrometric chart

141 lines (140 loc) 5.07 kB
import * as SMath from 'smath'; import Psychrolib from 'psychrolib'; /** * Represents a single air condition using several states. */ export class PsyState { state; options; /** * Calculation tolerance */ static TOL = 0.01; /** * Dry Bulb */ db; /** * Relative Humidity */ rh; /** * Wet Bulb */ wb; /** * Dew Point */ dp; /** * Humidity Ratio */ hr; /** * Vapor Pressure */ vp; /** * Moist Air Enthalpy */ h; /** * Moist Air Volume */ v; /** * Degree of Saturation */ s; /** * Standard Atmospheric Air Pressure */ atm; /** * Maximum Humidity Ratio */ hrMax; /** * Initialize a new psychrometric state. */ constructor(state, options) { this.state = state; this.options = options; Psychrolib.SetUnitSystem(options.unitSystem === 'IP' ? Psychrolib.IP : Psychrolib.SI); this.atm = Psychrolib.GetStandardAtmPressure(options.altitude); this.hrMax = Psychrolib.GetHumRatioFromTDewPoint(options.dpMax, this.atm); this.db = state.db; switch (state.measurement) { case ('dbrh'): { this.rh = state.other; [this.hr, this.wb, this.dp, this.vp, this.h, this.v, this.s] = Psychrolib.CalcPsychrometricsFromRelHum(state.db, state.other, this.atm); break; } case ('dbwb'): { this.wb = state.other; [this.hr, this.dp, this.rh, this.vp, this.h, this.v, this.s] = Psychrolib.CalcPsychrometricsFromTWetBulb(state.db, state.other, this.atm); break; } case ('dbdp'): { this.dp = state.other; [this.hr, this.wb, this.rh, this.vp, this.h, this.v, this.s] = Psychrolib.CalcPsychrometricsFromTDewPoint(state.db, state.other, this.atm); break; } case ('dbhr'): { this.dp = Psychrolib.GetTDewPointFromHumRatio(state.db, state.other, this.atm); [this.hr, this.wb, this.rh, this.vp, this.h, this.v, this.s] = Psychrolib.CalcPsychrometricsFromTDewPoint(state.db, this.dp, this.atm); if (!SMath.approx(this.hr, state.other) && Math.abs(SMath.error(this.hr, state.other)) > PsyState.TOL) { throw new Error(`Error in psychrolib computation. Expected "${state.other}" but found "${this.hr}" for ${state.measurement}.`); } break; } case ('dbh'): { this.hr = Psychrolib.GetHumRatioFromEnthalpyAndTDryBulb(state.other, state.db); this.dp = Psychrolib.GetTDewPointFromHumRatio(state.db, this.hr, this.atm); [this.hr, this.wb, this.rh, this.vp, this.h, this.v, this.s] = Psychrolib.CalcPsychrometricsFromTDewPoint(state.db, this.dp, this.atm); if (!SMath.approx(this.h, state.other) && Math.abs(SMath.error(this.h, state.other)) > PsyState.TOL) { throw new Error(`Error in psychrolib computation. Expected "${state.other}" but found "${this.h}" for ${state.measurement}.`); } break; } default: { throw new Error(`Invalid measurement type ${state.measurement}.`); } } } /** * Convert this psychrometric state to an X-Y coordinate on a psychrometric chart. */ toXY() { // Determine if additional padding is needed to show axis names const fontPad = this.options.showAxisNames ? (1.5 * this.options.font.size) : 0; // The lower-left location const origin = { x: this.options.padding.x + (this.options.flipXY ? fontPad : 0), y: this.options.padding.y + (this.options.flipXY ? fontPad : 0), }; // The upper-right location const bound = { x: this.options.size.x - this.options.padding.x - (this.options.flipXY ? 0 : fontPad), y: this.options.size.y - this.options.padding.y - (this.options.flipXY ? 0 : fontPad), }; if (this.options.flipXY) { return { x: SMath.clamp(SMath.translate(this.hr, 0, this.hrMax, origin.x, bound.x), origin.x, bound.x), y: SMath.clamp(SMath.translate(this.db, this.options.dbMin, this.options.dbMax, bound.y, origin.y), origin.y, bound.y) }; } else { return { x: SMath.clamp(SMath.translate(this.db, this.options.dbMin, this.options.dbMax, origin.x, bound.x), origin.x, bound.x), y: SMath.clamp(SMath.translate(this.hr, 0, this.hrMax, bound.y, origin.y), origin.y, bound.y) }; } } /** * Calculate the dry bulb temperature of dry air with enthalpy `h` */ static getDryBulbWithEnthalpy(h) { return Psychrolib.GetTDryBulbFromEnthalpyAndHumRatio(h, 0); } }