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: .. code:: shell $ 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 .. code:: shell $ make install To change the install location please use the CMakePresets.json file as mentioned in `test and deploy <#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 .. code:: cmake 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-use-the-resolve-library-in-your-own-project>`__ To test your own install of Re::Solve simply cd into your Re::Solve build directory and run .. code:: shell $ make test or .. code:: shell $ ctest Below is an example of what a functional Re::Solve build will ouput on Passing tests .. code:: text 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. .. code:: shell cmake -B build --preset cluster Getting Help ------------ For any questions or to report a bug please submit a `GitHub issue `__. .. |runResolve| replace:: ``runResolve`` .. _runResolve: https://github.com/ORNL/ReSolve/blob/develop/runResolve 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 using ``refactorize()``). * ``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::MatrixHandler`` or ``ReSolve::VectorHandler`` classes. * 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 a ``ReSolve::MatrixHandler`` or ``ReSolve::VectorHandler`` object 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.