Skip to content

Commit

Permalink
Merge pull request #1 from SKopecz/hr/package
Browse files Browse the repository at this point in the history
create package infrastructure and CI tests
  • Loading branch information
SKopecz authored Oct 16, 2023
2 parents 80a9649 + ea55fea commit d695c4d
Show file tree
Hide file tree
Showing 20 changed files with 434 additions and 90 deletions.
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "monthly"
115 changes: 115 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: CI

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
test:
runs-on: ${{ matrix.os }}
name: ${{ matrix.os }} - Julia ${{ matrix.version }} - ${{ github.event_name }}
strategy:
fail-fast: false
matrix:
version:
- '1'
- '1.8'
os:
- ubuntu-latest
include:
- version: '1'
os: macOS-latest
- version: '1'
os: windows-latest
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@v1
env:
GKSwstype: "100" # for Plots/GR
- uses: julia-actions/julia-runtest@v1
env:
GKSwstype: "100" # for Plots/GR
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
with:
file: lcov.info
# The standard setup of Coveralls is just annoying for parallel builds, see, e.g.,
# https://github.com/trixi-framework/Trixi.jl/issues/691
# https://github.com/coverallsapp/github-action/issues/47
# https://github.com/coverallsapp/github-action/issues/67
# This standard setup is reproduced below for completeness.
# - uses: coverallsapp/github-action@master
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# flag-name: run-${{ matrix.version }}-${{ github.run_id }}
# parallel: true
# path-to-lcov: ./lcov.info
# Instead, we use a more tedious approach:
# - Store all individual coverage files as artifacts (directly below)
# - Download and merge individual coverage reports in another step
# - Upload only the merged coverage report to Coveralls
- shell: bash
run: |
cp ./lcov.info ./lcov-${{ matrix.version }}-${{ github.run_id }}.info
- uses: actions/upload-artifact@v3
with:
name: lcov-${{ matrix.version }}-${{ github.run_id }}
path: ./lcov-${{ matrix.version }}-${{ github.run_id }}.info

finish:
needs: test
runs-on: ubuntu-latest
steps:
# The standard setup of Coveralls is just annoying for parallel builds, see, e.g.,
# https://github.com/trixi-framework/Trixi.jl/issues/691
# https://github.com/coverallsapp/github-action/issues/47
# https://github.com/coverallsapp/github-action/issues/67
# This standard setup is reproduced below for completeness.
# - name: Coveralls Finished
# uses: coverallsapp/github-action@master
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# parallel-finished: true
# Instead, we use the more tedious approach described above.
# At first, we check out the repository and download all artifacts
# (and list files for debugging).
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
- run: ls -R
# Next, we merge the individual coverage files and upload
# the combined results to Coveralls.
- name: Merge lcov files using Coverage.jl
shell: julia --color=yes {0}
run: |
using Pkg
Pkg.activate(temp=true)
Pkg.add("Coverage")
using Coverage
coverage = LCOV.readfolder(".")
for cov in coverage
cov.filename = replace(cov.filename, "\\" => "/")
end
filter!(c -> basename(c.filename) != "precompile.jl", coverage)
coverage = merge_coverage_counts(coverage)
@show covered_lines, total_lines = get_summary(coverage)
LCOV.writefile("./lcov.info", coverage)
# TODO: Activate this when the package becomes public
# - uses: coverallsapp/github-action@master
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# path-to-lcov: ./lcov.info
# Upload merged coverage data as artifact for debugging
- uses: actions/upload-artifact@v3
with:
name: lcov
path: ./lcov.info
# That's it
- run: echo "Finished testing"
26 changes: 26 additions & 0 deletions .github/workflows/CompatHelper.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: CompatHelper

on:
schedule:
- cron: 0 0 * * *
issues:
types: [opened, reopened]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: [1]
julia-arch: [x86]
os: [ubuntu-latest]
steps:
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.julia-version }}
- name: Pkg.add("CompatHelper")
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs=["", "docs", "examples", "test"])'
32 changes: 32 additions & 0 deletions .github/workflows/DocPreviewCleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Doc Preview Cleanup

on:
pull_request:
types: [closed]

jobs:
doc-preview-cleanup:
# Do not run on forks to avoid authorization errors
# Source: https://github.community/t/have-github-action-only-run-on-master-repo-and-not-on-forks/140840/18
if: github.repository_owner == 'SKopecz'
runs-on: ubuntu-latest
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v4
with:
ref: gh-pages

