frontend/src/grain/GrainMoisture.ts

192 lines
5 KiB
TypeScript

import { pond } from "protobuf-ts/pond";
import GrainDescriber from "./GrainDescriber";
export enum Equation {
"none",
"oswin",
"halsey",
"henderson",
"chungPfost"
}
const toERH = (humidity: number): number => {
return humidity >= 100 ? 0.99999 : humidity / 100;
};
export function ExtractMoisture(
type: pond.Grain | undefined,
celsius: number,
humidity: number,
customGrain?: pond.GrainSettings
): number {
if (humidity <= 0) {
return 0;
}
if (
type === undefined ||
type === pond.Grain.GRAIN_NONE ||
type === pond.Grain.GRAIN_INVALID ||
(type === pond.Grain.GRAIN_CUSTOM && customGrain === undefined)
) {
return humidity;
}
let dry = humidity;
let eq: pond.MoistureEquation
let constA: number
let constB: number
let constC: number
if(type === pond.Grain.GRAIN_CUSTOM && customGrain){
if(customGrain.equation === pond.MoistureEquation.MOISTURE_EQUATION_NONE) return humidity
eq = customGrain.equation
constA = customGrain.a
constB = customGrain.b
constC = customGrain.c
}else{
let ctx = GrainDescriber(type);
eq = ctx.equation
constA = ctx.a
constB = ctx.b
constC = ctx.c
}
dry = toDryMoisture(eq, celsius, humidity, constA, constB, constC);
return dryToWet(dry);
}
export function WaterContent(type: pond.Grain, bushels: number, moistureContent: number, customGrain?: pond.GrainSettings): number {
//kg per bushel conversion
let conversion = 0
if(type === pond.Grain.GRAIN_CUSTOM && customGrain){
conversion = customGrain.kgPerBushel
}else{
conversion = GrainDescriber(type).weightConversionKg;
}
return bushels * conversion * moistureContent;
}
export function MoistureToHumidity(
type: pond.Grain | undefined,
celsius: number,
wetMC: number
): number {
if (wetMC <= 0) {
return 0;
}
if (type === undefined || type === pond.Grain.GRAIN_NONE || type === pond.Grain.GRAIN_INVALID) {
return wetMC;
}
const dryMC = wetToDry(wetMC);
let ctx = GrainDescriber(type);
return dryMoistureToHumidity(ctx.equation, celsius, dryMC, ctx.a, ctx.b, ctx.c);
}
function dryToWet(dryMC: number): number {
return (100 * dryMC) / (dryMC + 100);
}
function wetToDry(wetMC: number): number {
return -((100 * wetMC) / (wetMC - 100));
}
function toDryMoisture(
eq: pond.MoistureEquation,
T: number,
RH: number,
a: number,
b: number,
c: number
): number {
const ERH: number = toERH(RH);
switch (eq) {
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
return chungPfost(T, ERH, a, b, c);
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
return halsey(T, ERH, a, b, c);
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
return henderson(T, ERH, a, b, c);
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
return oswin(T, ERH, a, b, c);
default:
return RH;
}
}
function dryMoistureToHumidity(
eq: pond.MoistureEquation,
celsius: number,
dryMC: number,
a: number,
b: number,
c: number
): number {
let ERH = 0;
switch (eq) {
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
ERH = chungPfostInverse(celsius, dryMC, a, b, c);
break;
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
ERH = halseyInverse(celsius, dryMC, a, b, c);
break;
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
ERH = hendersonInverse(celsius, dryMC, a, b, c);
break;
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
ERH = oswinInverse(celsius, dryMC, a, b, c);
break;
default:
return dryMC;
}
let RH = ERH * 100;
return RH;
}
function chungPfost(celsius: number, ERH: number, a: number, b: number, c: number): number {
const T = celsius;
return Math.log((-Math.log(ERH) * (T + c)) / a) / -b;
}
function halsey(celsius: number, ERH: number, a: number, b: number, c: number): number {
const T = celsius;
return Math.pow(-Math.exp(a + b * T) / Math.log(ERH), 1 / c);
}
function henderson(celsius: number, ERH: number, a: number, b: number, c: number): number {
const T = celsius;
return Math.pow(Math.log(1 - ERH) / (-a * (T + c)), 1 / b);
}
function oswin(celsius: number, ERH: number, a: number, b: number, c: number): number {
const T = celsius;
return (a + b * T) / Math.pow(Math.pow(ERH, -1) - 1, 1 / c);
}
function chungPfostInverse(
celsius: number,
dryMC: number,
a: number,
b: number,
c: number
): number {
const T = celsius;
return Math.exp(-(a / (T + c)) * Math.exp(-b * dryMC));
}
function halseyInverse(celsius: number, dryMC: number, a: number, b: number, c: number): number {
const T = celsius;
return Math.exp(-(Math.exp(a + b * T) / Math.pow(dryMC, c)));
}
function hendersonInverse(celsius: number, dryMC: number, a: number, b: number, c: number): number {
const T = celsius;
return 1 - Math.exp(-a * (T + c) * Math.pow(dryMC, b));
}
function oswinInverse(celsius: number, dryMC: number, a: number, b: number, c: number): number {
const T = celsius;
return Math.pow(Math.pow((a + b * T) / dryMC, c) + 1, -1);
}