ccs-sim
Version:
Modelling CCS systems
145 lines (144 loc) • 7.27 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fluid_1 = require("./fluid");
const element_1 = require("./element");
const transport_1 = __importDefault(require("./transport"));
const physical_quantities_1 = require("physical-quantities");
class Splitter extends transport_1.default {
constructor(name, physical, source) {
super(name, physical, 'Splitter');
this.destinations = [];
this.source = source;
this.source.setDestination(this);
}
addDestination(dest) {
if (dest.physical.elevation !== this.physical.elevation)
throw new Error('Destination elevation does not match splitter elevation');
this.destinations.push(dest);
dest.source = this;
}
setDestinations(destinations) {
destinations.forEach((d) => this.addDestination(d));
}
applyFlowrate(branch, flowrate) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.fluid) {
throw new Error('Splitter has no fluid - unable to calculate end pressure');
}
const newFluid = yield fluid_1.defaultFluidConstructor(this.fluid.pressure, this.fluid.temperature, flowrate);
return this.destinations[branch].process(newFluid);
});
}
searchBranchFlowrate(branch, fluid) {
return __awaiter(this, void 0, void 0, function* () {
if (!fluid) {
throw new Error('Splitter has no fluid - unable to calculate end pressure');
}
let low = 0;
let high = fluid.flowrate.kgps;
let mid = 0;
const calculatedPressureBoundaries = {
highFlowrate: (yield this.applyFlowrate(branch, fluid.flowrate)).pressure
.bara,
lowFlowrate: (yield this.applyFlowrate(branch, new physical_quantities_1.Flowrate(0, physical_quantities_1.FlowrateUnits.Kgps))).pressure.bara,
};
const target = yield this.getBranchTarget(branch, fluid);
if (!target) {
throw new Error(`Unable to find target pressure for branch ${branch}`);
}
let guesses = 0;
const maxGuesses = 25;
let pressureSolution = element_1.PressureSolution.Low;
while (pressureSolution !== element_1.PressureSolution.Ok) {
if (guesses++ > maxGuesses - 1) {
break;
}
mid =
low +
((high - low) /
(calculatedPressureBoundaries.highFlowrate -
calculatedPressureBoundaries.lowFlowrate)) *
(target.target.bara - calculatedPressureBoundaries.lowFlowrate);
if (mid >= fluid.flowrate.kgps * 0.9) {
return { flowrate: mid, pressureSolution };
}
if (mid <= new physical_quantities_1.Flowrate(0.001, physical_quantities_1.FlowrateUnits.Kgps).kgps) {
return { flowrate: mid, pressureSolution: element_1.PressureSolution.Low };
}
pressureSolution = (yield this.applyFlowrate(branch, new physical_quantities_1.Flowrate(mid, physical_quantities_1.FlowrateUnits.Kgps))).pressureSolution;
if (pressureSolution === element_1.PressureSolution.Low) {
high = mid;
}
else if (pressureSolution === element_1.PressureSolution.High) {
low = mid;
}
}
return { flowrate: mid, pressureSolution };
});
}
getBranchTarget(branchNum, fluid) {
return __awaiter(this, void 0, void 0, function* () {
let low = 0;
let high = fluid.flowrate.kgps;
let mid = 0;
let pressureSolution = element_1.PressureSolution.Low;
let guesses = 0;
const maxGuesses = 25;
while (pressureSolution !== element_1.PressureSolution.Ok) {
if (guesses++ > maxGuesses - 1) {
break;
}
const { pressureSolution: pSol, pressure, target, } = yield this.applyFlowrate(branchNum, new physical_quantities_1.Flowrate(mid, physical_quantities_1.FlowrateUnits.Kgps));
if (target)
return { pressureSolution: pSol, pressure, target };
mid = (low + high) / 2;
pressureSolution = pSol;
if (pressureSolution === element_1.PressureSolution.Low) {
high = mid;
}
else if (pressureSolution === element_1.PressureSolution.High) {
low = mid;
}
}
});
}
process(fluid) {
return __awaiter(this, void 0, void 0, function* () {
this.fluid = fluid;
const lowPressureLimit = new physical_quantities_1.Pressure(1000, physical_quantities_1.PressureUnits.Pascal).pascal;
if (this.fluid.pressure.pascal < lowPressureLimit)
return {
pressureSolution: element_1.PressureSolution.Low,
pressure: this.fluid.pressure,
target: null,
};
const newFluid = yield fluid_1.defaultFluidConstructor(this.fluid.pressure, this.fluid.temperature, this.fluid.flowrate);
for (let i = 0; i < this.destinations.length - 1; i++) {
const { flowrate, pressureSolution } = yield this.searchBranchFlowrate(i, newFluid);
if (pressureSolution !== element_1.PressureSolution.Ok) {
return {
pressureSolution,
pressure: this.fluid.pressure,
target: null,
};
}
newFluid.flowrate = new physical_quantities_1.Flowrate(newFluid.flowrate.kgps - flowrate, physical_quantities_1.FlowrateUnits.Kgps);
}
const lastSearchResult = yield this.applyFlowrate(this.destinations.length - 1, newFluid.flowrate);
return lastSearchResult;
});
}
}
exports.default = Splitter;