Skip to content

Commit

Permalink
Merge pull request #20 from jchristopherson/sparse
Browse files Browse the repository at this point in the history
Add Sparse Matrix Support
  • Loading branch information
jchristopherson committed Feb 28, 2024
2 parents 72c60fc + de7eafa commit 500d73f
Show file tree
Hide file tree
Showing 475 changed files with 71,987 additions and 3,999 deletions.
57 changes: 28 additions & 29 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,39 @@ env:
BUILD_TYPE: Release

jobs:
build:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
fortran_compiler: [gfortran, ifort]
os: [ubuntu-latest, macos-latest] # issue with windows-latest & CMake with CMake not recognizing defined compilers
os: [ubuntu-latest, macos-latest]
toolchain:
- {compiler: gcc, version: 11}
- {compiler: intel-classic, version: '2021.9'}
include:
- os: ubuntu-latest
toolchain: {compiler: intel, version: '2023.2'}

steps:

- name: Setup IFORT
if: contains( matrix.fortran_compiler, 'ifort' )
uses: modflowpy/install-intelfortran-action@v1

- name: Setup GFORTRAN
if: contains( matrix.fortran_compiler, 'gfortran')
uses: awvwgk/setup-fortran@main
id: setup-fortran
with:
compiler: gcc
version: 12

env:
FC: ${{ steps.setup-fortran.outputs.fc }}
CC: ${{ steps.setup-fortran.outputs.cc }}

- uses: actions/checkout@v3

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=${{ env.CC }} -DCMAKE_Fortran_COMPILER=${{ env.FC }} -DBUILD_TESTING=TRUE -DBUILD_C_API=TRUE
- uses: awvwgk/setup-fortran@v1
id: setup-fortran
with:
compiler: ${{ matrix.toolchain.compiler }}
version: ${{ matrix.toolchain.version }}

- run: ${{ env.FC }} --version
env:
FC: ${{ steps.setup-fortran.outputs.fc }}
CC: ${{ steps.setup-fortran.outputs.cc }}

- uses: actions/checkout@v3

- name: Build with CMake
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_Fortran_COMPILER=${{ env.FC }} -DBUILD_TESTING=TRUE

- name: Build with CMake
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test with CMake
working-directory: ${{github.workspace}}/build
run: ctest -C ${{env.BUILD_TYPE}}
- name: Test with CMake
working-directory: ${{github.workspace}}/build
run: ctest -C ${{env.BUILD_TYPE}}
5 changes: 1 addition & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.24)
project(
linalg
LANGUAGES Fortran C
VERSION 1.7.4
VERSION 1.8.0
)

# Get helper macros and functions
Expand Down Expand Up @@ -37,9 +37,6 @@ target_link_libraries(
)
link_library(${PROJECT_NAME} ${ferror_LIBRARY} ${ferror_INCLUDE_DIR})

# Installation
add_subdirectory(install)

