diff --git a/solver_klu/source/KLU_DLL/CMakeLists.txt b/solver_klu/source/KLU_DLL/CMakeLists.txt new file mode 100644 index 0000000..ceb3f15 --- /dev/null +++ b/solver_klu/source/KLU_DLL/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.6) +project(solver_KLU) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +find_package(KLU REQUIRED) + +add_library(${PROJECT_NAME} SHARED + KLU_DLL.h + KLU_DLL.cpp + ) + +if (WIN32) + set(KLU_LIB_PREFIX "") +else () + set(KLU_LIB_PREFIX "lib_") +endif () +set_target_properties(${PROJECT_NAME} + PROPERTIES PREFIX "${KLU_LIB_PREFIX}" + ) + +target_include_directories(${PROJECT_NAME} PRIVATE ${KLU_INCLUDES}) +target_link_libraries(${PROJECT_NAME} PRIVATE ${KLU_LIBRARIES}) + +set(FILE_PERMISSIONS PERMISSIONS + OWNER_EXECUTE OWNER_READ OWNER_WRITE + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ) + +install(TARGETS ${PROJECT_NAME} + ${FILE_PERMISSIONS} + RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/gridlabd + LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/gridlabd + ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/gridlabd + COMPONENT library) diff --git a/solver_klu/source/KLU_DLL/KLU_DLL.h b/solver_klu/source/KLU_DLL/KLU_DLL.h index 819f393..0c5005e 100644 --- a/solver_klu/source/KLU_DLL/KLU_DLL.h +++ b/solver_klu/source/KLU_DLL/KLU_DLL.h @@ -1,5 +1,11 @@ // KLU_DLL.h +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + typedef struct { double *a_LU; double *rhs_LU; @@ -15,14 +21,14 @@ typedef struct { } KLU_STRUCT; //Initialization function -extern "C" __declspec(dllexport) void *LU_init(void *ext_array); +extern "C" EXPORT void *LU_init(void *ext_array); // Allocation function -extern "C" __declspec(dllexport) void LU_alloc(void *ext_array, unsigned int rowcount, unsigned int colcount, bool admittance_change); +extern "C" EXPORT void LU_alloc(void *ext_array, unsigned int rowcount, unsigned int colcount, bool admittance_change); // Solver function -extern "C" __declspec(dllexport) int LU_solve(void *ext_array, NR_SOLVER_VARS *system_info_vars, unsigned int rowcount, unsigned int colcount); +extern "C" EXPORT int LU_solve(void *ext_array, NR_SOLVER_VARS *system_info_vars, unsigned int rowcount, unsigned int colcount); // Destructive function -extern "C" __declspec(dllexport) void LU_destroy(void *ext_array, bool new_iteration); +extern "C" EXPORT void LU_destroy(void *ext_array, bool new_iteration); diff --git a/solver_klu/source/KLU_DLL/README.md b/solver_klu/source/KLU_DLL/README.md new file mode 100644 index 0000000..fb05778 --- /dev/null +++ b/solver_klu/source/KLU_DLL/README.md @@ -0,0 +1,64 @@ +# GridLAB-D KLU External Powerflow Solver + +## Dependencies +### Installing KLU +The KLU External Solver requires an installation of KLU, now included in +the SuiteSparse Library package. + +SuiteSparse is available in Ubuntu as `libsuitesparse-dev` and MinGW/MSYS2 as +`mingw-w64-x86_64-suitesparse` + +#### Ubuntu installation +to install SuiteSparse on Ubuntu run the following command: +`sudo apt install libsuitesparse-dev` + +#### MSYS2 installation +to install SuiteSparse on MSYS2 run the following command: +`pacman -S mingw-w64-x86_64-suitesparse` + +### Other Dependencies +The build process for the KLU External Solver additionally requires the +following: +1. CMake (v3.6 or later) +2. Build tools and compilers used for GridLAB-D + + +## Building KLU External Solver +1. Open KLU_DLL directory in terminal +2. Create build directory + * e.g., `mkdir build` +3. Move into directory + * e.g., `cd build` +3. Invoke CMake, and set installation directory to GridLAB-D install prefix + * e.g., `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local/gridlabd ../` + * **note**: it is recommended for Windows builds to include `-G"CodeBlocks - Unix Makefiles"` in the `cmake` command, as MSVC compiler support is not guaranteed +4. Build and install the library + * e.g., `cmake --build . --target install` + * **note**: `sudo` may be required depending on installation target + +The KLU External Solver will be compiled and installed in your GridLAB-D +install directory. + +If you are unable to directly install, step 4 can be replaced with +`cmake --build .` and the produced `solver_KLU.dll` or `lib_solver_KLU.so` +manually moved to GridLAB-D's install directory and placed in +`/lib/gridlabd` + +## GLM Formatting +To activate the library linkage, it is required to add the `lu_solver` +tag in powerflow module section of your .GLM file, +to indicate the external solver should be used. + +Example powerflow module invocation: +``` cpp +module powerflow { + lu_solver "KLU"; + solver_method NR; +} +``` + +## More Information +More extensive details related to the External LU Solver Interface can be found on the +[Powerflow External LU Solver Interface](http://gridlab-d.shoutwiki.com/wiki/Powerflow_External_LU_Solver_Interface) +page of the GridLAB-D Wiki. + diff --git a/solver_klu/source/KLU_DLL/cmake/FindKLU.cmake b/solver_klu/source/KLU_DLL/cmake/FindKLU.cmake new file mode 100644 index 0000000..b77a1e2 --- /dev/null +++ b/solver_klu/source/KLU_DLL/cmake/FindKLU.cmake @@ -0,0 +1,51 @@ +# This finder is a modified version of https://gitlab.com/libeigen/eigen/blob/master/cmake/FindKLU.cmake +# All rights and ownership belong to the author + +# KLU lib usually requires linking to a blas library. +# It is up to the user of this module to find a BLAS and link to it. + +if (KLU_INCLUDES AND KLU_LIBRARIES) + set(KLU_FIND_QUIETLY TRUE) +endif () + +find_path(KLU_INCLUDES + NAMES + klu.h + PATHS + $ENV{KLUDIR} + ${INCLUDE_INSTALL_DIR} + PATH_SUFFIXES + suitesparse + ufsparse + ) + +find_library(KLU_LIBRARIES klu PATHS $ENV{KLUDIR} ${LIB_INSTALL_DIR}) + +if (KLU_LIBRARIES) + + if (NOT KLU_LIBDIR) + get_filename_component(KLU_LIBDIR ${KLU_LIBRARIES} PATH) + endif () + + find_library(COLAMD_LIBRARY colamd PATHS ${KLU_LIBDIR} $ENV{KLUDIR} ${LIB_INSTALL_DIR}) + if (COLAMD_LIBRARY) + set(KLU_LIBRARIES ${KLU_LIBRARIES} ${COLAMD_LIBRARY}) + endif () + + find_library(AMD_LIBRARY amd PATHS ${KLU_LIBDIR} $ENV{KLUDIR} ${LIB_INSTALL_DIR}) + if (AMD_LIBRARY) + set(KLU_LIBRARIES ${KLU_LIBRARIES} ${AMD_LIBRARY}) + endif () + + find_library(BTF_LIBRARY btf PATHS $ENV{KLU_LIBDIR} $ENV{KLUDIR} ${LIB_INSTALL_DIR}) + if (BTF_LIBRARY) + set(KLU_LIBRARIES ${KLU_LIBRARIES} ${BTF_LIBRARY}) + endif () + +endif () + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(KLU DEFAULT_MSG + KLU_INCLUDES KLU_LIBRARIES) + +mark_as_advanced(KLU_INCLUDES KLU_LIBRARIES AMD_LIBRARY COLAMD_LIBRARY BTF_LIBRARY)