mirror of
https://github.com/ANL-CEEESA/UnitCommitment.jl.git
synced 2025-12-06 00:08:52 -06:00
web: Add createProfiledUnit
This commit is contained in:
@@ -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],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
36
web/src/core/Operations/profiledUnitOps.test.ts
Normal file
36
web/src/core/Operations/profiledUnitOps.test.ts
Normal file
@@ -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.");
|
||||
});
|
||||
37
web/src/core/Operations/profiledUnitOps.ts
Normal file
37
web/src/core/Operations/profiledUnitOps.ts
Normal file
@@ -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", () => {});
|
||||
|
||||
Reference in New Issue
Block a user