web: Add createProfiledUnit

web
Alinson S. Xavier 3 months ago
parent 8827f9e6c8
commit 8397571c11

@ -23,6 +23,7 @@ import { ColumnDefinition } from "tabulator-tables";
import { offerDownload } from "../../Common/io";
import FileUploadElement from "../../Common/Buttons/FileUploadElement";
import { useRef } from "react";
import { createProfiledUnit } from "../../../core/Operations/profiledUnitOps";
interface ProfiledUnitsProps {
scenario: UnitCommitmentScenario;
@ -98,7 +99,14 @@ const ProfiledUnitsComponent = (props: ProfiledUnitsProps) => {
});
};
const onAdd = () => {};
const onAdd = () => {
const [newScenario, err] = createProfiledUnit(props.scenario);
if (err) {
props.onError(err.message);
return;
}
props.onDataChanged(newScenario);
};
return (
<div>

@ -30,18 +30,10 @@ test("changeBusData", () => {
[scenario, err] = changeBusData("b3", "Load (MW) 04:00", "99", scenario);
assert.equal(err, null);
assert.deepEqual(scenario, {
Parameters: {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 5,
"Time step (min)": 60,
},
Buses: {
b1: { "Load (MW)": [99, 34.38835, 33.45083, 99, 33.25044] },
b2: { "Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 99] },
},
assert.deepEqual(scenario.Buses, {
b1: { "Load (MW)": [99, 34.38835, 33.45083, 99, 33.25044] },
b2: { "Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 99] },
});
});
@ -54,35 +46,19 @@ test("changeBusData with invalid numbers", () => {
test("deleteBus", () => {
let scenario = TEST_DATA_1;
scenario = deleteBus("b2", scenario);
assert.deepEqual(scenario, {
Parameters: {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 5,
"Time step (min)": 60,
},
Buses: {
b1: { "Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268] },
},
assert.deepEqual(scenario.Buses, {
b1: { "Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268] },
});
});
test("renameBus", () => {
let [scenario, err] = renameBus("b2", "b99", TEST_DATA_1);
assert(err === null);
assert.deepEqual(scenario, {
Parameters: {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 5,
"Time step (min)": 60,
},
Buses: {
b1: { "Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044] },
b99: { "Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268] },
},
assert.deepEqual(scenario.Buses, {
b1: { "Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044] },
b99: { "Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268] },
});
});

@ -6,34 +6,27 @@
import { Buses, UnitCommitmentScenario } from "../fixtures";
import { ValidationError } from "../Validation/validate";
import { generateTimeslots } from "../../components/Common/Forms/DataTable";
const generateUniqueBusName = (scenario: UnitCommitmentScenario) => {
let newBusName = "b";
export const generateUniqueName = (container: any, prefix: string): string => {
let counter = 1;
let name = `${newBusName}${counter}`;
while (name in scenario.Buses) {
let name = `${prefix}${counter}`;
while (name in container) {
counter++;
name = `${newBusName}${counter}`;
name = `${prefix}${counter}`;
}
return name;
};
const generateDefaultBusLoad = (scenario: UnitCommitmentScenario) => {
const T =
scenario.Parameters["Time horizon (h)"] *
(60 / scenario.Parameters["Time step (min)"]);
return new Array(T).fill(0);
};
export const createBus = (scenario: UnitCommitmentScenario) => {
const load = generateDefaultBusLoad(scenario);
let name = generateUniqueBusName(scenario);
const name = generateUniqueName(scenario.Buses, "b");
const timeslots = generateTimeslots(scenario);
return {
...scenario,
Buses: {
...scenario.Buses,
[name]: {
"Load (MW)": load,
"Load (MW)": Array(timeslots.length).fill(0),
},
},
};

@ -15,18 +15,16 @@ import { TEST_DATA_1, TEST_DATA_2 } from "../fixtures.test";
test("changeTimeHorizon: Shrink 1", () => {
const [newScenario, err] = changeTimeHorizon(TEST_DATA_1, "3");
assert(err === null);
assert.deepEqual(newScenario, {
Parameters: {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 3,
"Time step (min)": 60,
},
Buses: {
b1: { "Load (MW)": [35.79534, 34.38835, 33.45083] },
b2: { "Load (MW)": [14.03739, 13.48563, 13.11797] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005] },
},
assert.deepEqual(newScenario.Parameters, {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 3,
"Time step (min)": 60,
});
assert.deepEqual(newScenario.Buses, {
b1: { "Load (MW)": [35.79534, 34.38835, 33.45083] },
b2: { "Load (MW)": [14.03739, 13.48563, 13.11797] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005] },
});
});
@ -51,23 +49,21 @@ test("changeTimeHorizon: Shrink 2", () => {
test("changeTimeHorizon grow", () => {
const [newScenario, err] = changeTimeHorizon(TEST_DATA_1, "7");
assert(err === null);
assert.deepEqual(newScenario, {
Parameters: {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 7,
"Time step (min)": 60,
assert.deepEqual(newScenario.Parameters, {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 7,
"Time step (min)": 60,
});
assert.deepEqual(newScenario.Buses, {
b1: {
"Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044, 0, 0],
},
Buses: {
b1: {
"Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044, 0, 0],
},
b2: {
"Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939, 0, 0],
},
b3: {
"Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268, 0, 0],
},
b2: {
"Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939, 0, 0],
},
b3: {
"Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268, 0, 0],
},
});
});

@ -0,0 +1,36 @@
/*
* UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment
* Copyright (C) 2020-2025, UChicago Argonne, LLC. All rights reserved.
* Released under the modified BSD license. See COPYING.md for more details.
*/
import { TEST_DATA_1, TEST_DATA_BLANK } from "../fixtures.test";
import assert from "node:assert";
import { createProfiledUnit } from "./profiledUnitOps";
test("createUnit", () => {
const [newScenario, err] = createProfiledUnit(TEST_DATA_1);
assert(err === null);
assert.deepEqual(newScenario.Generators, {
pu1: {
Bus: "b1",
Type: "Profiled",
"Cost ($/MW)": 12.5,
"Maximum power (MW)": [10, 12, 13, 15, 20],
"Minimum power (MW)": [0, 0, 0, 0, 0],
},
pu2: {
Bus: "b1",
Type: "Profiled",
"Cost ($/MW)": 0,
"Maximum power (MW)": [0, 0, 0, 0, 0],
"Minimum power (MW)": [0, 0, 0, 0, 0],
},
});
});
test("createUnit with blank file", () => {
const [newScenario, err] = createProfiledUnit(TEST_DATA_BLANK);
assert(err !== null);
assert.equal(err.message, "Profiled unit requires an existing bus.");
});

@ -0,0 +1,37 @@
/*
* UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment
* Copyright (C) 2020-2025, UChicago Argonne, LLC. All rights reserved.
* Released under the modified BSD license. See COPYING.md for more details.
*/
import { UnitCommitmentScenario } from "../fixtures";
import { generateTimeslots } from "../../components/Common/Forms/DataTable";
import { generateUniqueName } from "./busOperations";
import { ValidationError } from "../Validation/validate";
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 timeslots = generateTimeslots(scenario);
const name = generateUniqueName(scenario.Generators, "pu");
return [
{
...scenario,
Generators: {
...scenario.Generators,
[name]: {
Bus: busNames[0]!,
Type: "Profiled",
"Cost ($/MW)": 0,
"Minimum power (MW)": Array(timeslots.length).fill(0),
"Maximum power (MW)": Array(timeslots.length).fill(0),
},
},
},
null,
];
};

@ -12,7 +12,17 @@ export const TEST_DATA_1: UnitCommitmentScenario = {
b2: { "Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268] },
},
Generators: {
pu1: {
Bus: "b1",
Type: "Profiled",
"Cost ($/MW)": 12.5,
"Maximum power (MW)": [10, 12, 13, 15, 20],
"Minimum power (MW)": [0, 0, 0, 0, 0],
},
},
};
export const TEST_DATA_2: UnitCommitmentScenario = {
Parameters: {
Version: "0.4",
@ -27,4 +37,15 @@ export const TEST_DATA_2: UnitCommitmentScenario = {
},
};
export const TEST_DATA_BLANK: UnitCommitmentScenario = {
Parameters: {
Version: "0.4",
"Power balance penalty ($/MW)": 1000.0,
"Time horizon (h)": 5,
"Time step (min)": 60,
},
Buses: {},
Generators: {},
};
test("fixtures", () => {});

Loading…
Cancel
Save