web: ThermalUnits: Add, delete, and rename

web
Alinson S. Xavier 3 months ago
parent dea5217916
commit 7c752e4c31

@ -27,6 +27,11 @@ import {
} from "../../core/fixtures";
import { ColumnDefinition } from "tabulator-tables";
import { offerDownload } from "../Common/io";
import {
createThermalUnit,
deleteGenerator,
renameGenerator,
} from "../../core/Operations/generatorOps";
export const ThermalUnitsColumnSpec: ColumnSpec[] = [
{
@ -155,17 +160,17 @@ const ThermalUnitsComponent = (props: CaseBuilderSectionProps) => {
};
const onAdd = () => {
// const [newScenario, err] = createThermalUnit(props.scenario);
// if (err) {
// props.onError(err.message);
// return;
// }
// props.onDataChanged(newScenario);
const [newScenario, err] = createThermalUnit(props.scenario);
if (err) {
props.onError(err.message);
return;
}
props.onDataChanged(newScenario);
};
const onDelete = (name: string): ValidationError | null => {
// const newScenario = deleteGenerator(name, props.scenario);
// props.onDataChanged(newScenario);
const newScenario = deleteGenerator(name, props.scenario);
props.onDataChanged(newScenario);
return null;
};
@ -192,16 +197,16 @@ const ThermalUnitsComponent = (props: CaseBuilderSectionProps) => {
oldName: string,
newName: string,
): ValidationError | null => {
// const [newScenario, err] = renameGenerator(
// oldName,
// newName,
// props.scenario,
// );
// if (err) {
// props.onError(err.message);
// return err;
// }
// props.onDataChanged(newScenario);
const [newScenario, err] = renameGenerator(
oldName,
newName,
props.scenario,
);
if (err) {
props.onError(err.message);
return err;
}
props.onDataChanged(newScenario);
return null;
};

@ -129,7 +129,9 @@ export const generateTableData = (
break;
case "number[N]":
for (let i = 0; i < spec.length!; i++) {
entry[`${spec.title} ${i + 1}`] = entryData[spec.title][i] || "";
let v = entryData[spec.title][i];
if (v === undefined || v === null) v = "";
entry[`${spec.title} ${i + 1}`] = v;
}
break;
default:

@ -9,21 +9,24 @@ import assert from "node:assert";
import {
changeProfiledUnitData,
createProfiledUnit,
createThermalUnit,
deleteGenerator,
renameGenerator,
} from "./generatorOps";
import { ValidationError } from "../Validation/validate";
test("createProfiledUnit", () => {
const [newScenario, err] = createProfiledUnit(TEST_DATA_1);
assert(err === null);
assert.equal(Object.keys(newScenario.Generators).length, 4);
assert.deepEqual(newScenario.Generators["pu3"], {
Bus: "b1",
Type: "Profiled",
"Cost ($/MW)": 0,
"Maximum power (MW)": [0, 0, 0, 0, 0],
"Minimum power (MW)": [0, 0, 0, 0, 0],
});
assert("pu3" in newScenario.Generators);
});
test("createThermalUnit", () => {
const [newScenario, err] = createThermalUnit(TEST_DATA_1);
assert(err === null);
assert.equal(Object.keys(newScenario.Generators).length, 4);
assert("g2" in newScenario.Generators);
});
test("createProfiledUnit with blank file", () => {
@ -34,7 +37,7 @@ test("createProfiledUnit with blank file", () => {
test("changeProfiledUnitData", () => {
let scenario = TEST_DATA_1;
let err = null;
let err: ValidationError | null;
[scenario, err] = changeProfiledUnitData(
"pu1",
"Cost ($/MW)",
@ -71,7 +74,7 @@ test("changeProfiledUnitData with invalid bus", () => {
test("deleteGenerator", () => {
const newScenario = deleteGenerator("pu1", TEST_DATA_1);
assert.equal(Object.keys(newScenario.Generators).length, 2);
assert("gen1" in newScenario.Generators);
assert("g1" in newScenario.Generators);
assert("pu2" in newScenario.Generators);
});

@ -14,13 +14,20 @@ import {
} from "./commonOps";
import { ProfiledUnitsColumnSpec } from "../../components/CaseBuilder/ProfiledUnits";
const assertBusesNotEmpty = (
scenario: UnitCommitmentScenario,
): ValidationError | null => {
if (Object.keys(scenario.Buses).length === 0)
return { message: "Profiled unit requires an existing bus." };
return null;
};
export const createProfiledUnit = (
scenario: UnitCommitmentScenario,
): [UnitCommitmentScenario, ValidationError | null] => {
const busNames = Object.keys(scenario.Buses);
if (busNames.length === 0) {
return [scenario, { message: "Profiled unit requires an existing bus." }];
}
const err = assertBusesNotEmpty(scenario);
if (err) return [scenario, err];
const busName = Object.keys(scenario.Buses)[0]!;
const timeslots = generateTimeslots(scenario);
const name = generateUniqueName(scenario.Generators, "pu");
return [
@ -29,7 +36,7 @@ export const createProfiledUnit = (
Generators: {
...scenario.Generators,
[name]: {
Bus: busNames[0]!,
Bus: busName,
Type: "Profiled",
"Cost ($/MW)": 0,
"Minimum power (MW)": Array(timeslots.length).fill(0),
@ -41,6 +48,41 @@ export const createProfiledUnit = (
];
};
export const createThermalUnit = (
scenario: UnitCommitmentScenario,
): [UnitCommitmentScenario, ValidationError | null] => {
const err = assertBusesNotEmpty(scenario);
if (err) return [scenario, err];
const busName = Object.keys(scenario.Buses)[0]!;
const name = generateUniqueName(scenario.Generators, "g");
return [
{
...scenario,
Generators: {
...scenario.Generators,
[name]: {
Bus: busName,
Type: "Thermal",
"Production cost curve (MW)": [0],
"Production cost curve ($)": [0],
"Startup costs ($)": [0],
"Startup delays (h)": [1],
"Ramp up limit (MW)": "",
"Ramp down limit (MW)": "",
"Startup limit (MW)": "",
"Shutdown limit (MW)": "",
"Minimum downtime (h)": 1,
"Minimum uptime (h)": 1,
"Initial status (h)": -24,
"Initial power (MW)": 0,
"Must run?": false,
},
},
},
null,
];
};
export const changeProfiledUnitData = (
generator: string,
field: string,

@ -13,7 +13,7 @@ export const TEST_DATA_1: UnitCommitmentScenario = {
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268] },
},
Generators: {
gen1: {
g1: {
Bus: "b1",
Type: "Thermal",
"Production cost curve (MW)": [100.0, 110.0, 130.0, 135.0],

@ -27,10 +27,10 @@ export interface ThermalUnit {
"Production cost curve ($)": number[];
"Startup costs ($)": number[];
"Startup delays (h)": number[];
"Ramp up limit (MW)": number;
"Ramp down limit (MW)": number;
"Startup limit (MW)": number;
"Shutdown limit (MW)": number;
"Ramp up limit (MW)": number | "";
"Ramp down limit (MW)": number | "";
"Startup limit (MW)": number | "";
"Shutdown limit (MW)": number | "";
"Minimum downtime (h)": number;
"Minimum uptime (h)": number;
"Initial status (h)": number;
@ -158,7 +158,7 @@ export const TEST_SCENARIO: UnitCommitmentScenario = {
],
"Cost ($/MW)": 50.0,
},
gen1: {
g1: {
Bus: "b1",
Type: "Thermal",
"Production cost curve (MW)": [100.0, 110.0, 130.0, 135.0],

Loading…
Cancel
Save