Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
452 changes: 361 additions & 91 deletions src/applications/components/pf_matrix/pf_components.cpp

Large diffs are not rendered by default.

61 changes: 52 additions & 9 deletions src/applications/components/pf_matrix/pf_components.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
* @file pf_components.hpp
* @author Bruce Palmer
* @date 2016-07-14 13:27:00 d3g096
*
* @brief
*
*
*
* @updated Yousu Chen
* - Improved Q-limit handling with iterative PV-PQ conversion
* - Added island detection function
* - Automatic slack bus transfer for contingency analysis
* - RMPCT-based reactive power distribution for multi-generator buses
* @date 2026-01-31
*
* @brief
*
*
*/
// -------------------------------------------------------------

Expand Down Expand Up @@ -170,6 +177,36 @@ class PFBus
*/
bool getGenStatus(std::string gen_id);

/**
* Check if bus has any online generator
* @return true if at least one generator is online
*/
bool hasOnlineGenerator();

/**
* Get total capacity (Pmax) of all online generators on this bus
* @return total Pmax in MW
*/
double getOnlineGenCapacity();

/**
* Calculate power injection at this bus from connected branches.
* Updates p_Pinj and p_Qinj for slack bus.
*/
void calculatePowerInjection();

/**
* Get total real power output of all generators on this bus (after PF solve)
* @return total Pgen in MW
*/
double getTotalGenOutput();

/**
* Check if generator output exceeds capacity on this bus
* @return true if within limits, false if Pgen > Pmax
*/
bool checkGenCapacity();

/**
* Get list of generator IDs
* @return vector of generator IDs
Expand Down Expand Up @@ -203,8 +240,9 @@ class PFBus
* Set generator status
* @param gen_id generator ID
* @param status generator status
* @return true if generator ID found, false otherwise
*/
void setGenStatus(std::string gen_id, bool status);
bool setGenStatus(std::string gen_id, bool status);

/**
* Set isPV status
Expand Down Expand Up @@ -267,7 +305,7 @@ class PFBus
* This can be used as a way of moving data in a way that is useful for
* creating output or for copying state data from one network to another.
* @param data data collection object into which new values are inserted
* added by Renke, also modify the original bus mag, ang,
* added by Renke, also modify the original bus mag, ang,
* and the original generator PG QG in the datacollection
*/
void saveDataAlsotoOrg(boost::shared_ptr<gridpack::component::DataCollection> data);
Expand Down Expand Up @@ -456,10 +494,12 @@ class PFBus
// newly added priavate variables:
std::vector<double> p_pg, p_qg, p_pFac;
std::vector<double> p_savePg;
std::vector<double> p_saveQg; // Save original Q for restoration after Q limit handling
std::vector<int> p_gstatus;
std::vector<int> p_gstatus_save;
std::vector<double> p_qmax,p_qmin;
std::vector<double> p_qmax_orig, p_qmin_orig, p_pFac_orig;
std::vector<double> p_rmpct; // RMPCT: reactive power participation factor (PSS/E)
std::vector<double> p_vs;
std::vector<std::string> p_gid;
std::vector<double> p_pt;
Expand All @@ -477,6 +517,7 @@ class PFBus
int p_ngen;
int p_nload;
int p_type;
int p_save_type; // Save original bus type for restoration after Q limit handling
int p_area;
int p_zone;
bool p_source;
Expand Down Expand Up @@ -515,7 +556,8 @@ class PFBus
& p_P0 & p_Q0
& p_angle & p_voltage
& p_pg & p_qg & p_pFac & p_qmin & p_qmax
& p_qmin_orig & p_qmax_orig & p_pFac_orig
& p_qmin_orig & p_qmax_orig & p_pFac_orig & p_rmpct
& p_saveQg
& p_gstatus
& p_vs & p_gid
& p_pt & p_pb
Expand All @@ -527,7 +569,7 @@ class PFBus
& p_vmin & p_vmax
& p_isPV
& p_saveisPV
& p_ngen & p_type & p_nload
& p_ngen & p_type & p_save_type & p_nload
& p_area & p_zone
& p_source & p_sink
& p_rtpr_scale;
Expand Down Expand Up @@ -640,8 +682,9 @@ class PFBranch
* Set the status of the branch element
* @param tag character string identifying branch element
* @param status status of branch element
* @return true if circuit ID found, false otherwise
*/
void setBranchStatus(std::string tag, bool status);
bool setBranchStatus(std::string tag, bool status);