# Testing
option(BUILD_TESTING "Build tests")
include(CTest)
Expand Down
91 changes: 76 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,23 @@ A linear algebra library that provides a user-friendly interface to several BLAS
![Build Status](https://github.com/jchristopherson/linalg/actions/workflows/cmake.yml/badge.svg)
[![Actions Status](https://github.com/jchristopherson/linalg/workflows/fpm/badge.svg)](https://github.com/jchristopherson/linalg/actions)

## Example 1
## Documentation
The documentation can be found [here](https://jchristopherson.github.io/linalg/).

## Building LINALG
[CMake](https://cmake.org/)This library can be built using CMake. For instructions see [Running CMake](https://cmake.org/runningcmake/).

[FPM](https://github.com/fortran-lang/fpm) can also be used to build this library using the provided fpm.toml.
```txt
fpm build
```
The LINALG library can be used within your FPM project by adding the following to your fpm.toml file.
```toml
[dependencies]
linalg = { git = "https://github.com/jchristopherson/linalg" }
```

## Standard Solution Example
This example solves a normally defined system of 3 equations of 3 unknowns.

```fortran
Expand Down Expand Up @@ -56,8 +72,8 @@ LU Solution: X =
0.0000
```

## Example 2
This example solves an overdefined system of 3 equations of 2 uknowns.
## Overdetermined System Example
This example solves an overdetermined system of 3 equations of 2 uknowns.

```fortran
program example
Expand Down Expand Up @@ -100,7 +116,7 @@ Least Squares Solution: X =
-0.57895
```

## Example 3
## Eigen Analysis Example
This example computes the eigenvalues and eigenvectors of a mechanical system consisting of several masses connected by springs.

```fortran
Expand Down Expand Up @@ -180,20 +196,64 @@ Mode 3: (923.5669 Hz)
-0.184
0.179
```
## Documentation
The documentation can be found [here](https://jchristopherson.github.io/linalg/).

## Building LINALG
[CMake](https://cmake.org/)This library can be built using CMake. For instructions see [Running CMake](https://cmake.org/runningcmake/).
## Sparse Matrix Example
The following example solves a sparse system of equations using a direct solver. The solution is compared to the solution of the same system of equations but in dense format for comparison.
```fortran
program example
use iso_fortran_env
use linalg
implicit none
[FPM](https://github.com/fortran-lang/fpm) can also be used to build this library using the provided fpm.toml.
```txt
fpm build
! Local Variables
integer(int32) :: ipiv(4)
real(real64) :: dense(4, 4), b(4), x(4), bc(4)
type(csr_matrix) :: sparse
! Build the matrices as dense matrices
dense = reshape([ &
5.0d0, 0.0d0, 0.0d0, 0.0d0, &
0.0d0, 8.0d0, 0.0d0, 6.0d0, &
0.0d0, 0.0d0, 3.0d0, 0.0d0, &
0.0d0, 0.0d0, 0.0d0, 5.0d0], [4, 4])
b = [2.0d0, -1.5d0, 8.0d0, 1.0d0]
! Convert to sparse (CSR format)
! Note, the assignment operator is overloaded to allow conversion.
sparse = dense
! Compute the solution to the sparse equations
call sparse_direct_solve(sparse, b, x) ! Results stored in x
! Print the solution
print "(A)", "Sparse Solution:"
print *, x
! Perform a sanity check on the solution
! Note, matmul is overloaded to allow multiplication with sparse matrices
bc = matmul(sparse, x)
print "(A)", "Computed RHS:"
print *, bc
print "(A)", "Original RHS:"
print *, b
! For comparison, solve the dense system via LU decomposition
call lu_factor(dense, ipiv)
call solve_lu(dense, ipiv, b) ! Results stored in b
print "(A)", "Dense Solution:"
print *, b
end program
```
The LINALG library can be used within your FPM project by adding the following to your fpm.toml file.
```toml
[dependencies]
linalg = { git = "https://github.com/jchristopherson/linalg" }
The above program produces the following output.
```text
Sparse Solution:
0.40000000000000002 -0.18750000000000000 2.6666666666666665 0.42500000000000004
Computed RHS:
2.0000000000000000 -1.5000000000000000 8.0000000000000000 1.0000000000000000
Original RHS:
2.0000000000000000 -1.5000000000000000 8.0000000000000000 1.0000000000000000
Dense Solution:
0.40000000000000002 -0.18750000000000000 2.6666666666666665 0.42499999999999999
```

## External Libraries
Expand All @@ -202,5 +262,6 @@ Here is a list of external code libraries utilized by this library.
- [LAPACK](http://www.netlib.org/lapack/)
- [QRUpdate](https://sourceforge.net/projects/qrupdate/)
- [FERROR](https://github.com/jchristopherson/ferror)
- [SPARSKIT](https://www-users.cse.umn.edu/~saad/software/SPARSKIT/)

The dependencies do not necessarily have to be installed to be used. The build will initially look for installed items, but if not found, will then download and build the latest version as part of the build process.
18 changes: 1 addition & 17 deletions dependencies/ferror/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
# Get the macros and functions we'll need
include("${PROJECT_SOURCE_DIR}/cmake/helper.cmake")
include(FetchContent)

# Fetch the proper content
FetchContent_Declare(
ferror
GIT_REPOSITORY "https://github.com/jchristopherson/ferror"
)

FetchContent_MakeAvailable(ferror)

if (WIN32)
if (BUILD_SHARED_LIBS)
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:ferror>
$<TARGET_FILE_DIR:${PROJECT_NAME}
)
endif()
endif()

set(ferror_INCLUDE_DIR ${ferror_BINARY_DIR}/include)
set(ferror_INCLUDE_DIR ${ferror_INCLUDE_DIR} PARENT_SCOPE)
configure_file(
"${ferror_SOURCE_DIR}/include/ferror.h"
"${ferror_INCLUDE_DIR}/ferror.h"
COPYONLY
)

# Make a parent-scope variable for the library
set(ferror_LIBRARY ferror)
set(ferror_INCLUDE_DIR ${ferror_INCLUDE_DIR} PARENT_SCOPE)
set(ferror_LIBRARY ${ferror_LIBRARY} PARENT_SCOPE)
2 changes: 1 addition & 1 deletion docs/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = linalg
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 1.7.4
PROJECT_NUMBER = 1.8.0

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
Loading

0 comments on commit 500d73f

Please sign in to comment.