mirror of
https://github.com/ANL-CEEESA/UnitCommitment.jl.git
synced 2025-12-06 00:08:52 -06:00
web: Update busOperations to support time-indexed loads
This commit is contained in:
@@ -5,13 +5,13 @@
|
||||
*/
|
||||
|
||||
import assert from "node:assert";
|
||||
import { BUS_TEST_DATA_1 } from "../../../core/Operations/busOperations.test";
|
||||
import { parseBusesCsv } from "../../CaseBuilder/Buses/BusesCsv";
|
||||
import { generateBusesData } from "../../CaseBuilder/Buses/Buses";
|
||||
import { generateCsv } from "./DataTable";
|
||||
import { TEST_DATA_1 } from "../../../core/fixtures.test";
|
||||
|
||||
test("generate CSV", () => {
|
||||
const [data, columns] = generateBusesData(BUS_TEST_DATA_1);
|
||||
const [data, columns] = generateBusesData(TEST_DATA_1);
|
||||
const actualCsv = generateCsv(data, columns);
|
||||
const expectedCsv =
|
||||
"Name,Load (MW) 00:00,Load (MW) 01:00,Load (MW) 02:00,Load (MW) 03:00,Load (MW) 04:00\n" +
|
||||
@@ -26,7 +26,7 @@ test("parse valid CSV", () => {
|
||||
// "Name,Load 0,Load 1,Load 2,Load 3,Load 4\n" +
|
||||
// "b1,0,1,2,3,4\n" +
|
||||
// "b3,27.3729,26.29698,25.58005,25.15675,25.4268";
|
||||
// const newScenario = parseBusesCsv(BUS_TEST_DATA_1, csvContents);
|
||||
// const newScenario = parseBusesCsv(FixturesTest, csvContents);
|
||||
// assert.deepEqual(newScenario.Buses, {
|
||||
// b1: {
|
||||
// "Load (MW)": [0, 1, 2, 3, 4],
|
||||
@@ -43,7 +43,7 @@ test("parse invalid CSV (wrong headers)", () => {
|
||||
"b1,0,1,2,3,4\n" +
|
||||
"b3,27.3729,26.29698,25.58005,25.15675,25.4268";
|
||||
expect(() => {
|
||||
parseBusesCsv(BUS_TEST_DATA_1, csvContents);
|
||||
parseBusesCsv(TEST_DATA_1, csvContents);
|
||||
}).toThrow(Error);
|
||||
});
|
||||
|
||||
@@ -53,6 +53,6 @@ test("parse invalid CSV (wrong data length)", () => {
|
||||
"b1,0,1,2,3\n" +
|
||||
"b3,27.3729,26.29698,25.58005,25.15675,25.4268";
|
||||
expect(() => {
|
||||
parseBusesCsv(BUS_TEST_DATA_1, csvContents);
|
||||
parseBusesCsv(TEST_DATA_1, csvContents);
|
||||
}).toThrow(Error);
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Released under the modified BSD license. See COPYING.md for more details.
|
||||
*/
|
||||
|
||||
import { UnitCommitmentScenario } from "../fixtures";
|
||||
import {
|
||||
changeBusData,
|
||||
createBus,
|
||||
@@ -12,51 +11,23 @@ import {
|
||||
renameBus,
|
||||
} from "./busOperations";
|
||||
import assert from "node:assert";
|
||||
|
||||
export const BUS_TEST_DATA_1: UnitCommitmentScenario = {
|
||||
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] },
|
||||
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] },
|
||||
},
|
||||
};
|
||||
|
||||
export const BUS_TEST_DATA_2: UnitCommitmentScenario = {
|
||||
Parameters: {
|
||||
Version: "0.4",
|
||||
"Power balance penalty ($/MW)": 1000.0,
|
||||
"Time horizon (h)": 2,
|
||||
"Time step (min)": 30,
|
||||
},
|
||||
Buses: {
|
||||
b1: { "Load (MW)": [30, 30, 30, 30] },
|
||||
b2: { "Load (MW)": [10, 20, 30, 40] },
|
||||
b3: { "Load (MW)": [0, 30, 0, 40] },
|
||||
},
|
||||
};
|
||||
import { TEST_DATA_1 } from "../fixtures.test";
|
||||
|
||||
test("createBus", () => {
|
||||
const newScenario = createBus(BUS_TEST_DATA_1);
|
||||
const newScenario = createBus(TEST_DATA_1);
|
||||
assert.deepEqual(Object.keys(newScenario.Buses), ["b1", "b2", "b3", "b4"]);
|
||||
});
|
||||
|
||||
test("changeBusData", () => {
|
||||
let scenario = BUS_TEST_DATA_1;
|
||||
let scenario = TEST_DATA_1;
|
||||
let err = null;
|
||||
|
||||
[scenario, err] = changeBusData("b1", "Load 0", "99", scenario);
|
||||
[scenario, err] = changeBusData("b1", "Load (MW) 00:00", "99", scenario);
|
||||
assert.equal(err, null);
|
||||
[scenario, err] = changeBusData("b1", "Load (MW) 03:00", "99", scenario);
|
||||
assert.equal(err, null);
|
||||
|
||||
[scenario, err] = changeBusData("b1", "Load 3", "99", scenario);
|
||||
assert.equal(err, null);
|
||||
|
||||
[scenario, err] = changeBusData("b3", "Load 4", "99", scenario);
|
||||
[scenario, err] = changeBusData("b3", "Load (MW) 04:00", "99", scenario);
|
||||
assert.equal(err, null);
|
||||
|
||||
assert.deepEqual(scenario, {
|
||||
@@ -75,13 +46,13 @@ test("changeBusData", () => {
|
||||
});
|
||||
|
||||
test("changeBusData with invalid numbers", () => {
|
||||
let [, err] = changeBusData("b1", "Load 0", "xx", BUS_TEST_DATA_1);
|
||||
let [, err] = changeBusData("b1", "Load (MW) 00:00", "xx", TEST_DATA_1);
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, "Invalid value: xx");
|
||||
});
|
||||
|
||||
test("deleteBus", () => {
|
||||
let scenario = BUS_TEST_DATA_1;
|
||||
let scenario = TEST_DATA_1;
|
||||
scenario = deleteBus("b2", scenario);
|
||||
assert.deepEqual(scenario, {
|
||||
Parameters: {
|
||||
@@ -98,7 +69,7 @@ test("deleteBus", () => {
|
||||
});
|
||||
|
||||
test("renameBus", () => {
|
||||
let [scenario, err] = renameBus("b2", "b99", BUS_TEST_DATA_1);
|
||||
let [scenario, err] = renameBus("b2", "b99", TEST_DATA_1);
|
||||
assert(err === null);
|
||||
assert.deepEqual(scenario, {
|
||||
Parameters: {
|
||||
@@ -116,7 +87,7 @@ test("renameBus", () => {
|
||||
});
|
||||
|
||||
test("renameBus with duplicated name", () => {
|
||||
let [, err] = renameBus("b3", "b1", BUS_TEST_DATA_1);
|
||||
let [, err] = renameBus("b3", "b1", TEST_DATA_1);
|
||||
assert(err != null);
|
||||
assert.equal(err.message, `Bus b1 already exists`);
|
||||
});
|
||||
|
||||
@@ -46,13 +46,18 @@ export const changeBusData = (
|
||||
scenario: UnitCommitmentScenario,
|
||||
): [UnitCommitmentScenario, ValidationError | null] => {
|
||||
// Load (MW)
|
||||
const match = field.match(/Load (\d+)/);
|
||||
const match = field.match(/Load \(MW\) (\d+):(\d+)/);
|
||||
if (match) {
|
||||
const newValueFloat = parseFloat(newValueStr);
|
||||
if (isNaN(newValueFloat)) {
|
||||
return [scenario, { message: `Invalid value: ${newValueStr}` }];
|
||||
}
|
||||
const idx = parseInt(match[1]!, 10);
|
||||
|
||||
// Convert HH:MM to offset
|
||||
const hours = parseInt(match[1]!, 10);
|
||||
const min = parseInt(match[2]!, 10);
|
||||
const idx = (hours * 60 + min) / scenario.Parameters["Time step (min)"];
|
||||
|
||||
const newLoad = [...scenario.Buses[bus]!["Load (MW)"]];
|
||||
newLoad[idx] = newValueFloat;
|
||||
return [
|
||||
|
||||
@@ -9,11 +9,11 @@ import {
|
||||
changeTimeStep,
|
||||
evaluatePwlFunction,
|
||||
} from "./parameterOperations";
|
||||
import { BUS_TEST_DATA_1, BUS_TEST_DATA_2 } from "./busOperations.test";
|
||||
import assert from "node:assert";
|
||||
import { TEST_DATA_1, TEST_DATA_2 } from "../fixtures.test";
|
||||
|
||||
test("changeTimeHorizon: Shrink 1", () => {
|
||||
const [newScenario, err] = changeTimeHorizon(BUS_TEST_DATA_1, "3");
|
||||
const [newScenario, err] = changeTimeHorizon(TEST_DATA_1, "3");
|
||||
assert(err === null);
|
||||
assert.deepEqual(newScenario, {
|
||||
Parameters: {
|
||||
@@ -31,7 +31,7 @@ test("changeTimeHorizon: Shrink 1", () => {
|
||||
});
|
||||
|
||||
test("changeTimeHorizon: Shrink 2", () => {
|
||||
const [newScenario, err] = changeTimeHorizon(BUS_TEST_DATA_2, "1");
|
||||
const [newScenario, err] = changeTimeHorizon(TEST_DATA_2, "1");
|
||||
assert(err === null);
|
||||
assert.deepEqual(newScenario, {
|
||||
Parameters: {
|
||||
@@ -49,7 +49,7 @@ test("changeTimeHorizon: Shrink 2", () => {
|
||||
});
|
||||
|
||||
test("changeTimeHorizon grow", () => {
|
||||
const [newScenario, err] = changeTimeHorizon(BUS_TEST_DATA_1, "7");
|
||||
const [newScenario, err] = changeTimeHorizon(TEST_DATA_1, "7");
|
||||
assert(err === null);
|
||||
assert.deepEqual(newScenario, {
|
||||
Parameters: {
|
||||
@@ -73,11 +73,11 @@ test("changeTimeHorizon grow", () => {
|
||||
});
|
||||
|
||||
test("changeTimeHorizon invalid", () => {
|
||||
let [, err] = changeTimeHorizon(BUS_TEST_DATA_1, "x");
|
||||
let [, err] = changeTimeHorizon(TEST_DATA_1, "x");
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, "Invalid value: x");
|
||||
|
||||
[, err] = changeTimeHorizon(BUS_TEST_DATA_1, "-3");
|
||||
[, err] = changeTimeHorizon(TEST_DATA_1, "-3");
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, "Invalid value: -3");
|
||||
});
|
||||
@@ -93,7 +93,7 @@ test("evaluatePwlFunction", () => {
|
||||
});
|
||||
|
||||
test("changeTimeStep", () => {
|
||||
let [scenario, err] = changeTimeStep(BUS_TEST_DATA_2, "15");
|
||||
let [scenario, err] = changeTimeStep(TEST_DATA_2, "15");
|
||||
assert(err === null);
|
||||
assert.deepEqual(scenario, {
|
||||
Parameters: {
|
||||
@@ -109,7 +109,7 @@ test("changeTimeStep", () => {
|
||||
},
|
||||
});
|
||||
|
||||
[scenario, err] = changeTimeStep(BUS_TEST_DATA_2, "60");
|
||||
[scenario, err] = changeTimeStep(TEST_DATA_2, "60");
|
||||
assert(err === null);
|
||||
assert.deepEqual(scenario, {
|
||||
Parameters: {
|
||||
@@ -127,19 +127,19 @@ test("changeTimeStep", () => {
|
||||
});
|
||||
|
||||
test("changeTimeStep invalid", () => {
|
||||
let [, err] = changeTimeStep(BUS_TEST_DATA_2, "x");
|
||||
let [, err] = changeTimeStep(TEST_DATA_2, "x");
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, "Invalid value: x");
|
||||
|
||||
[, err] = changeTimeStep(BUS_TEST_DATA_2, "-10");
|
||||
[, err] = changeTimeStep(TEST_DATA_2, "-10");
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, "Invalid value: -10");
|
||||
|
||||
[, err] = changeTimeStep(BUS_TEST_DATA_2, "120");
|
||||
[, err] = changeTimeStep(TEST_DATA_2, "120");
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, "Invalid value: 120");
|
||||
|
||||
[, err] = changeTimeStep(BUS_TEST_DATA_2, "7");
|
||||
[, err] = changeTimeStep(TEST_DATA_2, "7");
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, "Time step must be a divisor of 60: 7");
|
||||
});
|
||||
|
||||
30
web/src/core/fixtures.test.ts
Normal file
30
web/src/core/fixtures.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { UnitCommitmentScenario } from "./fixtures";
|
||||
|
||||
export const TEST_DATA_1: UnitCommitmentScenario = {
|
||||
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] },
|
||||
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] },
|
||||
},
|
||||
};
|
||||
export const TEST_DATA_2: UnitCommitmentScenario = {
|
||||
Parameters: {
|
||||
Version: "0.4",
|
||||
"Power balance penalty ($/MW)": 1000.0,
|
||||
"Time horizon (h)": 2,
|
||||
"Time step (min)": 30,
|
||||
},
|
||||
Buses: {
|
||||
b1: { "Load (MW)": [30, 30, 30, 30] },
|
||||
b2: { "Load (MW)": [10, 20, 30, 40] },
|
||||
b3: { "Load (MW)": [0, 30, 0, 40] },
|
||||
},
|
||||
};
|
||||
|
||||
test("fixtures", () => {});
|
||||
Reference in New Issue
Block a user