/**
* get branch rating A value
Expand Down
97 changes: 46 additions & 51 deletions src/applications/contingency_analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# -------------------------------------------------------------
# Created May 6, 2013 by William A. Perkins
# Last Change: 2017-12-08 09:37:40 d3g096
# Updated Jan. 29, 2026 by Yousu Chen
# -------------------------------------------------------------

set(target_libraries
Expand Down Expand Up @@ -77,77 +78,71 @@ add_custom_command(
)

add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/input.polish.xml"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/input_14_auto_n1.xml"
COMMAND ${CMAKE_COMMAND}
-D INPUT:PATH="${GRIDPACK_DATA_DIR}/input/ca/input.polish.xml"
-D OUTPUT:PATH="${CMAKE_CURRENT_BINARY_DIR}/input.polish.xml"
-D INPUT:PATH="${GRIDPACK_DATA_DIR}/input/ca/input_14_auto_n1.xml"
-D OUTPUT:PATH="${CMAKE_CURRENT_BINARY_DIR}/input_14_auto_n1.xml"
-D PKG:STRING="${GRIDPACK_MATSOLVER_PKG}"
-P "${PROJECT_SOURCE_DIR}/cmake-modules/set_lu_solver_pkg.cmake"
DEPENDS "${GRIDPACK_DATA_DIR}/input/ca/input.polish.xml"
DEPENDS "${GRIDPACK_DATA_DIR}/input/ca/input_14_auto_n1.xml"
)

add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/input.euro.xml"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/input_14_qlim.xml"
COMMAND ${CMAKE_COMMAND}
-D INPUT:PATH="${GRIDPACK_DATA_DIR}/input/ca/input.euro.xml"
-D OUTPUT:PATH="${CMAKE_CURRENT_BINARY_DIR}/input.euro.xml"
-D INPUT:PATH="${GRIDPACK_DATA_DIR}/input/ca/input_14_qlim.xml"
-D OUTPUT:PATH="${CMAKE_CURRENT_BINARY_DIR}/input_14_qlim.xml"
-D PKG:STRING="${GRIDPACK_MATSOLVER_PKG}"
-P "${PROJECT_SOURCE_DIR}/cmake-modules/set_lu_solver_pkg.cmake"
DEPENDS "${GRIDPACK_DATA_DIR}/input/ca/input.euro.xml"
DEPENDS "${GRIDPACK_DATA_DIR}/input/ca/input_14_qlim.xml"
)

add_custom_target(ca.x.input

COMMAND ${CMAKE_COMMAND} -E copy
# Copy data files only when source changes (avoids unnecessary copies on every build)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/IEEE14_ca.raw"
COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/raw/IEEE14_ca.raw
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS "${GRIDPACK_DATA_DIR}/raw/IEEE14_ca.raw"
)

COMMAND ${CMAKE_COMMAND} -E copy
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/contingencies_14.xml"
COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/contingencies/contingencies_14.xml
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS "${GRIDPACK_DATA_DIR}/contingencies/contingencies_14.xml"
)

COMMAND ${CMAKE_COMMAND} -E copy
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/IEEE118.raw"
COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/raw/IEEE118.raw
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS "${GRIDPACK_DATA_DIR}/raw/IEEE118.raw"
)

COMMAND ${CMAKE_COMMAND} -E copy
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/contingencies_118.xml"
COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/contingencies/contingencies_118.xml
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS "${GRIDPACK_DATA_DIR}/contingencies/contingencies_118.xml"
)

COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/raw/Polish_model_v23.raw
${CMAKE_CURRENT_BINARY_DIR}

COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/contingencies/contingencies_polish.xml
${CMAKE_CURRENT_BINARY_DIR}

COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/raw/EuropeanOpenModel_v23.raw
${CMAKE_CURRENT_BINARY_DIR}

COMMAND ${CMAKE_COMMAND} -E copy
${GRIDPACK_DATA_DIR}/contingencies/contingencies_euro.xml
${CMAKE_CURRENT_BINARY_DIR}

COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/README.md
${CMAKE_CURRENT_BINARY_DIR}
# Note: README.md and contingencies_nk_example.xml are static files that don't
# need processing. They are installed directly from source locations.

add_custom_target(ca.x.input
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/input_14.xml
${GRIDPACK_DATA_DIR}/raw/IEEE14_ca.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_14.xml
${CMAKE_CURRENT_BINARY_DIR}/input_14_auto_n1.xml
${CMAKE_CURRENT_BINARY_DIR}/input_14_qlim.xml
${CMAKE_CURRENT_BINARY_DIR}/input_118.xml
${GRIDPACK_DATA_DIR}/raw/IEEE118.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_118.xml
${CMAKE_CURRENT_BINARY_DIR}/input.polish.xml
${GRIDPACK_DATA_DIR}/raw/Polish_model_v23.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_polish.xml
${CMAKE_CURRENT_BINARY_DIR}/input.euro.xml
${GRIDPACK_DATA_DIR}/raw/EuropeanOpenModel_v23.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_euro.xml
${CMAKE_CURRENT_SOURCE_DIR}/README.md
${CMAKE_CURRENT_BINARY_DIR}/IEEE14_ca.raw
${CMAKE_CURRENT_BINARY_DIR}/IEEE118.raw
${CMAKE_CURRENT_BINARY_DIR}/contingencies_14.xml
${CMAKE_CURRENT_BINARY_DIR}/contingencies_118.xml
)
add_dependencies(ca.x ca.x.input)

Expand All @@ -157,23 +152,21 @@ add_dependencies(ca.x ca.x.input)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.install.in
${CMAKE_CURRENT_BINARY_DIR}/CMakeLists.txt @ONLY)

install(FILES
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/CMakeLists.txt
${CMAKE_CURRENT_BINARY_DIR}/input_14.xml
${CMAKE_CURRENT_BINARY_DIR}/input_14_auto_n1.xml
${CMAKE_CURRENT_BINARY_DIR}/input_14_qlim.xml
${GRIDPACK_DATA_DIR}/raw/IEEE14_ca.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_14.xml
${GRIDPACK_DATA_DIR}/contingencies/contingencies_nk_example.xml
${CMAKE_CURRENT_BINARY_DIR}/input_118.xml
${GRIDPACK_DATA_DIR}/raw/IEEE118.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_118.xml
${CMAKE_CURRENT_BINARY_DIR}/input.polish.xml
${GRIDPACK_DATA_DIR}/raw/Polish_model_v23.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_polish.xml
${CMAKE_CURRENT_BINARY_DIR}/input.euro.xml
${GRIDPACK_DATA_DIR}/raw/EuropeanOpenModel_v23.raw
${GRIDPACK_DATA_DIR}/contingencies/contingencies_euro.xml
${CMAKE_CURRENT_SOURCE_DIR}/ca_driver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ca_driver.hpp
${CMAKE_CURRENT_SOURCE_DIR}/ca_main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/README.md
DESTINATION share/gridpack/example/contingency_analysis
)

Expand All @@ -184,4 +177,6 @@ install(TARGETS ca.x DESTINATION bin)
# -------------------------------------------------------------
set(TIMEOUT 120.0)
gridpack_add_run_test("contingency_analysis" ca.x input_14.xml)
gridpack_add_run_test("contingency_analysis_auto_n1" ca.x input_14_auto_n1.xml)
gridpack_add_run_test("contingency_analysis_qlim" ca.x input_14_qlim.xml)

Loading