- name: Delete preview and history
shell: bash
run: |
git config user.name "Documenter.jl"
git config user.email "[email protected]"
git rm -rf --ignore-unmatch "previews/PR$PRNUM"
git commit -m "delete preview" --allow-empty
git branch gh-pages-new $(echo "delete history" | git commit-tree HEAD^{tree})
env:
PRNUM: ${{ github.event.number }}

- name: Push changes
run: |
git push --force origin gh-pages-new:gh-pages
13 changes: 13 additions & 0 deletions .github/workflows/SpellCheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Spell Check

on: [pull_request, workflow_dispatch]

jobs:
typos-check:
name: Spell Check with Typos
runs-on: ubuntu-latest
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v4
- name: Check spelling
uses: crate-ci/[email protected]
15 changes: 15 additions & 0 deletions .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: TagBot
on:
issue_comment:
types:
- created
workflow_dispatch:
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Stefan Kopecz
Copyright (c) 2023--present Stefan Kopecz, Hendrik Ranocha, and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
26 changes: 22 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
name = "PositiveIntegrators"
uuid = "d1b20bf0-b083-4985-a874-dc5121669aa5"
authors = ["Stefan Kopecz, Hendrik Ranocha, and contributors"]
version = "0.1.0"

[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
DiffEqDevTools = "f3b72e0c-5b89-59e1-b016-84e28bfd966d"
FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898"
Kwonly = "18d08c8c-0732-55ee-a446-91a51d7b4206"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
SimpleUnPack = "ce78b400-467f-4804-87d8-8f486da07d0a"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[compat]
FastBroadcast = "0.2"
julia = "1.8"
Kwonly = "0.1"
LinearSolve = "2"
MuladdMacro = "0.2"
OrdinaryDiffEq = "6"
Reexport = "1"
SciMLBase = "2"
SimpleUnPack = "1"
5 changes: 5 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

[compat]
Documenter = "1"
57 changes: 33 additions & 24 deletions examples/01_example_proddest.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# A production-destruction sytem (PDS) has the form
# A production-destruction system (PDS) has the form
# uᵢ'(t) = ∑ⱼ(pᵢⱼ(t) - dᵢⱼ(t))
# with pᵢⱼ(t), dᵢⱼ ≥ 0.
# with pᵢⱼ(t), dᵢⱼ ≥ 0.
#
# Here, pᵢⱼ is a production term, i.e. a term with positive sign, in the ith equation with a corresponding
# destruction term, i.e. the same term with negative sign, in the jth equation. Positive terms of the ith equation
# Here, pᵢⱼ is a production term, i.e. a term with positive sign, in the ith equation with a corresponding
# destruction term, i.e. the same term with negative sign, in the jth equation. Positive terms of the ith equation
# without negative counterpart are gathered in pᵢᵢ. Similarly, dᵢᵢ contains the absolute values of the negative
# terms without positive counterparts.
#
Expand All @@ -13,19 +13,28 @@
# Similarly, p₁₂ = 2 u₂ = d₂₁. Furthermore, we have p₁₁ = 3 u₁, d₁₁ = 0 and p₂₂ = 0, d₂₂ = 4 u₂.
# Note that this representation is not unique!
#
# The PDS is conservative if dᵢⱼ == pⱼᵢ and pᵢᵢ == dᵢᵢ == 0. In this case only the matrix (pᵢⱼ) needs to be stored,
# because (dᵢⱼ) is the transpose of (pᵢⱼ). Furthermore, all diagonal elements of (pᵢⱼ) are zero.
# The PDS is conservative if dᵢⱼ == pⱼᵢ and pᵢᵢ == dᵢᵢ == 0. In this case only the matrix (pᵢⱼ) needs to be stored,
# because (dᵢⱼ) is the transpose of (pᵢⱼ). Furthermore, all diagonal elements of (pᵢⱼ) are zero.
# If the PDS is not conservative, we can store the additional production terms pᵢᵢ on the diagonal of (pᵢⱼ) and need to
# store an additional vector for dᵢᵢ.
#
# Modified Patankar-Runge-Kutta (MPRK) schemes are based on the production-destruction representation of an ODE.
#
# In OrdinaryDiffEq an ODE u' = f(t,u) with t in tspan and parameters p is represented as an ODEProblem(f,u,tspan,p). To
# respresent f as a PDS the new problem type ProdDestODEProblem(P,D,u,tspan,p) was added. Here P is the matrix (pᵢⱼ)
# In OrdinaryDiffEq an ODE u' = f(t,u) with t in tspan and parameters p is represented as an ODEProblem(f,u,tspan,p). To
# represent f as a PDS the new problem type ProdDestODEProblem(P,D,u,tspan,p) was added. Here P is the matrix (pᵢⱼ)
# from above, with possibly nonzero diagonal elements. D is the vector to store dᵢᵢ.

# Install packages
import Pkg
Pkg.activate(@__DIR__)
Pkg.develop(path = dirname(@__DIR__))
Pkg.instantiate()

# load new problem type for production-destruction systems
include("../src/proddest.jl")
using PositiveIntegrators

using OrdinaryDiffEq
using SparseArrays

### Example 1: Linear model problem ######################################################################################
# This is an example of a conservative PDS
Expand All @@ -35,12 +44,12 @@ include("../src/proddest.jl")
# Standard: f(t,u) = [-5 1; 5 -1]*u
#
# PDS: P = [0 u₂; 5 u₁ 0], D = [0; 0]
#
# We implent four variantions (in-place and out-of-place for both standard and PDS) of this ODE system and check that we
# obtain equivalent solutions with a standard solver of OrdinaryDiffEq.jl.
#
# We implement four variations (in-place and out-of-place for both standard and PDS) of this ODE system and check that we
# obtain equivalent solutions with a standard solver of OrdinaryDiffEq.jl.


# inital values
# initial values
u0 = [0.9, 0.1]
# time domain
tspan = (0.0, 2.0)
Expand Down Expand Up @@ -87,7 +96,7 @@ sol_linmod_PDS_ip = solve(linmod_PDS_ip,Tsit5())
@assert sol_linmod_f_op.u sol_linmod_f_ip.u sol_linmod_PDS_op.u sol_linmod_PDS_ip.u

# check that we really do not use too many additional allocations for in-place implementations
alloc1 = @allocated(solve(linmod_f_ip, Tsit5()))
alloc1 = @allocated(solve(linmod_f_ip, Tsit5()))
alloc2 = @allocated(solve(linmod_PDS_ip, Tsit5()))
@assert 0.95 < alloc1/alloc2 < 1.05

Expand All @@ -100,11 +109,11 @@ alloc2 = @allocated(solve(linmod_PDS_ip, Tsit5()))
# Standard: f(t,u) = [u₁ - u₁ u₂; u₁ u₂ - u₂]
#
# PDS: P = [u₁ 0; u₁ u₂ 0], D = [0; u₂]
#
# We implent four variantions (in-place and out-of-place for both standard and PDS) of this ODE system and check that we
# obtain equivalent solutions with a standard solver of OrdinaryDiffEq.jl.
#
# We implement four variations (in-place and out-of-place for both standard and PDS) of this ODE system and check that we
# obtain equivalent solutions with a standard solver of OrdinaryDiffEq.jl.

# inital values
# initial values
u0 = [0.9, 0.1]
# time domain
tspan = (0.0, 20.0)
Expand Down Expand Up @@ -151,20 +160,20 @@ sol_lotvol_PDS_ip = solve(lotvol_PDS_ip,Tsit5())
@assert sol_lotvol_f_op.u sol_lotvol_f_ip.u sol_lotvol_PDS_op.u sol_lotvol_PDS_ip.u

# check that we really do not use too many additional allocations for in-place implementations
alloc1 = @allocated(solve(lotvol_f_ip, Tsit5()))
alloc1 = @allocated(solve(lotvol_f_ip, Tsit5()))
alloc2 = @allocated(solve(lotvol_PDS_ip, Tsit5()))
@assert 0.95 < alloc1/alloc2 < 1.05

##########################################################################################################################
### Example 3: Linear advection discretized with finite differences and upwind, periodic boundary conditions #############
# This is an example of a large conservative PDS, which requires the use of sparese matrices.
#
# We implent the in-place versions for the standard rhs and the PDS representation of this ODE system. In addition, we
# compare the efficiency of dense and sparse matrices for the PDS version.
# This is an example of a large conservative PDS, which requires the use of sparese matrices.
#
# We implement the in-place versions for the standard rhs and the PDS representation of this ODE system. In addition, we
# compare the efficiency of dense and sparse matrices for the PDS version.

# number of nodes
N = 1000;
# inital data
# initial data
u0 = sin.(π*LinRange(0.0,1.0,N+1))[2:end]
# time domain
tspan = (0.0, 1.0)
Expand Down
Loading

0 comments on commit d695c4d

Please sign in to comment.