diff --git a/datafiles/unit/opflow/objective/OF_unittestx3.m b/datafiles/unit/opflow/objective/testx3.m similarity index 100% rename from datafiles/unit/opflow/objective/OF_unittestx3.m rename to datafiles/unit/opflow/objective/testx3.m diff --git a/datafiles/unit/opflow/objective/OF_unittestx600.m b/datafiles/unit/opflow/objective/testx600.m similarity index 100% rename from datafiles/unit/opflow/objective/OF_unittestx600.m rename to datafiles/unit/opflow/objective/testx600.m diff --git a/tests/unit/opflow/CMakeLists.txt b/tests/unit/opflow/CMakeLists.txt index 2f09e12f..a312cf31 100644 --- a/tests/unit/opflow/CMakeLists.txt +++ b/tests/unit/opflow/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(objective) +add_subdirectory(constraint_jacobian) diff --git a/tests/unit/opflow/constraint_jacobian/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/CMakeLists.txt new file mode 100644 index 00000000..5a69e533 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(equality) +add_subdirectory(inequality) diff --git a/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt new file mode 100644 index 00000000..4c9e1630 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/equality/CMakeLists.txt @@ -0,0 +1,97 @@ +if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_CUDA) + set_source_files_properties(jac_eq_acopf.cpp PROPERTIES LANGUAGE CUDA) +endif() + +add_executable( + jac_eq_acopf jac_eq_acopf.cpp + ${CMAKE_SOURCE_DIR}/tests/unit/utils/test_acopf_utils.cpp +) +target_link_libraries(jac_eq_acopf ExaGO::OPFLOW) +target_include_directories( + jac_eq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/utils +) +target_include_directories( + jac_eq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/opflow +) + +# Network files to run on - doing 3 and 600 bus examples. +set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) +set(obj_network_files testx3.m testx600.m) +# Map num_copies to a specific netfile +set(num_copies 3 600) + +list(TRANSFORM obj_network_files PREPEND ${prefix}) + +set(solvers "") +set(models "") +set(dependencies "") + +# Set up Ipopt solver tests if enabled +if(EXAGO_ENABLE_IPOPT) + list(APPEND solvers IPOPT) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies IPOPT) +endif() + +# Set up HIOP solver tests if enabled (deprecated) +if(EXAGO_ENABLE_HIOP) + list(APPEND solvers HIOP) + list(APPEND models POWER_BALANCE_HIOP) + list(APPEND dependencies HIOP) +endif() + +# Set up HIOPSPARSE solver tests if enabled +if(TARGET HiOp::SPARSE) + list(APPEND solvers HIOPSPARSE) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies HIOP_SPARSE) +endif() + +# Set up RAJA support tests if enabled (deprecated) +if(EXAGO_ENABLE_RAJA) + list(APPEND solvers HIOP) + list(APPEND models PBPOLRAJAHIOP) + list(APPEND dependencies HIOP) +endif() + +if(EXAGO_RUN_TESTS) + foreach( + model + solver + dependency + IN + ZIP_LISTS + models + solvers + dependencies + ) + # Iterate over networks, matching network file to num_copies + foreach(network num IN ZIP_LISTS obj_network_files num_copies) + get_filename_component(net ${network} NAME) + set(testname + "UNIT_TESTS_EQUALITY_CONSTRAINT_JACOBIAN_${net}_${solver}_${model}" + ) + message(STATUS "Setting up test: ${testname}") + exago_add_test( + NAME + ${testname} + DEPENDS + ${dependency} + COMMAND + ${RUNCMD} + $ + -opflow_model + ${model} + -opflow_solver + ${solver} + -netfile + ${network} + -num_copies + ${num} + -validation + ${CMAKE_CURRENT_SOURCE_DIR}/cecj.csv + ) + set_tests_properties(${testname} PROPERTIES SKIP_RETURN_CODE 2) + endforeach() + endforeach() +endif() diff --git a/tests/unit/opflow/constraint_jacobian/equality/compute_equality_constraints_jacobian_test_design.md b/tests/unit/opflow/constraint_jacobian/equality/README.md similarity index 100% rename from tests/unit/opflow/constraint_jacobian/equality/compute_equality_constraints_jacobian_test_design.md rename to tests/unit/opflow/constraint_jacobian/equality/README.md diff --git a/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp new file mode 100644 index 00000000..2b09eea4 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/equality/jac_eq_acopf.cpp @@ -0,0 +1,166 @@ +#include +#include +#include + +#include +#include +#include + +#include "opflow_tests.h" +#include "test_acopf_utils.h" + +/** + * @brief Unit test driver for objective function + * @see opflow/OpflowTests.hpp for kernel tested by this driver + * + * You can pass two options to the objectiveAcopf executatable through the + * command line (implemented using PETSc options): + * + * ~ -netfile : Specifies the input data file to test against. + * Default value is `//datafiles/case9/case9mod.m`. See directory + * datafiles for other potential inputs. + * + * ~ -num_copies : Specifies the number of replications of the + * network given through `-netfile`. If this is not set properly, test may fail + * + */ +int main(int argc, char **argv) { + PetscErrorCode ierr; + PetscBool flg; + Vec X; + int fail = 0; + double obj_value; + char file_c_str[PETSC_MAX_PATH_LEN]; + char validation_c_str[PETSC_MAX_PATH_LEN]; + std::string file; + char appname[] = "opflow"; + MPI_Comm comm = MPI_COMM_WORLD; + int num_copies = 0; + + char help[] = "Unit tests for equality constraint Jacobians running opflow\n"; + + /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ + ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + if (ierr) { + fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); + return ierr; + } + + /* Get network data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + + /* Get num_copies from command line */ + ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); + CHKERRQ(ierr); + + if (!flg) { + file = "../datafiles/case9/case9mod.m"; + } else { + file.assign(file_c_str); + } + + // Set obj_value as reference solution, and run as usual + /* Get validation data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-validation", validation_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + readFromFile(&obj_value, validation_c_str); + + obj_value = obj_value * num_copies; + + OPFLOW opflowtest; + exago::tests::TestOpflow test; + + /* Set up test opflow */ + ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); + CHKERRQ(ierr); + ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); + CHKERRQ(ierr); + ierr = OPFLOWSetUp(opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWGetSolution(opflowtest, &X); + CHKERRQ(ierr); + + // If we are using HIOP, need to convert X + // The string lengths must be 65 + std::string modelname; + std::string solvername; + ierr = OPFLOWGetModel(opflowtest, &modelname); + ierr = OPFLOWGetSolver(opflowtest, &solvername); + + if (solvername == "HIOP") { +#if defined(EXAGO_ENABLE_HIOP) + double *x_ref; + ierr = VecGetArray(X, &x_ref); + + int nx, nconeq, nconineq; + ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); + CHKERRQ(ierr); + + // If we are running using the CPU model, nothing needs to be done + if (modelname == "POWER_BALANCE_HIOP") { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref, obj_value); + } else // Using model PBPOLRAJAHIOP + { +#if defined(EXAGO_ENABLE_RAJA) + // Get resource manager instance + auto &resmgr = umpire::ResourceManager::getInstance(); + + // Get Allocator + umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); + + // Register array xref with umpire + umpire::util::AllocationRecord record_x{ + x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; + resmgr.registerAllocation(x_ref, record_x); + // Allocate and copy xref to device + double *x_ref_dev; + +#ifdef EXAGO_ENABLE_GPU + + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); + CHKERRQ(ierr); + + umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); + x_ref_dev = + static_cast(d_allocator.allocate(nx * sizeof(double))); +#else + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); + CHKERRQ(ierr); + x_ref_dev = x_ref; +#endif + resmgr.copy(x_ref_dev, x_ref); + + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); + +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(x_ref_dev); +#endif +#endif + } + + ierr = VecRestoreArray(X, &x_ref); + CHKERRQ(ierr); + + ierr = PetscFree(x_ref); + CHKERRQ(ierr); +#endif // End #ifdefined(EXAGO_ENABLE_HIOP) + } else { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, X, obj_value); + } + ierr = OPFLOWDestroy(&opflowtest); + CHKERRQ(ierr); + + // Temporarily skip the test + fail = exago::tests::SKIP_TEST; + + ExaGOFinalize(); + return fail; +} diff --git a/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt new file mode 100644 index 00000000..18177699 --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/inequality/CMakeLists.txt @@ -0,0 +1,92 @@ +if(EXAGO_ENABLE_RAJA AND EXAGO_ENABLE_CUDA) + set_source_files_properties(jac_ineq_acopf.cpp PROPERTIES LANGUAGE CUDA) +endif() + +add_executable( + jac_ineq_acopf jac_ineq_acopf.cpp + ${CMAKE_SOURCE_DIR}/tests/unit/utils/test_acopf_utils.cpp +) +target_link_libraries(jac_ineq_acopf ExaGO::OPFLOW) +target_include_directories( + jac_ineq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/utils +) +target_include_directories( + jac_ineq_acopf PRIVATE ${CMAKE_SOURCE_DIR}/tests/unit/opflow +) + +# Network files to run on - doing 3 and 600 bus examples. +set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) +set(obj_network_files testx3.m testx600.m) +# Map num_copies to a specific netfile +set(num_copies 3 600) + +list(TRANSFORM obj_network_files PREPEND ${prefix}) + +# Set up Ipopt solver tests if enabled +if(EXAGO_ENABLE_IPOPT) + list(APPEND solvers IPOPT) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies IPOPT) +endif() + +# Set up HIOP solver tests if enabled (deprecated) +if(EXAGO_ENABLE_HIOP) + list(APPEND solvers HIOP) + list(APPEND models POWER_BALANCE_HIOP) + list(APPEND dependencies HIOP) +endif() + +# Set up HIOPSPARSE solver tests if enabled +if(TARGET HiOp::SPARSE) + list(APPEND solvers HIOPSPARSE) + list(APPEND models POWER_BALANCE_POLAR) + list(APPEND dependencies HIOP_SPARSE) +endif() + +# Set up RAJA support tests if enabled (deprecated) +if(EXAGO_ENABLE_RAJA) + list(APPEND solvers HIOP) + list(APPEND models PBPOLRAJAHIOP) + list(APPEND dependencies HIOP) +endif() + +if(EXAGO_RUN_TESTS) + foreach( + model + solver + dependency + IN + ZIP_LISTS + models + solvers + dependencies + ) + # Iterate over networks, matching network file to num_copies + foreach(network num IN ZIP_LISTS obj_network_files num_copies) + get_filename_component(net ${network} NAME) + set(testname + "UNIT_TESTS_INEQUALITY_CONSTRAINT_JACOBIAN_${net}_${solver}_${model}" + ) + exago_add_test( + NAME + ${testname} + DEPENDS + ${dependency} + COMMAND + ${RUNCMD} + $ + -opflow_model + ${model} + -opflow_solver + ${solver} + -netfile + ${network} + -num_copies + ${num} + -validation + ${CMAKE_CURRENT_SOURCE_DIR}/cicj.csv + ) + set_tests_properties(${testname} PROPERTIES SKIP_RETURN_CODE 2) + endforeach() + endforeach() +endif() diff --git a/tests/unit/opflow/constraint_jacobian/inequality/compute_inequality_constraints_jacobian_test_design.md b/tests/unit/opflow/constraint_jacobian/inequality/README.md similarity index 100% rename from tests/unit/opflow/constraint_jacobian/inequality/compute_inequality_constraints_jacobian_test_design.md rename to tests/unit/opflow/constraint_jacobian/inequality/README.md diff --git a/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp new file mode 100644 index 00000000..4a6fc30c --- /dev/null +++ b/tests/unit/opflow/constraint_jacobian/inequality/jac_ineq_acopf.cpp @@ -0,0 +1,167 @@ +#include +#include +#include + +#include +#include +#include + +#include "opflow_tests.h" +#include "test_acopf_utils.h" + +/** + * @brief Unit test driver for objective function + * @see opflow/OpflowTests.hpp for kernel tested by this driver + * + * You can pass two options to the objectiveAcopf executatable through the + * command line (implemented using PETSc options): + * + * ~ -netfile : Specifies the input data file to test against. + * Default value is `//datafiles/case9/case9mod.m`. See directory + * datafiles for other potential inputs. + * + * ~ -num_copies : Specifies the number of replications of the + * network given through `-netfile`. If this is not set properly, test may fail + * + */ +int main(int argc, char **argv) { + PetscErrorCode ierr; + PetscBool flg; + Vec X; + int fail = 0; + double obj_value; + char file_c_str[PETSC_MAX_PATH_LEN]; + char validation_c_str[PETSC_MAX_PATH_LEN]; + std::string file; + char appname[] = "opflow"; + MPI_Comm comm = MPI_COMM_WORLD; + int num_copies = 0; + + char help[] = + "Unit tests for inequality constraint Jacobians running opflow\n"; + + /** Use `ExaGOLogSetLoggingFileName("opflow-logfile");` to log the output. */ + ierr = ExaGOInitialize(comm, &argc, &argv, appname, help); + if (ierr) { + fprintf(stderr, "Could not initialize ExaGO application %s.\n", appname); + return ierr; + } + + /* Get network data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-netfile", file_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + + /* Get num_copies from command line */ + ierr = PetscOptionsGetInt(NULL, NULL, "-num_copies", &num_copies, &flg); + CHKERRQ(ierr); + + if (!flg) { + file = "../datafiles/case9/case9mod.m"; + } else { + file.assign(file_c_str); + } + + // Set obj_value as reference solution, and run as usual + /* Get validation data file from command line */ + ierr = PetscOptionsGetString(NULL, NULL, "-validation", validation_c_str, + PETSC_MAX_PATH_LEN, &flg); + CHKERRQ(ierr); + readFromFile(&obj_value, validation_c_str); + + obj_value = obj_value * num_copies; + + OPFLOW opflowtest; + exago::tests::TestOpflow test; + + /* Set up test opflow */ + ierr = OPFLOWCreate(PETSC_COMM_WORLD, &opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWReadMatPowerData(opflowtest, file.c_str()); + CHKERRQ(ierr); + ierr = OPFLOWSetInitializationType(opflowtest, OPFLOWINIT_FROMFILE); + CHKERRQ(ierr); + ierr = OPFLOWSetUp(opflowtest); + CHKERRQ(ierr); + ierr = OPFLOWGetSolution(opflowtest, &X); + CHKERRQ(ierr); + + // If we are using HIOP, need to convert X + // The string lengths must be 65 + std::string modelname; + std::string solvername; + ierr = OPFLOWGetModel(opflowtest, &modelname); + ierr = OPFLOWGetSolver(opflowtest, &solvername); + + if (solvername == "HIOP") { +#if defined(EXAGO_ENABLE_HIOP) + double *x_ref; + ierr = VecGetArray(X, &x_ref); + + int nx, nconeq, nconineq; + ierr = OPFLOWGetSizes(opflowtest, &nx, &nconeq, &nconineq); + CHKERRQ(ierr); + + // If we are running using the CPU model, nothing needs to be done + if (modelname == "POWER_BALANCE_HIOP") { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref, obj_value); + } else // Using model PBPOLRAJAHIOP + { +#if defined(EXAGO_ENABLE_RAJA) + // Get resource manager instance + auto &resmgr = umpire::ResourceManager::getInstance(); + + // Get Allocator + umpire::Allocator h_allocator = resmgr.getAllocator("HOST"); + + // Register array xref with umpire + umpire::util::AllocationRecord record_x{ + x_ref, sizeof(double) * nx, h_allocator.getAllocationStrategy()}; + resmgr.registerAllocation(x_ref, record_x); + // Allocate and copy xref to device + double *x_ref_dev; + +#ifdef EXAGO_ENABLE_GPU + + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "GPU"); + CHKERRQ(ierr); + + umpire::Allocator d_allocator = resmgr.getAllocator("DEVICE"); + x_ref_dev = + static_cast(d_allocator.allocate(nx * sizeof(double))); +#else + ierr = OPFLOWSetHIOPComputeMode(opflowtest, "CPU"); + CHKERRQ(ierr); + x_ref_dev = x_ref; +#endif + resmgr.copy(x_ref_dev, x_ref); + + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, x_ref_dev, obj_value); + +#ifdef EXAGO_ENABLE_GPU + d_allocator.deallocate(x_ref_dev); +#endif +#endif + } + + ierr = VecRestoreArray(X, &x_ref); + CHKERRQ(ierr); + + ierr = PetscFree(x_ref); + CHKERRQ(ierr); +#endif // End #ifdefined(EXAGO_ENABLE_HIOP) + } else { + // TODO: Replace with inequality Jacobian test once implemented + // fail += test.computeObjective(opflowtest, X, obj_value); + } + ierr = OPFLOWDestroy(&opflowtest); + CHKERRQ(ierr); + + // Temporarily skip the test + fail = exago::tests::SKIP_TEST; + + ExaGOFinalize(); + return fail; +} diff --git a/tests/unit/opflow/objective/CMakeLists.txt b/tests/unit/opflow/objective/CMakeLists.txt index 0b89bff6..07b52079 100644 --- a/tests/unit/opflow/objective/CMakeLists.txt +++ b/tests/unit/opflow/objective/CMakeLists.txt @@ -11,7 +11,7 @@ target_include_directories(objective_acopf PRIVATE ../) # Network files to run on - doing 3 and 600 bus examples. set(prefix ${CMAKE_SOURCE_DIR}/datafiles/unit/opflow/objective/) -set(obj_network_files OF_unittestx3.m OF_unittestx600.m) +set(obj_network_files testx3.m testx600.m) # Map num_copies to a specific netfile set(num_copies 3 600) @@ -40,7 +40,7 @@ if(EXAGO_RUN_TESTS) # Iterate over networks, matching network file to num_copies foreach(network num IN ZIP_LISTS obj_network_files num_copies) get_filename_component(net ${network} NAME) - set(testname "UNIT_TESTS_OBJECTIVE_SIZE_${net}_${solver}_${model}") + set(testname "UNIT_TESTS_OBJECTIVE_${net}_${solver}_${model}") exago_add_test( NAME ${testname} diff --git a/tests/unit/utils/test_base.h b/tests/unit/utils/test_base.h index f03dc5bf..0e2d018c 100644 --- a/tests/unit/utils/test_base.h +++ b/tests/unit/utils/test_base.h @@ -35,7 +35,7 @@ static const RealType three = 3.0; // static const RealType eps = 10*std::numeric_limits::epsilon(); static const RealType eps = 1e-8; -static const LocalOrdinalType SKIP_TEST = -1; +static const LocalOrdinalType SKIP_TEST = 2; /** @brief Base class for all testing classes. Each child class will call the