web: Update busOperations to support time-indexed loads

web
Alinson S. Xavier 3 months ago
parent 80d8bb838c
commit eb862e5701

@ -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 3", "99", scenario);
[scenario, err] = changeBusData("b1", "Load (MW) 03:00", "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");
});

@ -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", () => {});
Loading…
Cancel
Save