Compare commits
5 Commits
012331c4bd
...
eb3d39b1ab
Author | SHA1 | Date |
---|---|---|
|
eb3d39b1ab | 3 months ago |
|
3bf028577e | 3 months ago |
|
3f10ad23ca | 3 months ago |
|
7c752e4c31 | 3 months ago |
|
dea5217916 | 3 months ago |
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 assert from "node:assert";
|
||||
import { BusesColumnSpec, generateBusesData } from "./Buses";
|
||||
import { generateCsv, parseCsv } from "../Common/Forms/DataTable";
|
||||
import { TEST_DATA_1 } from "../../core/fixtures.test";
|
||||
|
||||
test("generate CSV", () => {
|
||||
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" +
|
||||
"b1,35.79534,34.38835,33.45083,32.89729,33.25044\n" +
|
||||
"b2,14.03739,13.48563,13.11797,12.9009,13.03939\n" +
|
||||
"b3,27.3729,26.29698,25.58005,25.15675,25.4268";
|
||||
assert.strictEqual(actualCsv, expectedCsv);
|
||||
});
|
||||
|
||||
test("parse CSV", () => {
|
||||
const csvContents =
|
||||
"Name,Load (MW) 00:00,Load (MW) 01:00,Load (MW) 02:00,Load (MW) 03:00,Load (MW) 04:00\n" +
|
||||
"b1,0,1,2,3,4\n" +
|
||||
"b3,27.3729,26.29698,25.58005,25.15675,25.4268";
|
||||
const [newBuses, err] = parseCsv(csvContents, BusesColumnSpec, TEST_DATA_1);
|
||||
assert(err === null);
|
||||
assert.deepEqual(newBuses, {
|
||||
b1: {
|
||||
"Load (MW)": [0, 1, 2, 3, 4],
|
||||
},
|
||||
b3: {
|
||||
"Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("parse CSV with duplicated names", () => {
|
||||
const csvContents =
|
||||
"Name,Load (MW) 00:00,Load (MW) 01:00,Load (MW) 02:00,Load (MW) 03:00,Load (MW) 04:00\n" +
|
||||
"b1,0,0,0,0,0\n" +
|
||||
"b1,0,0,0,0,0";
|
||||
const [, err] = parseCsv(csvContents, BusesColumnSpec, TEST_DATA_1);
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, `Name "b1" is duplicated (row 2)`);
|
||||
});
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 {
|
||||
floatFormatter,
|
||||
generateTableColumns,
|
||||
parseCsv,
|
||||
} from "../Common/Forms/DataTable";
|
||||
import {
|
||||
parseProfiledUnitsCsv,
|
||||
ProfiledUnitsColumnSpec,
|
||||
} from "./ProfiledUnits";
|
||||
import { TEST_DATA_1 } from "../../core/fixtures.test";
|
||||
import assert from "node:assert";
|
||||
import {
|
||||
getProfiledGenerators,
|
||||
getThermalGenerators,
|
||||
} from "../../core/fixtures";
|
||||
|
||||
test("parse CSV", () => {
|
||||
const csvContents =
|
||||
"Name,Bus,Cost ($/MW),Maximum power (MW) 00:00,Maximum power (MW) 01:00," +
|
||||
"Maximum power (MW) 02:00,Maximum power (MW) 03:00," +
|
||||
"Maximum power (MW) 04:00,Minimum power (MW) 00:00," +
|
||||
"Minimum power (MW) 01:00,Minimum power (MW) 02:00," +
|
||||
"Minimum power (MW) 03:00,Minimum power (MW) 04:00\n" +
|
||||
"pu1,b1,50,260.25384545,72.89148068,377.17886108,336.66732361," +
|
||||
"376.82781758,52.05076909,14.57829614,75.43577222,67.33346472,75.36556352\n" +
|
||||
"pu2,b1,0,0,0,0,0,0,0,0,0,0,0";
|
||||
const [scenario, err] = parseProfiledUnitsCsv(csvContents, TEST_DATA_1);
|
||||
assert(err === null);
|
||||
const thermalGens = getThermalGenerators(scenario);
|
||||
const profGens = getProfiledGenerators(scenario);
|
||||
assert.equal(Object.keys(thermalGens).length, 1);
|
||||
assert.equal(Object.keys(profGens).length, 2);
|
||||
|
||||
assert.deepEqual(profGens, {
|
||||
pu1: {
|
||||
Bus: "b1",
|
||||
"Minimum power (MW)": [
|
||||
52.05076909, 14.57829614, 75.43577222, 67.33346472, 75.36556352,
|
||||
],
|
||||
"Maximum power (MW)": [
|
||||
260.25384545, 72.89148068, 377.17886108, 336.66732361, 376.82781758,
|
||||
],
|
||||
"Cost ($/MW)": 50.0,
|
||||
Type: "Profiled",
|
||||
},
|
||||
pu2: {
|
||||
Bus: "b1",
|
||||
"Minimum power (MW)": [0, 0, 0, 0, 0],
|
||||
"Maximum power (MW)": [0, 0, 0, 0, 0],
|
||||
"Cost ($/MW)": 0.0,
|
||||
Type: "Profiled",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("parse CSV with invalid bus", () => {
|
||||
const csvContents =
|
||||
"Name,Bus,Cost ($/MW),Maximum power (MW) 00:00,Maximum power (MW) 01:00," +
|
||||
"Maximum power (MW) 02:00,Maximum power (MW) 03:00," +
|
||||
"Maximum power (MW) 04:00,Minimum power (MW) 00:00," +
|
||||
"Minimum power (MW) 01:00,Minimum power (MW) 02:00," +
|
||||
"Minimum power (MW) 03:00,Minimum power (MW) 04:00\n" +
|
||||
"pu1,b99,50,260.25384545,72.89148068,377.17886108,336.66732361," +
|
||||
"376.82781758,52.05076909,14.57829614,75.43577222,67.33346472,75.36556352\n" +
|
||||
"pu2,b1,0,0,0,0,0,0,0,0,0,0,0";
|
||||
const [, err] = parseCsv(csvContents, ProfiledUnitsColumnSpec, TEST_DATA_1);
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, 'Bus "b99" does not exist (row 1)');
|
||||
});
|
||||
|
||||
test("generateTableColumns", () => {
|
||||
const columns = generateTableColumns(TEST_DATA_1, ProfiledUnitsColumnSpec);
|
||||
assert.equal(columns.length, 5);
|
||||
assert.deepEqual(columns[0], {
|
||||
editor: "input",
|
||||
editorParams: {
|
||||
selectContents: true,
|
||||
},
|
||||
field: "Name",
|
||||
formatter: "plaintext",
|
||||
headerHozAlign: "left",
|
||||
headerSort: false,
|
||||
headerWordWrap: true,
|
||||
hozAlign: "left",
|
||||
minWidth: 100,
|
||||
resizable: false,
|
||||
title: "Name",
|
||||
});
|
||||
assert.equal(columns[3]!["columns"]!.length, 5);
|
||||
assert.deepEqual(columns[3]!["columns"]![0], {
|
||||
editor: "input",
|
||||
editorParams: {
|
||||
selectContents: true,
|
||||
},
|
||||
field: "Maximum power (MW) 00:00",
|
||||
formatter: floatFormatter,
|
||||
headerHozAlign: "left",
|
||||
headerSort: false,
|
||||
headerWordWrap: true,
|
||||
hozAlign: "left",
|
||||
minWidth: 60,
|
||||
resizable: false,
|
||||
title: "00:00",
|
||||
});
|
||||
});
|
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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 {
|
||||
floatFormatter,
|
||||
generateCsv,
|
||||
generateTableColumns,
|
||||
generateTableData,
|
||||
} from "../Common/Forms/DataTable";
|
||||
import { TEST_DATA_1 } from "../../core/fixtures.test";
|
||||
import {
|
||||
generateThermalUnitsData,
|
||||
parseThermalUnitsCsv,
|
||||
ThermalUnitsColumnSpec,
|
||||
} from "./ThermalUnits";
|
||||
import assert from "node:assert";
|
||||
import {
|
||||
getProfiledGenerators,
|
||||
getThermalGenerators,
|
||||
} from "../../core/fixtures";
|
||||
|
||||
test("generateTableColumns", () => {
|
||||
const columns = generateTableColumns(TEST_DATA_1, ThermalUnitsColumnSpec);
|
||||
assert.equal(columns[2]!["columns"]!.length, 10);
|
||||
assert.deepEqual(columns[2]!["columns"]![0], {
|
||||
editor: "input",
|
||||
editorParams: {
|
||||
selectContents: true,
|
||||
},
|
||||
field: "Production cost curve (MW) 1",
|
||||
formatter: floatFormatter,
|
||||
headerHozAlign: "left",
|
||||
headerSort: false,
|
||||
headerWordWrap: true,
|
||||
hozAlign: "left",
|
||||
minWidth: 60,
|
||||
resizable: false,
|
||||
title: "1",
|
||||
});
|
||||
});
|
||||
|
||||
test("generateTableData", () => {
|
||||
const data = generateTableData(
|
||||
getThermalGenerators(TEST_DATA_1),
|
||||
ThermalUnitsColumnSpec,
|
||||
TEST_DATA_1,
|
||||
);
|
||||
assert.deepEqual(data[0], {
|
||||
Name: "g1",
|
||||
Bus: "b1",
|
||||
"Initial power (MW)": 115,
|
||||
"Initial status (h)": 12,
|
||||
"Minimum downtime (h)": 4,
|
||||
"Minimum uptime (h)": 4,
|
||||
"Ramp down limit (MW)": 232.68,
|
||||
"Ramp up limit (MW)": 232.68,
|
||||
"Shutdown limit (MW)": 232.68,
|
||||
"Startup limit (MW)": 232.68,
|
||||
"Production cost curve ($) 1": 1400,
|
||||
"Production cost curve ($) 2": 1600,
|
||||
"Production cost curve ($) 3": 2200,
|
||||
"Production cost curve ($) 4": 2400,
|
||||
"Production cost curve ($) 5": "",
|
||||
"Production cost curve ($) 6": "",
|
||||
"Production cost curve ($) 7": "",
|
||||
"Production cost curve ($) 8": "",
|
||||
"Production cost curve ($) 9": "",
|
||||
"Production cost curve ($) 10": "",
|
||||
"Production cost curve (MW) 1": 100,
|
||||
"Production cost curve (MW) 2": 110,
|
||||
"Production cost curve (MW) 3": 130,
|
||||
"Production cost curve (MW) 4": 135,
|
||||
"Production cost curve (MW) 5": "",
|
||||
"Production cost curve (MW) 6": "",
|
||||
"Production cost curve (MW) 7": "",
|
||||
"Production cost curve (MW) 8": "",
|
||||
"Production cost curve (MW) 9": "",
|
||||
"Production cost curve (MW) 10": "",
|
||||
"Startup costs ($) 1": 300,
|
||||
"Startup costs ($) 2": 400,
|
||||
"Startup costs ($) 3": "",
|
||||
"Startup costs ($) 4": "",
|
||||
"Startup costs ($) 5": "",
|
||||
"Startup delays (h) 1": 1,
|
||||
"Startup delays (h) 2": 4,
|
||||
"Startup delays (h) 3": "",
|
||||
"Startup delays (h) 4": "",
|
||||
"Startup delays (h) 5": "",
|
||||
"Must run?": false,
|
||||
});
|
||||
});
|
||||
|
||||
const expectedCsvContents =
|
||||
"Name,Bus," +
|
||||
"Production cost curve (MW) 1," +
|
||||
"Production cost curve (MW) 2," +
|
||||
"Production cost curve (MW) 3," +
|
||||
"Production cost curve (MW) 4," +
|
||||
"Production cost curve (MW) 5," +
|
||||
"Production cost curve (MW) 6," +
|
||||
"Production cost curve (MW) 7," +
|
||||
"Production cost curve (MW) 8," +
|
||||
"Production cost curve (MW) 9," +
|
||||
"Production cost curve (MW) 10," +
|
||||
"Production cost curve ($) 1," +
|
||||
"Production cost curve ($) 2," +
|
||||
"Production cost curve ($) 3," +
|
||||
"Production cost curve ($) 4," +
|
||||
"Production cost curve ($) 5," +
|
||||
"Production cost curve ($) 6," +
|
||||
"Production cost curve ($) 7," +
|
||||
"Production cost curve ($) 8," +
|
||||
"Production cost curve ($) 9," +
|
||||
"Production cost curve ($) 10," +
|
||||
"Startup costs ($) 1," +
|
||||
"Startup costs ($) 2," +
|
||||
"Startup costs ($) 3," +
|
||||
"Startup costs ($) 4," +
|
||||
"Startup costs ($) 5," +
|
||||
"Startup delays (h) 1," +
|
||||
"Startup delays (h) 2," +
|
||||
"Startup delays (h) 3," +
|
||||
"Startup delays (h) 4," +
|
||||
"Startup delays (h) 5," +
|
||||
"Minimum uptime (h),Minimum downtime (h),Ramp up limit (MW)," +
|
||||
"Ramp down limit (MW),Startup limit (MW),Shutdown limit (MW)," +
|
||||
"Initial status (h),Initial power (MW),Must run?\n" +
|
||||
"g1,b1,100,110,130,135,,,,,,,1400,1600,2200,2400,,,,,,,300,400,,,,1,4,,,,4,4,232.68,232.68,232.68,232.68,12,115,false";
|
||||
|
||||
const invalidCsv =
|
||||
"Name,Bus," +
|
||||
"Production cost curve (MW) 1," +
|
||||
"Production cost curve (MW) 2," +
|
||||
"Production cost curve (MW) 3," +
|
||||
"Production cost curve (MW) 4," +
|
||||
"Production cost curve (MW) 5," +
|
||||
"Production cost curve (MW) 6," +
|
||||
"Production cost curve (MW) 7," +
|
||||
"Production cost curve (MW) 8," +
|
||||
"Production cost curve (MW) 9," +
|
||||
"Production cost curve (MW) 10," +
|
||||
"Production cost curve ($) 1," +
|
||||
"Production cost curve ($) 2," +
|
||||
"Production cost curve ($) 3," +
|
||||
"Production cost curve ($) 4," +
|
||||
"Production cost curve ($) 5," +
|
||||
"Production cost curve ($) 6," +
|
||||
"Production cost curve ($) 7," +
|
||||
"Production cost curve ($) 8," +
|
||||
"Production cost curve ($) 9," +
|
||||
"Production cost curve ($) 10," +
|
||||
"Startup costs ($) 1," +
|
||||
"Startup costs ($) 2," +
|
||||
"Startup costs ($) 3," +
|
||||
"Startup costs ($) 4," +
|
||||
"Startup costs ($) 5," +
|
||||
"Startup delays (h) 1," +
|
||||
"Startup delays (h) 2," +
|
||||
"Startup delays (h) 3," +
|
||||
"Startup delays (h) 4," +
|
||||
"Startup delays (h) 5," +
|
||||
"Minimum uptime (h),Minimum downtime (h),Ramp up limit (MW)," +
|
||||
"Ramp down limit (MW),Startup limit (MW),Shutdown limit (MW)," +
|
||||
"Initial status (h),Initial power (MW),Must run?\n" +
|
||||
"g1,b1,100,110,130,x,,,,,,,1400,1600,2200,2400,,,,,,,300,400,,,,1,4,,,,4,4,232.68,232.68,232.68,232.68,12,115,false";
|
||||
|
||||
test("generateCSV", () => {
|
||||
const [data, columns] = generateThermalUnitsData(TEST_DATA_1);
|
||||
const actualCsvContents = generateCsv(data, columns);
|
||||
assert.equal(actualCsvContents, expectedCsvContents);
|
||||
});
|
||||
|
||||
test("parseCSV", () => {
|
||||
const [scenario, err] = parseThermalUnitsCsv(
|
||||
expectedCsvContents,
|
||||
TEST_DATA_1,
|
||||
);
|
||||
assert(!err);
|
||||
const thermalGens = getThermalGenerators(scenario);
|
||||
const profGens = getProfiledGenerators(scenario);
|
||||
assert.equal(Object.keys(thermalGens).length, 1);
|
||||
assert.equal(Object.keys(profGens).length, 2);
|
||||
assert.deepEqual(thermalGens["g1"], {
|
||||
Bus: "b1",
|
||||
Type: "Thermal",
|
||||
"Production cost curve (MW)": [100.0, 110.0, 130.0, 135.0],
|
||||
"Production cost curve ($)": [1400.0, 1600.0, 2200.0, 2400.0],
|
||||
"Startup costs ($)": [300.0, 400.0],
|
||||
"Startup delays (h)": [1, 4],
|
||||
"Ramp up limit (MW)": 232.68,
|
||||
"Ramp down limit (MW)": 232.68,
|
||||
"Startup limit (MW)": 232.68,
|
||||
"Shutdown limit (MW)": 232.68,
|
||||
"Minimum downtime (h)": 4,
|
||||
"Minimum uptime (h)": 4,
|
||||
"Initial status (h)": 12,
|
||||
"Initial power (MW)": 115,
|
||||
"Must run?": false,
|
||||
});
|
||||
});
|
||||
|
||||
test("parseCSV with invalid number[T]", () => {
|
||||
const [, err] = parseThermalUnitsCsv(invalidCsv, TEST_DATA_1);
|
||||
assert(err);
|
||||
assert.equal(err.message, '"x" is not a valid number (row 1)');
|
||||
});
|
@ -1,214 +0,0 @@
|
||||
/*
|
||||
* 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 assert from "node:assert";
|
||||
import { BusesColumnSpec, generateBusesData } from "../../CaseBuilder/Buses";
|
||||
import {
|
||||
floatFormatter,
|
||||
generateCsv,
|
||||
generateTableColumns,
|
||||
generateTableData,
|
||||
parseCsv,
|
||||
} from "./DataTable";
|
||||
import { TEST_DATA_1 } from "../../../core/fixtures.test";
|
||||
import { ProfiledUnitsColumnSpec } from "../../CaseBuilder/ProfiledUnits";
|
||||
import { ThermalUnitsColumnSpec } from "../../CaseBuilder/ThermalUnits";
|
||||
import { getThermalGenerators } from "../../../core/fixtures";
|
||||
|
||||
test("generateTableColumns (ProfiledUnits)", () => {
|
||||
const columns = generateTableColumns(TEST_DATA_1, ProfiledUnitsColumnSpec);
|
||||
assert.equal(columns.length, 5);
|
||||
assert.deepEqual(columns[0], {
|
||||
editor: "input",
|
||||
editorParams: {
|
||||
selectContents: true,
|
||||
},
|
||||
field: "Name",
|
||||
formatter: "plaintext",
|
||||
headerHozAlign: "left",
|
||||
headerSort: false,
|
||||
headerWordWrap: true,
|
||||
hozAlign: "left",
|
||||
minWidth: 100,
|
||||
resizable: false,
|
||||
title: "Name",
|
||||
});
|
||||
assert.equal(columns[3]!["columns"]!.length, 5);
|
||||
assert.deepEqual(columns[3]!["columns"]![0], {
|
||||
editor: "input",
|
||||
editorParams: {
|
||||
selectContents: true,
|
||||
},
|
||||
field: "Maximum power (MW) 00:00",
|
||||
formatter: floatFormatter,
|
||||
headerHozAlign: "left",
|
||||
headerSort: false,
|
||||
headerWordWrap: true,
|
||||
hozAlign: "left",
|
||||
minWidth: 60,
|
||||
resizable: false,
|
||||
title: "00:00",
|
||||
});
|
||||
});
|
||||
|
||||
test("generateTableColumns (ThermalUnits)", () => {
|
||||
const columns = generateTableColumns(TEST_DATA_1, ThermalUnitsColumnSpec);
|
||||
assert.equal(columns[2]!["columns"]!.length, 10);
|
||||
assert.deepEqual(columns[2]!["columns"]![0], {
|
||||
editor: "input",
|
||||
editorParams: {
|
||||
selectContents: true,
|
||||
},
|
||||
field: "Production cost curve (MW) 1",
|
||||
formatter: floatFormatter,
|
||||
headerHozAlign: "left",
|
||||
headerSort: false,
|
||||
headerWordWrap: true,
|
||||
hozAlign: "left",
|
||||
minWidth: 60,
|
||||
resizable: false,
|
||||
title: "1",
|
||||
});
|
||||
});
|
||||
|
||||
test("generateTableData (ThermalUnits)", () => {
|
||||
const data = generateTableData(
|
||||
getThermalGenerators(TEST_DATA_1),
|
||||
ThermalUnitsColumnSpec,
|
||||
TEST_DATA_1,
|
||||
);
|
||||
assert.deepEqual(data[0], {
|
||||
Name: "gen1",
|
||||
Bus: "b1",
|
||||
"Initial power (MW)": 115,
|
||||
"Initial status (h)": 12,
|
||||
"Minimum downtime (h)": 4,
|
||||
"Minimum uptime (h)": 4,
|
||||
"Ramp down limit (MW)": 232.68,
|
||||
"Ramp up limit (MW)": 232.68,
|
||||
"Shutdown limit (MW)": 232.68,
|
||||
"Startup limit (MW)": 232.68,
|
||||
"Production cost curve ($) 1": 1400,
|
||||
"Production cost curve ($) 2": 1600,
|
||||
"Production cost curve ($) 3": 2200,
|
||||
"Production cost curve ($) 4": 2400,
|
||||
"Production cost curve ($) 5": "",
|
||||
"Production cost curve ($) 6": "",
|
||||
"Production cost curve ($) 7": "",
|
||||
"Production cost curve ($) 8": "",
|
||||
"Production cost curve ($) 9": "",
|
||||
"Production cost curve ($) 10": "",
|
||||
"Production cost curve (MW) 1": 100,
|
||||
"Production cost curve (MW) 2": 110,
|
||||
"Production cost curve (MW) 3": 130,
|
||||
"Production cost curve (MW) 4": 135,
|
||||
"Production cost curve (MW) 5": "",
|
||||
"Production cost curve (MW) 6": "",
|
||||
"Production cost curve (MW) 7": "",
|
||||
"Production cost curve (MW) 8": "",
|
||||
"Production cost curve (MW) 9": "",
|
||||
"Production cost curve (MW) 10": "",
|
||||
"Startup costs ($) 1": 300,
|
||||
"Startup costs ($) 2": 400,
|
||||
"Startup costs ($) 3": "",
|
||||
"Startup costs ($) 4": "",
|
||||
"Startup costs ($) 5": "",
|
||||
"Startup delays (h) 1": 1,
|
||||
"Startup delays (h) 2": 4,
|
||||
"Startup delays (h) 3": "",
|
||||
"Startup delays (h) 4": "",
|
||||
"Startup delays (h) 5": "",
|
||||
});
|
||||
});
|
||||
|
||||
test("generate CSV", () => {
|
||||
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" +
|
||||
"b1,35.79534,34.38835,33.45083,32.89729,33.25044\n" +
|
||||
"b2,14.03739,13.48563,13.11797,12.9009,13.03939\n" +
|
||||
"b3,27.3729,26.29698,25.58005,25.15675,25.4268";
|
||||
assert.strictEqual(actualCsv, expectedCsv);
|
||||
});
|
||||
|
||||
test("parse CSV (Buses)", () => {
|
||||
const csvContents =
|
||||
"Name,Load (MW) 00:00,Load (MW) 01:00,Load (MW) 02:00,Load (MW) 03:00,Load (MW) 04:00\n" +
|
||||
"b1,0,1,2,3,4\n" +
|
||||
"b3,27.3729,26.29698,25.58005,25.15675,25.4268";
|
||||
const [newBuses, err] = parseCsv(csvContents, BusesColumnSpec, TEST_DATA_1);
|
||||
assert(err === null);
|
||||
assert.deepEqual(newBuses, {
|
||||
b1: {
|
||||
"Load (MW)": [0, 1, 2, 3, 4],
|
||||
},
|
||||
b3: {
|
||||
"Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("parse CSV with duplicated names", () => {
|
||||
const csvContents =
|
||||
"Name,Load (MW) 00:00,Load (MW) 01:00,Load (MW) 02:00,Load (MW) 03:00,Load (MW) 04:00\n" +
|
||||
"b1,0,0,0,0,0\n" +
|
||||
"b1,0,0,0,0,0";
|
||||
const [, err] = parseCsv(csvContents, BusesColumnSpec, TEST_DATA_1);
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, `Name "b1" is duplicated (row 2)`);
|
||||
});
|
||||
|
||||
test("parse CSV (Profiled Units)", () => {
|
||||
const csvContents =
|
||||
"Name,Bus,Cost ($/MW),Maximum power (MW) 00:00,Maximum power (MW) 01:00," +
|
||||
"Maximum power (MW) 02:00,Maximum power (MW) 03:00," +
|
||||
"Maximum power (MW) 04:00,Minimum power (MW) 00:00," +
|
||||
"Minimum power (MW) 01:00,Minimum power (MW) 02:00," +
|
||||
"Minimum power (MW) 03:00,Minimum power (MW) 04:00\n" +
|
||||
"pu1,b1,50,260.25384545,72.89148068,377.17886108,336.66732361," +
|
||||
"376.82781758,52.05076909,14.57829614,75.43577222,67.33346472,75.36556352\n" +
|
||||
"pu2,b1,0,0,0,0,0,0,0,0,0,0,0";
|
||||
const [newGenerators, err] = parseCsv(
|
||||
csvContents,
|
||||
ProfiledUnitsColumnSpec,
|
||||
TEST_DATA_1,
|
||||
);
|
||||
assert(err === null);
|
||||
assert.deepEqual(newGenerators, {
|
||||
pu1: {
|
||||
Bus: "b1",
|
||||
"Minimum power (MW)": [
|
||||
52.05076909, 14.57829614, 75.43577222, 67.33346472, 75.36556352,
|
||||
],
|
||||
"Maximum power (MW)": [
|
||||
260.25384545, 72.89148068, 377.17886108, 336.66732361, 376.82781758,
|
||||
],
|
||||
"Cost ($/MW)": 50.0,
|
||||
},
|
||||
pu2: {
|
||||
Bus: "b1",
|
||||
"Minimum power (MW)": [0, 0, 0, 0, 0],
|
||||
"Maximum power (MW)": [0, 0, 0, 0, 0],
|
||||
"Cost ($/MW)": 0.0,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("parse CSV with invalid bus", () => {
|
||||
const csvContents =
|
||||
"Name,Bus,Cost ($/MW),Maximum power (MW) 00:00,Maximum power (MW) 01:00," +
|
||||
"Maximum power (MW) 02:00,Maximum power (MW) 03:00," +
|
||||
"Maximum power (MW) 04:00,Minimum power (MW) 00:00," +
|
||||
"Minimum power (MW) 01:00,Minimum power (MW) 02:00," +
|
||||
"Minimum power (MW) 03:00,Minimum power (MW) 04:00\n" +
|
||||
"pu1,b99,50,260.25384545,72.89148068,377.17886108,336.66732361," +
|
||||
"376.82781758,52.05076909,14.57829614,75.43577222,67.33346472,75.36556352\n" +
|
||||
"pu2,b1,0,0,0,0,0,0,0,0,0,0,0";
|
||||
const [, err] = parseCsv(csvContents, ProfiledUnitsColumnSpec, TEST_DATA_1);
|
||||
assert(err !== null);
|
||||
assert.equal(err.message, 'Bus "b99" does not exist (row 1)');
|
||||
});
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 { parseBool } from "./commonOps";
|
||||
import assert from "node:assert";
|
||||
|
||||
test("parseBool", () => {
|
||||
// True values
|
||||
for (const str of ["true", "TRUE", "1"]) {
|
||||
let [v, err] = parseBool(str);
|
||||
assert(!err);
|
||||
assert.equal(v, true);
|
||||
}
|
||||
|
||||
// False values
|
||||
for (const str of ["false", "FALSE", "0"]) {
|
||||
let [v, err] = parseBool(str);
|
||||
assert(!err);
|
||||
assert.equal(v, false);
|
||||
}
|
||||
|
||||
// Invalid values
|
||||
for (const str of ["qwe", ""]) {
|
||||
let [, err] = parseBool(str);
|
||||
assert(err);
|
||||
}
|
||||
});
|
Loading…
Reference in new issue