From 362ef96e10601dceac845d508670f3ed8e55fa49 Mon Sep 17 00:00:00 2001 From: pelesh Date: Tue, 28 Apr 2026 11:30:27 -0400 Subject: [PATCH 1/2] Add INSTALL.md file. --- CMakeLists.txt | 2 +- INSTALL.md | 358 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 37 +++-- 3 files changed, 384 insertions(+), 13 deletions(-) create mode 100644 INSTALL.md diff --git a/CMakeLists.txt b/CMakeLists.txt index df51b9220..83201d58e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ set(GRIDKIT_THIRD_PARTY_DIR ${PROJECT_SOURCE_DIR}/third-party) option(GridKit_ENABLE_IPOPT "Enable Ipopt support" OFF) # SUNDIALS support is disabled by default -option(GridKit_ENABLE_SUNDIALS "Enable SUNDIALS support" ON) +option(GridKit_ENABLE_SUNDIALS "Enable SUNDIALS support" OFF) # Enzyme support is disabled by default option(GridKit_ENABLE_ENZYME "Enable automatic differentiation with Enzyme" OFF) diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 000000000..8af4fc379 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,358 @@ +# GridKit Installation Guide + +GridKit has been built and tested on Linux and macOS. Windows users are +encouraged to use [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install), +which provides a Linux environment on Windows and is the easiest path to +a working GridKit build on that platform. Native Windows builds (Cygwin or +MSVC toolchain) are possible but not regularly tested. + +## Contents + +- [Requirements](#requirements) +- [Getting the source](#getting-the-source) +- [Building GridKit](#building-gridkit) +- [CMake options](#cmake-options) +- [Installing dependencies](#installing-dependencies) + - [SUNDIALS](#sundials) + - [Ipopt and HSL](#ipopt-and-hsl) + - [Enzyme](#enzyme) +- [Using GridKit](#using-gridkit) +- [Building with Spack](#building-with-spack) + +--- + +## Requirements + +| Requirement | Version | Notes | +|---|---|---| +| CMake | >= 3.13 | | +| C++ compiler | C++20 | Clang or GCC | +| SUNDIALS | >= 7.4.0 | Optional; disabled by default | +| SuiteSparse (KLU) | >= 7.x | Optional; needed for sparse solvers in SUNDIALS | +| Ipopt | >= 3.14 | Optional; disabled by default | +| HSL | >= 2015 | Optional; required by Ipopt for efficient linear solvers | +| gfortran | F90 | Optional; required when building with Ipopt/HSL | +| Enzyme | >= 0.0.206 | Optional; disabled by default; experimental | +| LLVM | >= 15 (tested with 16) | Optional; required when building with Enzyme | +| Doxygen | any | Optional; needed to build API documentation | + +--- + +## Getting the source + +```sh +git clone git@github.com:ORNL/GridKit.git +cd GridKit +git submodule update --init third-party/ +``` + +The second step initializes bundled third-party headers (`magic-enum`, +`nlohmann-json`). Re-run it after pulling updates that change submodule +revisions. + +--- + +## Building GridKit + +The build directory must be outside the GridKit source tree. A sibling +directory is a common convention: + +```sh +mkdir GridKit-build && cd GridKit-build +cmake ../GridKit \ + -DCMAKE_INSTALL_PREFIX=/path/to/install +cmake --build . -j$(nproc) +cmake --install . +``` + +If dependencies are not in standard locations, point CMake to them: + +```sh +cmake ../GridKit \ + -DSUNDIALS_DIR=/path/to/sundials/install \ + -DIPOPT_DIR=/path/to/ipopt/install \ + -DCMAKE_INSTALL_PREFIX=/path/to/install \ + -DGridKit_ENABLE_SUNDIALS=ON \ + -DGridKit_ENABLE_IPOPT=ON +``` + +### Running tests + +```sh +cd build +ctest --output-on-failure +``` + +### Testing the installation + +After installing, you can verify that the installed CMake configuration is +correct and that GridKit can be consumed as a dependency by an external +project: + +```sh +cd build +make test_install +``` + +`test_install` configures, builds, and runs a small consumer project located +in the GridKit install tree (`share/gridkit/examples/GridKitConsumer`). It +uses `find_package(GridKit)` against the installation prefix, so it exercises +the same code path a downstream user would follow. The build and test results +are placed under that consumer directory. + +This target must be run **after** `cmake --install` because it depends on the +installed headers, libraries, and CMake config files. + +--- + +## CMake options + +| Option | Default | Description | +|---|---|---| +| `GridKit_ENABLE_SUNDIALS` | `OFF` | Build with SUNDIALS DAE integrators | +| `GridKit_ENABLE_IPOPT` | `OFF` | Build with Ipopt optimization solver | +| `GridKit_ENABLE_ENZYME` | `OFF` | Build with Enzyme automatic differentiation | +| `GridKit_ENABLE_ASAN` | `OFF` | Enable address sanitizer | +| `GridKit_ENABLE_UBSAN` | `OFF` | Enable undefined behavior sanitizer | +| `BUILD_SHARED_LIBS` | `ON` | Build shared libraries | +| `CMAKE_INSTALL_PREFIX` | system default | Installation root | + +Options may also be spelled with the `GridKit_ENABLE_*` prefix. + +Dependency root directories: + +| Variable | Points to | +|---|---| +| `SUNDIALS_DIR` | SUNDIALS install prefix | +| `IPOPT_DIR` | Ipopt install prefix | +| `ENZYME_DIR` | Enzyme install prefix | +| `SUITESPARSE_DIR` | SuiteSparse install prefix | + +--- + +## Installing dependencies + +### SUNDIALS + +GridKit requires SUNDIALS 7.4.0 or newer. For sparse linear algebra support +(recommended), SUNDIALS must be built with KLU enabled, which requires +SuiteSparse. + +**Install SuiteSparse first** (via the system package manager, or from source): + +```sh +# Ubuntu/Debian +sudo apt install libsuitesparse-dev + +# macOS with Homebrew +brew install suite-sparse +``` + +**Build SUNDIALS with KLU:** + +```sh +cmake -B sundials-build -S sundials-src \ + -DCMAKE_INSTALL_PREFIX=/path/to/sundials/install \ + -DENABLE_KLU=ON \ + -DKLU_INCLUDE_DIR=/path/to/suitesparse/include \ + -DKLU_LIBRARY_DIR=/path/to/suitesparse/lib \ + -DENABLE_MPI=OFF +cmake --build sundials-build -j$(nproc) +cmake --install sundials-build +``` + +Without KLU, omit the `ENABLE_KLU` and `KLU_*` flags. + +--- + +### Ipopt and HSL + +Ipopt requires a Fortran compiler for the HSL linear solver library. The +HSL source must be obtained separately from the +[HSL website](https://licences.stfc.ac.uk/product/coin-hsl) (free for +academic use). + +Because HSL is Fortran library, it requires a feature complete Fortran +compiler. We were not able to build HSL with Flang, so to enable both, Ipopt +and Enzyme support, we used Clang as C/C++ and `gfortran` as Fortran compiler. +The compilers are set per-language via the `CC`, `CXX`, and `FC` environment +variables. + +**Step 1 — Build HSL via ThirdParty-HSL:** + +```sh +git clone https://github.com/coin-or-tools/ThirdParty-HSL.git +cd ThirdParty-HSL +# Place the HSL source tarball in the same directory where you plan to +# install Ipopt and follow the instructions in the ThirdParty-HSL README +# (get_HSL.sh or manual unpack). +./configure CC=clang FC=gfortran --prefix=/path/to/hsl/install +make -j$(nproc) +make install +``` + +**Step 2 — Build Ipopt:** + +```sh +git clone https://github.com/coin-or/Ipopt.git +cd Ipopt +./configure \ + CC=clang CXX=clang++ FC=gfortran \ + --prefix=/path/to/ipopt/install \ + --with-hsl-lflags="-L/path/to/hsl/install/lib -lcoinhsl" \ + --with-hsl-cflags="-I/path/to/hsl/install/include" +make -j$(nproc) +make install +``` + +Note: Ipopt's built-in tests will fail with mixed Clang/gfortran compilers. +This is because Ipopt build system does not add `-lgfortran` flag in that +configuration. Ignore these failed tests and cross your fingers. + +**Step 3 — Build GridKit with Ipopt:** + +```sh +cmake -B build -S . \ + -DGridKit_ENABLE_IPOPT=ON \ + -DIPOPT_DIR=/path/to/ipopt/install \ + -DSUNDIALS_DIR=/path/to/sundials/install \ + -DCMAKE_INSTALL_PREFIX=/path/to/gridkit/install +cmake --build build -j$(nproc) +cmake --install build +``` + +> **Note on the Fortran linker:** GridKit's CMakeLists sets +> `LINKER_LANGUAGE Fortran` for executables that use Ipopt+HSL. This +> causes `gfortran` to drive the final link step, which automatically adds +> the Fortran runtime libraries (`libgfortran`, `libquadmath`). No manual +> `-lgfortran` flags should be needed. + +--- + +### Enzyme + +Enzyme support is experimental. Only `Release` and `RelWithDebInfo` build +types are supported due to a known Enzyme limitation. + +Enzyme requires a matching LLVM installation (currently tested with LLVM 16) +and must be compiled with the same Clang used to build GridKit. + +For instructions how to acquire Enzyme and (optionally) LLVM check Enzyme +[installation instructions](https://enzyme.mit.edu/Installation/). + +After you installed Enzyme, you can build GridKit as + +```sh +# Build GridKit with Enzyme +CC=clang CXX=clang++ FC=gcc cmake -B build -S . \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DGridKit_ENABLE_ENZYME=ON \ + -DENZYME_DIR=/path/to/enzyme/install \ + -DSUNDIALS_DIR=/path/to/sundials/install +cmake --build build -j 4 +``` + +--- + +## Using GridKit + +GridKit installs CMake config files that allow downstream projects to find and +link against GridKit with `find_package`. The config file automatically +re-finds GridKit's own dependencies (e.g. SUNDIALS) so consuming projects do +not need to locate them manually. + +### Minimal CMakeLists.txt + +```cmake +cmake_minimum_required(VERSION 3.13) +project(MyApp LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) # GridKit public headers require C++20 +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(GridKit REQUIRED) + +add_executable(myapp myapp.cpp) +target_link_libraries(myapp GridKit::solvers_dyn GridKit::phasor_dynamics_components) +``` + +### Locating the GridKit installation + +If GridKit was not installed to a system-wide prefix, tell CMake where to +find it via `GridKit_DIR` or `CMAKE_PREFIX_PATH`: + +```sh +# Option A — point directly to the install prefix +cmake -B build -S . -DGridKit_DIR=/path/to/gridkit/install + +# Option B — add the prefix to the search path +cmake -B build -S . -DCMAKE_PREFIX_PATH=/path/to/gridkit/install +``` + +### Available CMake targets + +All targets are under the `GridKit::` namespace. + +| Target | Description | +|---|---| +| `GridKit::solvers_dyn` | DAE integrators (requires SUNDIALS) | +| `GridKit::solvers_opt` | Optimization solvers (requires Ipopt) | +| `GridKit::phasor_dynamics_components` | Phasor dynamics model components | +| `GridKit::phasor_dynamics_core` | Phasor dynamics core infrastructure | +| `GridKit::phasor_dynamics_signal` | Signal node models | +| `GridKit::DenseMatrix` | Dense matrix utilities | +| `GridKit::sparse_matrix` | Sparse matrix utilities | +| `GridKit::Utilities` | General-purpose utility types | +| `GridKit::definitions` | Compile-time definitions and configuration | + +Individual model component targets (generators, buses, loads, exciters, +governors, stabilizers) follow the pattern `GridKit::` and +are also available; refer to the GridKit headers under `GridKit/Model/` for +the full list. + +### C++20 requirement + +GridKit's public headers use C++20 features. Consuming projects must enable +C++20 or later: + +```cmake +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +``` + +--- + +## Building with Spack + +GridKit ships a Spack repository under `buildsystem/spack_repo` and includes +Spack as a submodule. This is the approach used for CI builds. + +```sh +# Initialize submodules (if not done already) +git submodule update --init buildsystem/spack + +# Set up Spack +source ./buildsystem/spack/share/spack/setup-env.sh + +# Create and activate an environment +spack env create gridkit +spack env activate -p gridkit + +# Register the GridKit Spack repo +spack repo add buildsystem/spack_repo/gridkit + +# Tell Spack to use the local source tree +spack develop --path=$(pwd) gridkit@develop + +# Detect available compilers +spack compiler find + +# Add GridKit with desired variants, then build +spack add gridkit+sundials+ipopt+klu +spack concretize -f +spack install +spack env deactivate +``` + +Available Spack variants: `sundials`, `ipopt`, `klu`, `enzyme`, `asan`, `ubsan`. +Note that `+klu` requires `+sundials`. diff --git a/README.md b/README.md index 69e0f2209..58a252f7b 100644 --- a/README.md +++ b/README.md @@ -37,25 +37,38 @@ Note, you may need to run the second step periodically as our third party depend ### Installing -GridKit™ uses CMake for build configuration. Per CMake best practices it is recommended -to build GridKit™ outside the source directory. Building GridKit™ can be as simple as executing +GridKit™ uses CMake for build configuration. The build directory must be +outside the source tree: ```bash -cmake source_dir -make -make install +mkdir build && cd build +cmake -DCMAKE_INSTALL_PREFIX=/path/to/install ../GridKit +cmake --build . +cmake --install . ``` -in the build directory. Dependencies should be autodetected if they are installed in -standard locations, otherwise you need to specify the location of the dependency -manually. For example: +Dependencies are autodetected if installed in standard locations, otherwise +specify their location explicitly. For example: ```bash -cmake -DSUNDIALS_DIR=/path/to/sundials/install source_dir +cmake -DSUNDIALS_DIR=/path/to/sundials/install ../GridKit ``` -You can also use `ccmake` or `cmake-gui` tools to adjust GridKit™ build configuration. +You can also use `ccmake` or `cmake-gui` to adjust the build configuration. + +See [INSTALL.md](INSTALL.md) for full instructions, including how to build +each optional dependency and all available CMake options. ### Testing -Several examples are built together with GridKit™ libraries. These are also used -as functionality test and executed by running `ctest` in the build directory. +Several examples are built together with GridKit™ libraries and serve as +functionality tests. Run them with `ctest` in the build directory: +```bash +ctest --output-on-failure +``` +To verify the installed CMake configuration works correctly for downstream +projects, run the installation test after `cmake --install`: +```bash +make test_install +``` +See [Testing the installation](INSTALL.md#testing-the-installation) in +[INSTALL.md](INSTALL.md) for details. ## Contributors From e761b9675cba8d4d0274fc98899310ead82449fa Mon Sep 17 00:00:00 2001 From: pelesh Date: Thu, 30 Apr 2026 17:48:58 -0400 Subject: [PATCH 2/2] [skip ci] Update INSTALL.md --- INSTALL.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 8af4fc379..5adc25996 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -231,8 +231,10 @@ cmake --install build ### Enzyme -Enzyme support is experimental. Only `Release` and `RelWithDebInfo` build -types are supported due to a known Enzyme limitation. +Enzyme support is experimental. There is a known bug in Enzyme +that causes errors when compiler optimization is turned off with +`-O0` flag. A workaround is to use `Release` or `RelWithDebInfo` +build types in CMake. Enzyme requires a matching LLVM installation (currently tested with LLVM 16) and must be compiled with the same Clang used to build GridKit.