Files
swift-manual-s/Sources/ManualS/Internal/HeatPumpHeatingInterpolation.swift
Michael Housh bd33827e53
All checks were successful
CI / Ubuntu (push) Successful in 11m46s
feat: Adds heat pump heating interpolation.
2025-03-13 10:55:15 -04:00

81 lines
2.6 KiB
Swift

import CoreFoundation
import Models
import Validations
extension HeatPumpHeatingInterpolation.Request {
func respond() async throws -> HeatPumpHeatingInterpolation.Response {
try await validate()
let altitudeAdjustmentMultiplier = try await altitudeAdjustmentMultiplier()
let finalCapacity = finalCapacity(altitudeAdjustmentMultiplier)
let balancePointTemperature = try await balancePoint(finalCapacity)
let capacityAtDesign = capacityAtDesign(finalCapacity)
let requiredKW = try await requiredKW(capacityAtDesign)
return .init(
altitudeAdjustmentMultiplier: altitudeAdjustmentMultiplier,
balancePointTemperature: balancePointTemperature,
capacityAtDesign: capacityAtDesign,
finalCapacity: finalCapacity,
supplementalHeatRequired: requiredKW
)
}
private func balancePoint(_ finalCapacity: Capacity.HeatPumpHeating) async throws -> Int {
let response = try await BalancePoint.Request(
winterDesignTemperature: winterDesignTemperature,
heatLoss: heatLoss,
heatPumpCapacity: finalCapacity
).respond()
return Int(response.balancePointTemperature)
}
private func altitudeAdjustmentMultiplier() async throws -> Double? {
guard let elevation else { return nil }
let response = try await Derating.Request(
elevation: elevation,
systemType: .airToAir(type: .heatPump, compressor: .singleSpeed, climate: climateType)
).respond()
return response.heating
}
private func finalCapacity(
_ adjustmentMultiplier: Double?
) -> Capacity.HeatPumpHeating {
guard let adjustmentMultiplier else { return capacity }
return .init(
at47: Int(Double(capacity.at47) * adjustmentMultiplier),
at17: Int(Double(capacity.at17) * adjustmentMultiplier)
)
}
private func capacityAtDesign(
_ finalCapacity: Capacity.HeatPumpHeating
) -> Int {
let outdoorTemperature = Double(winterDesignTemperature)
let derating = Double((finalCapacity.at47 - finalCapacity.at17) / 30)
* (17 - outdoorTemperature)
return Int(Double(finalCapacity.at17) - derating)
}
private func requiredKW(_ capacityAtDesign: Int) async throws -> Int {
let response = try await RequiredKW.Request(
capacityAtDesign: capacityAtDesign,
heatLoss: heatLoss
).respond()
return Int(response.requiredKW)
}
}
extension HeatPumpHeatingInterpolation.Request: AsyncValidatable {
public var body: some AsyncValidation<Self> {
AsyncValidator.accumulating {
AsyncValidator.greaterThan(\.heatLoss, 0)
AsyncValidator.validate(\.capacity)
}
}
}