User Guide¶
Getting started¶
Re::Solve is maintained and developed at Github. It has following build dependencies:
C++11 compliant compiler
CMake >= 3.22
KLU, AMD and COLAMD libraries from SuiteSparse >= 5.0 (optional)
CUDA >= 11.4 (optional)
HIP/ROCm >= 6.4 (optional)
To acquire and build Re::Solve it is as easy as:
$ git clone https://code.ornl.gov/peles/resolve.git
$ mkdir build && cd build
$ cmake ../resolve
$ make
Note if you don’t include any of the optional dependencies, there will be
little functionality provided. You might want to use tool such as ccmake
to enable features you need.
To install the library¶
In the directory where you built the library run
$ make install
To change the install location please use the CMakePresets.json file as mentioned in test and deploy
To run it, download test linear systems and then try some of Re::Solve’s examples. The examples will emulate nonlinear solver calling the linear solver repeatedly.
To use the Re::Solve library in your own project¶
Make sure Resolve library is installed (see above)
Below is an example CMakeList.txt file to use Re::Solve library in your project
cmake_minimum_required(VERSION 3.20)
project(my_app LANGUAGES CXX)
find_package(ReSolve CONFIG
PATHS ${ReSolve_DIR} ${ReSolve_DIR}/share/resolve/cmake
ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH
REQUIRED)
# Build your executable
add_executable(my_app my_app.cpp)
target_link_libraries(my_app PRIVATE ReSolve::ReSolve)
Test and Deploy¶
Re::Solve as a library is tested every pull request via GitHub pipelines that execute various library tests including a test of Re::Solve being consumed as package within an external project as mentioned in Using Re::Solve in your own Project
To test your own install of Re::Solve simply cd into your Re::Solve build directory and run
$ make test
or
$ ctest
Below is an example of what a functional Re::Solve build will ouput on Passing tests
Test project /people/dane678/resolve/build
Start 1: resolve_consume
1/9 Test #1: resolve_consume .................. Passed 16.51 sec
Start 2: klu_klu_test
2/9 Test #2: klu_klu_test ..................... Passed 1.04 sec
Start 3: klu_rf_test
3/9 Test #3: klu_rf_test ...................... Passed 1.04 sec
Start 4: klu_rf_fgmres_test
4/9 Test #4: klu_rf_fgmres_test ............... Passed 3.14 sec
Start 5: klu_glu_test
5/9 Test #5: klu_glu_test ..................... Passed 1.06 sec
Start 6: matrix_test
6/9 Test #6: matrix_test ...................... Passed 0.03 sec
Start 7: matrix_handler_test
7/9 Test #7: matrix_handler_test .............. Passed 0.97 sec
Start 8: vector_handler_test
8/9 Test #8: vector_handler_test .............. Passed 0.98 sec
Start 9: logger_test
9/9 Test #9: logger_test ...................... Passed 0.03 sec
Important Notes¶
You can find default Cmake Configurations in the CMakePresets.json file, which allows for easy switching between different CMake Configs. To create your own CMake Configuration we encourage you to utlize a CmakeUserPresets.json file. To learn more about cmake-presets please checkout the cmake docs.
For example if you wanted to build and install Re::Solve on a High Performance Computing Cluster such as ORNL’s Frontier we encourage you to utilize our cluster preset. Using this preset will set CMAKE_INSTALL_PREFIX to an install folder. To use this preset simply call the preset flag in the cmake build step.
cmake -B build --preset cluster
Getting Help¶
For any questions or to report a bug please submit a GitHub issue.
Re::Solve General API Description¶
Users are encouraged to look at the examples and tests for guidance on how to use the library. When there is any conflict between the examples/tests and this documentation, the examples/tests are correct.
Solver Subroutines¶
For direct solvers, the following functions are provided and must be called in this order:
analyze()- Performs symbolic factorization, currently only with KLU on the CPU.factorize()- Performs numeric factorization, given a symbolic factorization.refactorizationSetup()- Prepares for a new numeric factorization, given a new matrix with the same sparsity structure (required only if usingrefactorize()).solve()- Solves the linear system, given a numeric factorization.refactorize()- Reuses the symbolic factorization to perform a new numeric factorization, given a new matrix.
Subsequent systems only require calls to refactorize() and solve() if the sparsity structure hasn’t changed.
Note some examples do not reuse the factorization from the 0-th iteration because the numeric sparsity structure changes and that’s how the matrices are stored. In a practical application, the sparsity structure is likely to remain the same. If it does not, it is the user’s responsibility to reallocate memory and call analyze() and factorize() again. The user should enforce that symbolic nonzeros are stored explicitly, even if they are numerically zero.
Function Requirements¶
Functions must be used as in the examples and tests:
Workspaces are required for GPU solvers. The generic workspace_type is required for backend agnostic code.
Handles are created with the
initializeHandles()function and destroyed with the default destructor.Allocate memory first, preferably with the
ReSolve::MatrixHandlerorReSolve::VectorHandlerclasses.Memory must be allocated before attempting to copy to it.
Solver output variables must be allocated before passing to the solver.
Use setup functions to initialize objects, where available. Do not call them more than once.
Call the set or factor functions before the corresponding reset or refactor functions.
Deallocate memory at the end.
Functions in ReSolve that take pointers as arguments will have the following requirements:
Pointers must be valid and point to allocated memory, unless the function’s use is to allocate memory.
Pointers that are not marked as const must point to memory that is writable.
Pointers that are marked as const must point to memory that is readable.
Memory Synchronization¶
For CPU solvers, memory is always in sync.
For GPU solvers, the user must synchronize memory manually.
Manually call
setUpdated()if you modify the contents of aReSolve::MatrixHandlerorReSolve::VectorHandlerobject without using the object’s member functions.Manually call
syncData(memspace)when you modify the other memory space and want them to match. Both memory spaces must be allocated.