text:
using Devectorize
include("helper_functions.jl")

function fprop(input_batch,
              word_embedding_weights,
              embed_to_hid_weights,
              hid_to_output_weights,
              hid_bias,
              output_bias)
#=
To forward propagate through the neural network.
---
Inputs:
  input_batch :
  The input data as a matrix of size numwords X batchsize where,
  numwords is the number of words, batchsize is the number of data points.
  So, if input_batch(i, j) = k then the ith word in data point j is word
  index k of the vocabulary.
=#

# Compute the state of the word embedding layer
# Here simply look up the word_embedding_weights and choose the corresponding weights
numwords, batchsize = size(input_batch)
vocab_size, numofhid1units = size(word_embedding_weights)
numofhid2units = size(embed_to_hid_weights, 2)

# Compute the stae of the WORD EMBEDDING LAYER
# Simple look up in inputs word indices in the word_embedding_weights matrix.
embedding_layer_state = modified_reshape(
                                  word_embedding_weights[
                                    vec(modified_reshape(input_batch, row_number=1)), :]',
                                        row_number=numofhid1units * numwords)
# Compute the state of the HIDDEN LAYER

# First Compute inputs to hidden units
inputs_to_hidden_units = embed_to_hid_weights' * embedding_layer_state + repmat(hid_bias, 1, batchsize)

# Next step is to apply the logistic function to find activations
@devec hidden_layer_state = 1./ (1 + exp(-inputs_to_hidden_units))

# Compute the state of the OUTPUT LAYER

# First we need to compute the inputs for softmax units
inputs_to_softmax = hid_to_output_weights' * hidden_layer_state + repmat(output_bias, 1, batchsize)

# This trick is taken from Hinton's homeworks
inputs_to_softmax  = inputs_to_softmax - repmat(findmaxcols(inputs_to_softmax), vocab_size, 1)

# Apply the softmax approach
@devec output_layer_state = exp(inputs_to_softmax)

# Normalize the output_layer_state
output_layer_state = output_layer_state ./ repmat(sum_columns(output_layer_state), vocab_size, 1)

return (embedding_layer_state, hidden_layer_state, output_layer_state)
end

max_stars_repo_name: kirnap/Machine-Learning-in-Julia

max_issues_repo_name: kirnap/Machine-Learning-in-Julia

max_forks_repo_name: kirnap/Machine-Learning-in-Julia


text:
# ImagePFM.jl
# FileIO.jl integration for PFM image files.
# Copyright (c) 2021 Samuele Colombo, Paolo Galli

"""
    little_endian

`true` if system is little endian, `false` if big endian.
"""
const little_endian = ENDIAN_BOM == 0x04030201

"""
    write(io::IO, ::Type{format"PFM"}, image::AbstractMatrix{<:RGB})

Write an image to stream in PFM format.

A PFM files has an head containing, in order,
    - the magic bytes `PF\\n`,
    - the image width and height,
    - either -1.0 or 1.0 for little and big endian encoding of binary data respectively.
Then the `RGB(Float32)` image will be written as binary data scanning the image left to right - bottom to top.

# Examples
```jldoctest
julia> image = RGB{Float32}[RGB(1.0e1, 2.0e1, 3.0e1) RGB(1.0e2, 2.0e2, 3.0e2)
                            RGB(4.0e1, 5.0e1, 6.0e1) RGB(4.0e2, 5.0e2, 6.0e2)
                            RGB(7.0e1, 8.0e1, 9.0e1) RGB(7.0e2, 8.0e2, 9.0e2)];

julia> io = IOBuffer();

julia> ImagePFM.write(io, format"PFM", image) # write to stream in pfm format, return number of bytes written
84
```
"""
function write(io::IO, ::Type{format"PFM"}, image::AbstractMatrix{<:RGB})
    head = transcode(UInt8, "PF\n$(join(size(image)," "))\n$(little_endian ? -1. : 1.)\n")
    write(io, head, (c for c ∈ @view image[:, end:-1:begin])...)
end

"""
    write(io::IO, c::RGB{Float32})

Overload of the `write` function for the RGB type behavior is similar to the one of a generic container.
"""
function write(io::IO, c::RGB{Float32})
    write(io, c.r, c.g, c.b)
end

"""
    write(io::IO, c::RGB)

Throw error if `eltype(c) != Float32``
"""
function write(io::IO, c::RGB)
    throw(InvalidRGBEltype())
end

"""
    read(io::IO, fmt::Type{format"PFM"})

Read a PFM image from stream.

After skipping the magic bytes `PF\\n` the image width and height will be parsed, then the source endiannes.
The `RGB(Float32)` matrix will be read up to the `(width * height)`th element. The presence of additional data won't be considered an error.
Note that, unlike `read`, this function will convert endiannes for you from the declared source endiannes to the host endiannes.
"""
function read(io::IO, fmt::Type{format"PFM"})
    try
        skipmagic(io, fmt)
    catch e
        isa(e, ErrorException) && throw(InvalidPfmFileFormat("invalid head in PFM file: magic: expected $(magic(fmt))"))
    end
    img_width, img_height = io |> _read_line |> _parse_img_size
    endian_f = io |> _read_line |> _parse_endianness

    try
        map(endian_f, _read_matrix(io, RGB{Float32}, img_width, img_height))[:, end:-1:begin]
    catch e
        isa(e, ArgumentError) && throw(InvalidPfmFileFormat("invalid bytestream in PFM file: corrupted binary data."))
        isa(e, EOFError) && rethrow(InvalidPfmFileFormat("invalid bytestream in PFM file: found less floats than declared in head."))
        rethrow(e)
    end
end

#####################
# SUPPORT FUNCTIONS #
#####################

"""
    _parse_img_size(line::String)

Parse a string formatted like "img_width img_height" and return both values
"""
function _parse_img_size(line::String)
    elements = split(line, ' ')
    correct_length = 2
    (length(elements) == correct_length) || throw(InvalidPfmFileFormat("invalid head in PFM file: image size: expected $correct_length dimensions got $(length(elements))."))
    map(_parse_int ∘ string, elements)
end

"""
    _parse_int(str::String)

Verify that the given String is parsable to a type `UInt` and return its parsed value
"""
function _parse_int(str::String)
    DestT = UInt
    try
        parse(DestT, str)
    catch e
        isa(e, ArgumentError) && throw(InvalidPfmFileFormat("invalid head in PFM file: image size: \"$str\" is not parsable to type $DestT."))
        rethrow(e)
    end
end

"""
    _parse_endianness(line::String)

Verify that the given String is parsable to type `Float32` and is equal to ±1.0:
if the parsed value is equal to +1.0 then file endianness is big-endian,
else if it is equal to -1.0 then endianness is little-endian.

Return a function that translates from file endianness to host endianness.
"""
function _parse_endianness(line::String)
    DestT = Float32
    endian_spec = try
        parse(DestT, line)
    catch e
        isa(e, ArgumentError) && throw(InvalidPfmFileFormat("invalid head in PFM file: endianness: \"$line\" is not parsable to type $DestT."))
        rethrow(e)
    end

    valid_spec = one(DestT)
    if endian_spec == valid_spec
        return ntoh
    elseif endian_spec == -valid_spec
        return ltoh
    else
        throw(InvalidPfmFileFormat("invalid head in PFM file: endianness: expected ±$valid_spec got $endian_spec."))
    end
end

"""
    _read_line(io::IO)

Read line from stream, return nothing if eof, throw exceptions if read string is not ascii
and if newlines are not LF conform (it may signal that file corruption occurred
in file transfer from other systems) else return line.
"""
function _read_line(io::IO)
    eof(io) && return nothing
    line = readline(io, keep=true)
    ('\r' ∈ line) && throw(InvalidPfmFileFormat("invalid head in PFM file: newline is not LF conform."))
    isascii(line) || throw(InvalidPfmFileFormat("invalid head in PFM file: found non-ascii line."))
    line
end

"""
    _read_type(io::IO, DestT::Type)

Read a DestT instance from stream, return read value.
"""
function _read_type(io::IO, DestT::Type)
    eof(io) && return nothing
    len = sizeof(DestT)
    data = Array{UInt8, 1}(undef, len)
    readbytes!(io, data, len)
    reinterpret(DestT, data)[1]
end

"""
    _TypeStream

Utility interface for a stram containing at least `n` `T` type instances.
Useful for reading sets of values in a more compact notation.
"""
struct _TypeStream
    io::IO
    T::Type
    n::Integer
end

"""
    iterate(s::_TypeStream, state = 1)

Iterator over the interface.
"""
function iterate(s::_TypeStream, state = 1)
    if state <= s.n
        eof(s.io) && throw(EOFError())
        (_read_type(s.io, s.T), state + 1)
    else
        nothing
    end
end

"""
    _read(io::IO, C::Type{RGB{Float32}})

Utility function to read single instance of an `RGB` type.
"""
function _read(io::IO, C::Type{RGB{Float32}})
    C(_TypeStream(io, eltype(C), 3)...)
end

"""
    _read(io::IO, C::Type{<:RGB})

    Throw error if `eltype(c) != Float32``
"""
function _read(io::IO, C::Type{<:RGB})
    throw(InvalidRGBEltype())
end

"""
    _read_matrix(io::IO, DestT::Type, mat_width, mat_height)

Utility function to read the image matrix from file.
"""
function _read_matrix(io::IO, DestT::Type, mat_width, mat_height)
    mat = Matrix{DestT}(undef, mat_width, mat_height)
    for i in LinearIndices(mat)
        mat[i] = _read(io, DestT)
    end
    mat
end

ext: jl


text:
if get(ENV, "GITHUB_ACTIONS", "false") == "true"
    # We're being run as part of a Github action. The most likely case is that
    # this is the auto-merge action as part of the General registry.
    # For now, we're going to silently skip the tests.
    #
    # TODO(odow): remove this once we distribute the community edition.
    exit(0)
end

using Test
import Pkg
using MathProgBase
using CPLEX

@testset "$folder" for folder in ["C_API", "MathProgBase", "MathOptInterface"]
    @testset "$(file)" for file in readdir(folder)
        include(joinpath(folder, file))
    end
end


text:
# K is a flag for forward/backward
# also used as an alias for r2c/c2r

abstract type CuFFTPlan{T<:cufftNumber, K, inplace} <: Plan{T} end

mutable struct cCuFFTPlan{T<:cufftNumber,K,inplace,N} <: CuFFTPlan{T,K,inplace}
    plan::cufftHandle_t
    sz::NTuple{N,Int} # Julia size of input array
    osz::NTuple{N,Int} # Julia size of output array
    xtype::Int
    region::Any
    pinv::ScaledPlan # required by AbstractFFT API

    function cCuFFTPlan{T,K,inplace,N}(plan::cufftHandle_t, X::CuArray{T,N},
                                       sizey::Tuple, region, xtype::Integer
                                       ) where {T<:cufftNumber,K,inplace,N}
        # maybe enforce consistency of sizey
        p = new(plan, size(X), sizey, xtype, region)
        finalizer(destroy_plan, p)
        p
    end
end

cCuFFTPlan(plan,X,region,xtype::Integer) = cCuFFTPlan(plan,X,size(X),region,xtype)

mutable struct rCuFFTPlan{T<:cufftNumber,K,inplace,N} <: CuFFTPlan{T,K,inplace}
    plan::cufftHandle_t
    sz::NTuple{N,Int} # Julia size of input array
    osz::NTuple{N,Int} # Julia size of output array
    xtype::Int
    region::Any
    pinv::ScaledPlan # required by AbstractFFT API

    function rCuFFTPlan{T,K,inplace,N}(plan::cufftHandle_t, X::CuArray{T,N},
                                       sizey::Tuple, region, xtype::Integer
                                       ) where {T<:cufftNumber,K,inplace,N}
        # maybe enforce consistency of sizey
        p = new(plan, size(X), sizey, xtype, region)
        finalizer(destroy_plan, p)
        p
    end
end

rCuFFTPlan(plan,X,region,xtype::Integer) = rCuFFTPlan(plan,X,size(X),region,xtype)

const xtypenames = Dict{cufftType,String}(CUFFT_R2C => "real-to-complex",
                                          CUFFT_C2R => "complex-to-real",
                                          CUFFT_C2C => "complex",
                                          CUFFT_D2Z => "d.p. real-to-complex",
                                          CUFFT_Z2D => "d.p. complex-to-real",
                                          CUFFT_Z2Z => "d.p. complex")

function showfftdims(io, sz, T)
    if isempty(sz)
        print(io,"0-dimensional")
    elseif length(sz) == 1
        print(io, sz[1], "-element")
    else
        print(io, join(sz, "×"))
    end
    print(io, " CuArray of ", T)
end

function show(io::IO, p::CuFFTPlan{T,K,inplace}) where {T,K,inplace}
    print(io, inplace ? "CUFFT in-place " : "CUFFT ",
          xtypenames[p.xtype],
          K == CUFFT_FORWARD ? " forward" : " backward",
          " plan for ")
    showfftdims(io, p.sz, T)
end


text:
module Iconv

export iconv, togbk, toutf8, @g_str

function iconv(str, f, t)
    prcs = open(`iconv -f $f -t $t`, "r+")
    write(prcs.in, str)
    close(prcs.in)
    strgbk = read(prcs.out)
    return strgbk
end

iconv(v::Array{UInt8}, f, t) = iconv(String(v), f, t)

togbk(str) = iconv(str, "UTF-8", "GBK")
toutf8(str) = iconv(str, "GBK", "UTF-8")

macro g_str(str)
    str_gbk = togbk(str)
    :($str_gbk)
end

end # module


text:
using Test

@test 1 == 1

using LatticeBoltzmann

quadratures = [D2Q4(), D2Q5(), D2Q9(), D2Q13(), D2Q17(), D2Q21(), D2Q37()]
quadratures = LatticeBoltzmann.Quadratures

include("problems/taylor_green_vortex.jl")
include("problems/poiseuille.jl")
include("collision_models.jl")
include("initial_conditions.jl")

@testset "LatticeBoltzmann.jl" begin

    @testset "Multinomial hermite coefficients" begin

        ξ = [1.0 0.0]
        @test hermite(0, ξ) ≈ 1.0
        @test all(hermite(1, ξ) .≈ [1.0 0.0])
        @test all(hermite(2, ξ) .≈ [0.0 0.0; 0.0 -1.0])

        H_3 = hermite(3, ξ)
        @test all(H_3[:, :, 1] .≈ [-2.0 0.0; 0.0 -1.0])
        @test all(H_3[:, :, 2] .≈ [0.0 -1.0; -1.0 0.0])

        H_4 = hermite(4, ξ)

        # Check that our hermite polynomials obey the recurrance rule in 1 dimension
        ξ = 1.0
        for n in 3:4
            H = hermite(n, [ξ])[1]

            @test H ≈ ξ * hermite(n - 1, [ξ])[1] .- (n - 1) * hermite(n - 2, [ξ])[1]
        end

        # Check H4
        # H4 = [
        #     ξ[α_4] .* ξ[α_3] .* ξ[α_2] .* ξ[α_1] .- (
        #         # 6 terms
        #         (ξ[α_1] .* ξ[α_2]) .* δ(α_3, α_4) .+
        #         (ξ[α_1] .* ξ[α_3]) .* δ(α_2, α_4) .+
        #         (ξ[α_1] .* ξ[α_4]) .* δ(α_3, α_2) .+
        #         (ξ[α_2] .* ξ[α_3]) .* δ(α_1, α_4) .+
        #         (ξ[α_2] .* ξ[α_4]) .* δ(α_1, α_3) .+
        #         (ξ[α_3] .* ξ[α_4]) .* δ(α_1, α_2)
        #     ) .+ (δ(α_1, α_2) * δ(α_3, α_4) + δ(α_1, α_3) * δ(α_2, α_4) + δ(α_1, α_4) * δ(α_2, α_3))
        #     for α_1 = 1:D, α_2 = 1:D, α_3 = 1:D, α_4 = 1:D
        # ]
    end

    include("quadrature.jl")

    logspace(start, stop, length) = exp10.(range(start, stop = stop, length = length))
    @testset "moments of the equilibrium distribution of the $q lattice" for q in
                                                                             quadratures
        N = 1

        f = LatticeBoltzmann.equilibrium(q, 1.0, zeros(LatticeBoltzmann.dimension(q)), 1.0)

        @test LatticeBoltzmann.density(q, f) ≈ 1.0

        v = zeros(LatticeBoltzmann.dimension(q))
        LatticeBoltzmann.velocity!(q, f, 1.0, v)
        @test isapprox(v, zeros(LatticeBoltzmann.dimension(q)), atol = 1e-16)

        equilibrium(ρ, u) = begin
            T = 1.0
            # return LatticeBoltzmann.equilibrium(q, ρ, u, T)

            f = zeros(length(q.weights))
            LatticeBoltzmann.hermite_based_equilibrium!(q, ρ, u, T, f)
            f1 = copy(f)
            LatticeBoltzmann.equilibrium!(q, ρ, u, T, f)

            if !isapprox(LatticeBoltzmann.density(q, f), 1.0, rtol = 1e-10, atol = 1e-8)
                # @show f1 f
                # @show f1 - f
                LatticeBoltzmann.hermite_based_equilibrium!(q, ρ, u, T, f)
            end
            if !isapprox(LatticeBoltzmann.density(q, f1), 1.0, rtol = 1e-10, atol = 1e-8)
                # @show f1 f
                # @show f1 - f
                LatticeBoltzmann.hermite_based_equilibrium!(q, ρ, u, T, f)
            end
            # @show isapprox(LatticeBoltzmann.density(q, f), 1.0, rtol = 1e-10, atol = 1e-8) isapprox(LatticeBoltzmann.density(q, f1), 1.0, rtol = 1e-10, atol = 1e-8)
            # @show f - f1
            # return f1
            return f
        end
        density(ρ, u) = LatticeBoltzmann.density(q, equilibrium(ρ, u))
        momentum(ρ, u) = begin
            v = zeros(LatticeBoltzmann.dimension(q))
            LatticeBoltzmann.velocity!(q, equilibrium(ρ, u), 1.0, v)
            return v
        end

        pressure(ρ, u) = LATTICEBOLTZMANN.pressure(equilibrium(ρ, u))

        @test density(1.0, [0.0, 0.0]) ≈ 1.0
        @test isapprox(
            momentum(1.0, [0.0, 0.0]),
            fill(0.0, LatticeBoltzmann.dimension(q)),
            atol = 1e-16,
        )

        # Todo: analytically check the numerical error bounds

        for u in logspace(2, -9, 12)
            for v in [[0, 0], [u, 0.0], [0.0, u], [u, u]]
                @test isapprox(density(1.0, v), 1.0, rtol = 1e-10, atol = 1e-8)
                for d in 1:LatticeBoltzmann.dimension(q)
                    @test isapprox(momentum(1.0, v)[d], v[d], atol = 1e-11, rtol = 1e-6)
                end
            end
        end
    end
end


text:
module PropulsionWrapper

using JavaCall

const AbsoluteDate = @jimport org.orekit.time.AbsoluteDate
const AbstractConstantThrustPropulsionModel = @jimport org.orekit.forces.maneuvers.propulsion.AbstractConstantThrustPropulsionModel
const Attitude = @jimport org.orekit.attitudes.Attitude
const AttitudeProvider = @jimport org.orekit.attitudes.AttitudeProvider
const BasicConstantThrustPropulsionModel = @jimport org.orekit.forces.maneuvers.propulsion.BasicConstantThrustPropulsionModel
const Class = @jimport java.lang.Class
const ConstantThrustDirectionProvider = @jimport org.orekit.forces.maneuvers.propulsion.ConstantThrustDirectionProvider
const FieldAbsoluteDate = @jimport org.orekit.time.FieldAbsoluteDate
const FieldAttitude = @jimport org.orekit.attitudes.FieldAttitude
const FieldPVCoordinatesProvider = @jimport org.orekit.utils.FieldPVCoordinatesProvider
const FieldSpacecraftState = @jimport org.orekit.propagation.FieldSpacecraftState
const FieldVector3D = @jimport org.hipparchus.geometry.euclidean.threed.FieldVector3D
const Frame = @jimport org.orekit.frames.Frame
const JString = @jimport java.lang.String
const LOFType = @jimport org.orekit.frames.LOFType
const Object = @jimport java.lang.Object
const PVCoordinatesProvider = @jimport org.orekit.utils.PVCoordinatesProvider
const ParameterDriver = @jimport org.orekit.utils.ParameterDriver
const PropulsionModel = @jimport org.orekit.forces.maneuvers.propulsion.PropulsionModel
const RealFieldElement = @jimport org.hipparchus.RealFieldElement
const ScaledConstantThrustPropulsionModel = @jimport org.orekit.forces.maneuvers.propulsion.ScaledConstantThrustPropulsionModel
const SpacecraftState = @jimport org.orekit.propagation.SpacecraftState
const ThrustDirectionAndAttitudeProvider = @jimport org.orekit.forces.maneuvers.propulsion.ThrustDirectionAndAttitudeProvider
const ThrustDirectionProvider = @jimport org.orekit.forces.maneuvers.propulsion.ThrustDirectionProvider
const ThrustPropulsionModel = @jimport org.orekit.forces.maneuvers.propulsion.ThrustPropulsionModel
const Vector3D = @jimport org.hipparchus.geometry.euclidean.threed.Vector3D

export AbstractConstantThrustPropulsionModel
export BasicConstantThrustPropulsionModel
export ConstantThrustDirectionProvider
export PropulsionModel
export ScaledConstantThrustPropulsionModel
export ThrustDirectionAndAttitudeProvider
export ThrustDirectionProvider
export ThrustPropulsionModel
export build_from_custom_attitude
export build_from_direction_in_frame
export build_from_direction_in_lof
export build_from_fixed_direction_in_satellite_frame
export compute_thrust_direction
export equals
export get_acceleration
export get_attitude
export get_class
export get_direction
export get_flow_rate
export get_isp
export get_maneuver_attitude_provider
export get_mass_derivatives
export get_name
export get_parameters_drivers
export get_thrust
export get_thrust_vector
export get_thruster_axis_in_satellite_frame
export hash_code
export init
export notify
export notify_all
export to_string
export wait

include("abstract_constant_thrust_propulsion_model.jl")
include("basic_constant_thrust_propulsion_model.jl")
include("constant_thrust_direction_provider.jl")
include("propulsion_model.jl")
include("scaled_constant_thrust_propulsion_model.jl")
include("thrust_direction_and_attitude_provider.jl")
include("thrust_direction_provider.jl")
include("thrust_propulsion_model.jl")

end


text:
using Gnuplot, ColorSchemes
@gp key="left" linetypes(:seaborn_colorblind, dashed=true, ps=2)
for i in 1:10
    @gp :- i .* (0:10) "w lp t '$i'"
end
save(term ="pngcairo size 600,400", output ="./code/lineSmarkers.png") # hide

max_stars_repo_name: lazarusA/gnuplot-examples

max_issues_repo_name: lazarusA/gnuplot-examples

max_forks_repo_name: lazarusA/gnuplot-examples


text:
using SafeTestsets

@safetestset "rsvd" begin include("rsvd_tests.jl") end
@safetestset "rpca" begin include("rpca_tests.jl") end
# @safetestset "rrpca" begin include("rrpca_tests.jl") end
# @safetestset "rcur" begin include("rcur_tests.jl") end
# @safetestset "rnmf" begin include("rnmf_tests.jl") end
# @safetestset "rica" begin include("rica_tests.jl") end
# @safetestset "rid" begin include("rid_tests.jl") end
# @safetestset "rdmd" begin include("rdmd_tests.jl") end
# @safetestset "rnpca" begin include("rnpca_tests.jl") end
# @safetestset "rncca" begin include("rncca_tests.jl") end


text:
#=
Define some constants
Use string values to make printing/interpretation easier
=#
export JULIA, CPP, MATLAB, DENDRO, HOMG, CUSTOM_GEN_TARGET,
        SQUARE, IRREGULAR, UNIFORM_GRID, TREE, UNSTRUCTURED,
        CG, DG, HDG, FV, MIXED,
        NODAL, MODAL, CELL, LEGENDRE, UNIFORM, GAUSS, LOBATTO,
        NONLINEAR_NEWTON, NONLINEAR_SOMETHING,
        EULER_EXPLICIT, EULER_IMPLICIT, CRANK_NICHOLSON, RK4, LSRK4, PECE, MIXED_STEPPER,
        DEFAULT_SOLVER, PETSC_SOLVER, CUDA_SOLVER,
        VTK, RAW_OUTPUT, CUSTOM_OUTPUT,
        DIRICHLET, NEUMANN, ROBIN, NO_BC, FLUX,
        MSH_V2, MSH_V4,
        SCALAR, VECTOR, TENSOR, SYM_TENSOR, VAR_ARRAY,
        LHS, RHS,
        LINEMESH, QUADMESH, TRIMESH, HEXMESH

# Targets for generated code
const JULIA = "Julia";
const CPP = "C++";
const MATLAB = "Matlab";
const DENDRO = "Dendro";
const HOMG = "HOMG";
const CUSTOM_GEN_TARGET = "Custom gen target";

# Domain types
const SQUARE = "square";
const IRREGULAR = "irregular";

# Domain decomposition
const UNIFORM_GRID = "uniform grid";
const TREE = "tree";
const UNSTRUCTURED = "unstructured";

# Solver type
const CG = "CG";
const DG = "DG";
const HDG = "HDG";
const FV = "FV";
const MIXED = "mixed";

# Value type
const NODAL = "nodal";
const MODAL = "modal";
const CELL = "cell";

# Function space
const LEGENDRE = "Legendre";

# Element node positions
const UNIFORM = "uniform";
const GAUSS = "Gauss";
const LOBATTO = "Lobatto";

# Nonlinear solver methods
const NONLINEAR_NEWTON = "Newton";
const NONLINEAR_SOMETHING = "something";

# Time steppers
const EULER_EXPLICIT = "Euler-explicit";
const EULER_IMPLICIT = "Euler-implicit";
const CRANK_NICHOLSON = "crank-nicholson";
const RK4 = "RK4";
const LSRK4 = "LSRK4";
const PECE = "PECE";
const MIXED_STEPPER = "mixed stepper";

# Linear system solvers
const DEFAULT_SOLVER = "Default solver";
const PETSC_SOLVER = "PETSC";
const CUDA_SOLVER = "CUDA_SOLVER";

# Output format
const VTK = "vtk";
const RAW_OUTPUT = "raw";
const CUSTOM_OUTPUT = "custom";

# mesh file
const MSH_V2 = "msh-2";
const MSH_V4 = "msh-4";

#BC
const DIRICHLET = "Dirichlet";
const NEUMANN = "Neumann";
const ROBIN = "Robin";
const NO_BC = "No BC";
const FLUX = "flux";
const SYMMETRIC = "symmetric";

# variables
const SCALAR = "scalar";
const VECTOR = "vector";
const TENSOR = "tensor";
const SYM_TENSOR = "sym_tensor";
const VAR_ARRAY = "var array";

const LHS = "lhs";
const RHS = "rhs";

# simple mesh types
const LINEMESH = "line_mesh";
const QUADMESH = "quad_mesh";
const TRIMESH = "tri_mesh";
const HEXMESH = "hex_mesh";

max_stars_repo_name: paralab/Finch

max_issues_repo_name: paralab/Finch

max_forks_repo_name: paralab/Finch


text:
const seaborn_rocket_gradient = [RGBA(0.01060815, 0.01808215, 0.10018654),
                                 RGBA(0.01428972, 0.02048237, 0.10374486),
                                 RGBA(0.01831941, 0.0229766, 0.10738511),
                                 RGBA(0.02275049, 0.02554464, 0.11108639),
                                 RGBA(0.02759119, 0.02818316, 0.11483751),
                                 RGBA(0.03285175, 0.03088792, 0.11863035),
                                 RGBA(0.03853466, 0.03365771, 0.12245873),
                                 RGBA(0.04447016, 0.03648425, 0.12631831),
                                 RGBA(0.05032105, 0.03936808, 0.13020508),
                                 RGBA(0.05611171, 0.04224835, 0.13411624),
                                 RGBA(0.0618531, 0.04504866, 0.13804929),
                                 RGBA(0.06755457, 0.04778179, 0.14200206),
                                 RGBA(0.0732236, 0.05045047, 0.14597263),
                                 RGBA(0.0788708, 0.05305461, 0.14995981),
                                 RGBA(0.08450105, 0.05559631, 0.15396203),
                                 RGBA(0.09011319, 0.05808059, 0.15797687),
                                 RGBA(0.09572396, 0.06050127, 0.16200507),
                                 RGBA(0.10132312, 0.06286782, 0.16604287),
                                 RGBA(0.10692823, 0.06517224, 0.17009175),
                                 RGBA(0.1125315, 0.06742194, 0.17414848),
                                 RGBA(0.11813947, 0.06961499, 0.17821272),
                                 RGBA(0.12375803, 0.07174938, 0.18228425),
                                 RGBA(0.12938228, 0.07383015, 0.18636053),
                                 RGBA(0.13501631, 0.07585609, 0.19044109),
                                 RGBA(0.14066867, 0.0778224, 0.19452676),
                                 RGBA(0.14633406, 0.07973393, 0.1986151),
                                 RGBA(0.15201338, 0.08159108, 0.20270523),
                                 RGBA(0.15770877, 0.08339312, 0.20679668),
                                 RGBA(0.16342174, 0.0851396, 0.21088893),
                                 RGBA(0.16915387, 0.08682996, 0.21498104),
                                 RGBA(0.17489524, 0.08848235, 0.2190294),
                                 RGBA(0.18065495, 0.09009031, 0.22303512),
                                 RGBA(0.18643324, 0.09165431, 0.22699705),
                                 RGBA(0.19223028, 0.09317479, 0.23091409),
                                 RGBA(0.19804623, 0.09465217, 0.23478512),
                                 RGBA(0.20388117, 0.09608689, 0.23860907),
                                 RGBA(0.20973515, 0.09747934, 0.24238489),
                                 RGBA(0.21560818, 0.09882993, 0.24611154),
                                 RGBA(0.22150014, 0.10013944, 0.2497868),
                                 RGBA(0.22741085, 0.10140876, 0.25340813),
                                 RGBA(0.23334047, 0.10263737, 0.25697736),
                                 RGBA(0.23928891, 0.10382562, 0.2604936),
                                 RGBA(0.24525608, 0.10497384, 0.26395596),
                                 RGBA(0.25124182, 0.10608236, 0.26736359),
                                 RGBA(0.25724602, 0.10715148, 0.27071569),
                                 RGBA(0.26326851, 0.1081815, 0.27401148),
                                 RGBA(0.26930915, 0.1091727, 0.2772502),
                                 RGBA(0.27536766, 0.11012568, 0.28043021),
                                 RGBA(0.28144375, 0.11104133, 0.2835489),
                                 RGBA(0.2875374, 0.11191896, 0.28660853),
                                 RGBA(0.29364846, 0.11275876, 0.2896085),
                                 RGBA(0.29977678, 0.11356089, 0.29254823),
                                 RGBA(0.30592213, 0.11432553, 0.29542718),
                                 RGBA(0.31208435, 0.11505284, 0.29824485),
                                 RGBA(0.31826327, 0.1157429, 0.30100076),
                                 RGBA(0.32445869, 0.11639585, 0.30369448),
                                 RGBA(0.33067031, 0.11701189, 0.30632563),
                                 RGBA(0.33689808, 0.11759095, 0.3088938),
                                 RGBA(0.34314168, 0.11813362, 0.31139721),
                                 RGBA(0.34940101, 0.11863987, 0.3138355),
                                 RGBA(0.355676, 0.11910909, 0.31620996),
                                 RGBA(0.36196644, 0.1195413, 0.31852037),
                                 RGBA(0.36827206, 0.11993653, 0.32076656),
                                 RGBA(0.37459292, 0.12029443, 0.32294825),
                                 RGBA(0.38092887, 0.12061482, 0.32506528),
                                 RGBA(0.38727975, 0.12089756, 0.3271175),
                                 RGBA(0.39364518, 0.12114272, 0.32910494),
                                 RGBA(0.40002537, 0.12134964, 0.33102734),
                                 RGBA(0.40642019, 0.12151801, 0.33288464),
                                 RGBA(0.41282936, 0.12164769, 0.33467689),
                                 RGBA(0.41925278, 0.12173833, 0.33640407),
                                 RGBA(0.42569057, 0.12178916, 0.33806605),
                                 RGBA(0.43214263, 0.12179973, 0.33966284),
                                 RGBA(0.43860848, 0.12177004, 0.34119475),
                                 RGBA(0.44508855, 0.12169883, 0.34266151),
                                 RGBA(0.45158266, 0.12158557, 0.34406324),
                                 RGBA(0.45809049, 0.12142996, 0.34540024),
                                 RGBA(0.46461238, 0.12123063, 0.34667231),
                                 RGBA(0.47114798, 0.12098721, 0.34787978),
                                 RGBA(0.47769736, 0.12069864, 0.34902273),
                                 RGBA(0.48426077, 0.12036349, 0.35010104),
                                 RGBA(0.49083761, 0.11998161, 0.35111537),
                                 RGBA(0.49742847, 0.11955087, 0.35206533),
                                 RGBA(0.50403286, 0.11907081, 0.35295152),
                                 RGBA(0.51065109, 0.11853959, 0.35377385),
                                 RGBA(0.51728314, 0.1179558, 0.35453252),
                                 RGBA(0.52392883, 0.11731817, 0.35522789),
                                 RGBA(0.53058853, 0.11662445, 0.35585982),
                                 RGBA(0.53726173, 0.11587369, 0.35642903),
                                 RGBA(0.54394898, 0.11506307, 0.35693521),
                                 RGBA(0.5506426, 0.11420757, 0.35737863),
                                 RGBA(0.55734473, 0.11330456, 0.35775059),
                                 RGBA(0.56405586, 0.11235265, 0.35804813),
                                 RGBA(0.57077365, 0.11135597, 0.35827146),
                                 RGBA(0.5774991, 0.11031233, 0.35841679),
                                 RGBA(0.58422945, 0.10922707, 0.35848469),
                                 RGBA(0.59096382, 0.10810205, 0.35847347),
                                 RGBA(0.59770215, 0.10693774, 0.35838029),
                                 RGBA(0.60444226, 0.10573912, 0.35820487),
                                 RGBA(0.61118304, 0.10450943, 0.35794557),
                                 RGBA(0.61792306, 0.10325288, 0.35760108),
                                 RGBA(0.62466162, 0.10197244, 0.35716891),
                                 RGBA(0.63139686, 0.10067417, 0.35664819),
                                 RGBA(0.63812122, 0.09938212, 0.35603757),
                                 RGBA(0.64483795, 0.0980891, 0.35533555),
                                 RGBA(0.65154562, 0.09680192, 0.35454107),
                                 RGBA(0.65824241, 0.09552918, 0.3536529),
                                 RGBA(0.66492652, 0.09428017, 0.3526697),
                                 RGBA(0.67159578, 0.09306598, 0.35159077),
                                 RGBA(0.67824099, 0.09192342, 0.3504148),
                                 RGBA(0.684863, 0.09085633, 0.34914061),
                                 RGBA(0.69146268, 0.0898675, 0.34776864),
                                 RGBA(0.69803757, 0.08897226, 0.3462986),
                                 RGBA(0.70457834, 0.0882129, 0.34473046),
                                 RGBA(0.71108138, 0.08761223, 0.3430635),
                                 RGBA(0.7175507, 0.08716212, 0.34129974),
                                 RGBA(0.72398193, 0.08688725, 0.33943958),
                                 RGBA(0.73035829, 0.0868623, 0.33748452),
                                 RGBA(0.73669146, 0.08704683, 0.33543669),
                                 RGBA(0.74297501, 0.08747196, 0.33329799),
                                 RGBA(0.74919318, 0.08820542, 0.33107204),
                                 RGBA(0.75535825, 0.08919792, 0.32876184),
                                 RGBA(0.76145589, 0.09050716, 0.32637117),
                                 RGBA(0.76748424, 0.09213602, 0.32390525),
                                 RGBA(0.77344838, 0.09405684, 0.32136808),
                                 RGBA(0.77932641, 0.09634794, 0.31876642),
                                 RGBA(0.78513609, 0.09892473, 0.31610488),
                                 RGBA(0.79085854, 0.10184672, 0.313391),
                                 RGBA(0.7965014, 0.10506637, 0.31063031),
                                 RGBA(0.80205987, 0.10858333, 0.30783),
                                 RGBA(0.80752799, 0.11239964, 0.30499738),
                                 RGBA(0.81291606, 0.11645784, 0.30213802),
                                 RGBA(0.81820481, 0.12080606, 0.29926105),
                                 RGBA(0.82341472, 0.12535343, 0.2963705),
                                 RGBA(0.82852822, 0.13014118, 0.29347474),
                                 RGBA(0.83355779, 0.13511035, 0.29057852),
                                 RGBA(0.83850183, 0.14025098, 0.2876878),
                                 RGBA(0.84335441, 0.14556683, 0.28480819),
                                 RGBA(0.84813096, 0.15099892, 0.281943),
                                 RGBA(0.85281737, 0.15657772, 0.27909826),
                                 RGBA(0.85742602, 0.1622583, 0.27627462),
                                 RGBA(0.86196552, 0.16801239, 0.27346473),
                                 RGBA(0.86641628, 0.17387796, 0.27070818),
                                 RGBA(0.87079129, 0.17982114, 0.26797378),
                                 RGBA(0.87507281, 0.18587368, 0.26529697),
                                 RGBA(0.87925878, 0.19203259, 0.26268136),
                                 RGBA(0.8833417, 0.19830556, 0.26014181),
                                 RGBA(0.88731387, 0.20469941, 0.25769539),
                                 RGBA(0.89116859, 0.21121788, 0.2553592),
                                 RGBA(0.89490337, 0.21785614, 0.25314362),
                                 RGBA(0.8985026, 0.22463251, 0.25108745),
                                 RGBA(0.90197527, 0.23152063, 0.24918223),
                                 RGBA(0.90530097, 0.23854541, 0.24748098),
                                 RGBA(0.90848638, 0.24568473, 0.24598324),
                                 RGBA(0.911533, 0.25292623, 0.24470258),
                                 RGBA(0.9144225, 0.26028902, 0.24369359),
                                 RGBA(0.91717106, 0.26773821, 0.24294137),
                                 RGBA(0.91978131, 0.27526191, 0.24245973),
                                 RGBA(0.92223947, 0.28287251, 0.24229568),
                                 RGBA(0.92456587, 0.29053388, 0.24242622),
                                 RGBA(0.92676657, 0.29823282, 0.24285536),
                                 RGBA(0.92882964, 0.30598085, 0.24362274),
                                 RGBA(0.93078135, 0.31373977, 0.24468803),
                                 RGBA(0.93262051, 0.3215093, 0.24606461),
                                 RGBA(0.93435067, 0.32928362, 0.24775328),
                                 RGBA(0.93599076, 0.33703942, 0.24972157),
                                 RGBA(0.93752831, 0.34479177, 0.25199928),
                                 RGBA(0.93899289, 0.35250734, 0.25452808),
                                 RGBA(0.94036561, 0.36020899, 0.25734661),
                                 RGBA(0.94167588, 0.36786594, 0.2603949),
                                 RGBA(0.94291042, 0.37549479, 0.26369821),
                                 RGBA(0.94408513, 0.3830811, 0.26722004),
                                 RGBA(0.94520419, 0.39062329, 0.27094924),
                                 RGBA(0.94625977, 0.39813168, 0.27489742),
                                 RGBA(0.94727016, 0.4055909, 0.27902322),
                                 RGBA(0.94823505, 0.41300424, 0.28332283),
                                 RGBA(0.94914549, 0.42038251, 0.28780969),
                                 RGBA(0.95001704, 0.42771398, 0.29244728),
                                 RGBA(0.95085121, 0.43500005, 0.29722817),
                                 RGBA(0.95165009, 0.44224144, 0.30214494),
                                 RGBA(0.9524044, 0.44944853, 0.3072105),
                                 RGBA(0.95312556, 0.45661389, 0.31239776),
                                 RGBA(0.95381595, 0.46373781, 0.31769923),
                                 RGBA(0.95447591, 0.47082238, 0.32310953),
                                 RGBA(0.95510255, 0.47787236, 0.32862553),
                                 RGBA(0.95569679, 0.48489115, 0.33421404),
                                 RGBA(0.95626788, 0.49187351, 0.33985601),
                                 RGBA(0.95681685, 0.49882008, 0.34555431),
                                 RGBA(0.9573439, 0.50573243, 0.35130912),
                                 RGBA(0.95784842, 0.51261283, 0.35711942),
                                 RGBA(0.95833051, 0.51946267, 0.36298589),
                                 RGBA(0.95879054, 0.52628305, 0.36890904),
                                 RGBA(0.95922872, 0.53307513, 0.3748895),
                                 RGBA(0.95964538, 0.53983991, 0.38092784),
                                 RGBA(0.96004345, 0.54657593, 0.3870292),
                                 RGBA(0.96042097, 0.55328624, 0.39319057),
                                 RGBA(0.96077819, 0.55997184, 0.39941173),
                                 RGBA(0.9611152, 0.5666337, 0.40569343),
                                 RGBA(0.96143273, 0.57327231, 0.41203603),
                                 RGBA(0.96173392, 0.57988594, 0.41844491),
                                 RGBA(0.96201757, 0.58647675, 0.42491751),
                                 RGBA(0.96228344, 0.59304598, 0.43145271),
                                 RGBA(0.96253168, 0.5995944, 0.43805131),
                                 RGBA(0.96276513, 0.60612062, 0.44471698),
                                 RGBA(0.96298491, 0.6126247, 0.45145074),
                                 RGBA(0.96318967, 0.61910879, 0.45824902),
                                 RGBA(0.96337949, 0.6255736, 0.46511271),
                                 RGBA(0.96355923, 0.63201624, 0.47204746),
                                 RGBA(0.96372785, 0.63843852, 0.47905028),
                                 RGBA(0.96388426, 0.64484214, 0.4861196),
                                 RGBA(0.96403203, 0.65122535, 0.4932578),
                                 RGBA(0.96417332, 0.65758729, 0.50046894),
                                 RGBA(0.9643063, 0.66393045, 0.5077467),
                                 RGBA(0.96443322, 0.67025402, 0.51509334),
                                 RGBA(0.96455845, 0.67655564, 0.52251447),
                                 RGBA(0.96467922, 0.68283846, 0.53000231),
                                 RGBA(0.96479861, 0.68910113, 0.53756026),
                                 RGBA(0.96492035, 0.69534192, 0.5451917),
                                 RGBA(0.96504223, 0.7015636, 0.5528892),
                                 RGBA(0.96516917, 0.70776351, 0.5606593),
                                 RGBA(0.96530224, 0.71394212, 0.56849894),
                                 RGBA(0.96544032, 0.72010124, 0.57640375),
                                 RGBA(0.96559206, 0.72623592, 0.58438387),
                                 RGBA(0.96575293, 0.73235058, 0.59242739),
                                 RGBA(0.96592829, 0.73844258, 0.60053991),
                                 RGBA(0.96612013, 0.74451182, 0.60871954),
                                 RGBA(0.96632832, 0.75055966, 0.61696136),
                                 RGBA(0.96656022, 0.75658231, 0.62527295),
                                 RGBA(0.96681185, 0.76258381, 0.63364277),
                                 RGBA(0.96709183, 0.76855969, 0.64207921),
                                 RGBA(0.96739773, 0.77451297, 0.65057302),
                                 RGBA(0.96773482, 0.78044149, 0.65912731),
                                 RGBA(0.96810471, 0.78634563, 0.66773889),
                                 RGBA(0.96850919, 0.79222565, 0.6764046),
                                 RGBA(0.96893132, 0.79809112, 0.68512266),
                                 RGBA(0.96935926, 0.80395415, 0.69383201),
                                 RGBA(0.9698028, 0.80981139, 0.70252255),
                                 RGBA(0.97025511, 0.81566605, 0.71120296),
                                 RGBA(0.97071849, 0.82151775, 0.71987163),
                                 RGBA(0.97120159, 0.82736371, 0.72851999),
                                 RGBA(0.97169389, 0.83320847, 0.73716071),
                                 RGBA(0.97220061, 0.83905052, 0.74578903),
                                 RGBA(0.97272597, 0.84488881, 0.75440141),
                                 RGBA(0.97327085, 0.85072354, 0.76299805),
                                 RGBA(0.97383206, 0.85655639, 0.77158353),
                                 RGBA(0.97441222, 0.86238689, 0.78015619),
                                 RGBA(0.97501782, 0.86821321, 0.78871034),
                                 RGBA(0.97564391, 0.87403763, 0.79725261),
                                 RGBA(0.97628674, 0.87986189, 0.8057883),
                                 RGBA(0.97696114, 0.88568129, 0.81430324),
                                 RGBA(0.97765722, 0.89149971, 0.82280948),
                                 RGBA(0.97837585, 0.89731727, 0.83130786),
                                 RGBA(0.97912374, 0.90313207, 0.83979337),
                                 RGBA(0.979891, 0.90894778, 0.84827858),
                                 RGBA(0.98067764, 0.91476465, 0.85676611),
                                 RGBA(0.98137749, 0.92061729, 0.86536915)]

const seaborn_icefire_gradient = [RGBA(0.73936227, 0.90443867, 0.85757238),
                                  RGBA(0.72888063, 0.89639109, 0.85488394),
                                  RGBA(0.71834255, 0.88842162, 0.8521605),
                                  RGBA(0.70773866, 0.88052939, 0.849422),
                                  RGBA(0.69706215, 0.87271313, 0.84668315),
                                  RGBA(0.68629021, 0.86497329, 0.84398721),
                                  RGBA(0.67543654, 0.85730617, 0.84130969),
                                  RGBA(0.66448539, 0.84971123, 0.83868005),
                                  RGBA(0.65342679, 0.84218728, 0.83611512),
                                  RGBA(0.64231804, 0.83471867, 0.83358584),
                                  RGBA(0.63117745, 0.827294, 0.83113431),
                                  RGBA(0.62000484, 0.81991069, 0.82876741),
                                  RGBA(0.60879435, 0.81256797, 0.82648905),
                                  RGBA(0.59754118, 0.80526458, 0.82430414),
                                  RGBA(0.58624247, 0.79799884, 0.82221573),
                                  RGBA(0.57489525, 0.7907688, 0.82022901),
                                  RGBA(0.56349779, 0.78357215, 0.81834861),
                                  RGBA(0.55204294, 0.77640827, 0.81657563),
                                  RGBA(0.54052516, 0.76927562, 0.81491462),
                                  RGBA(0.52894085, 0.76217215, 0.81336913),
                                  RGBA(0.51728854, 0.75509528, 0.81194156),
                                  RGBA(0.50555676, 0.74804469, 0.81063503),
                                  RGBA(0.49373871, 0.7410187, 0.80945242),
                                  RGBA(0.48183174, 0.73401449, 0.80839675),
                                  RGBA(0.46982587, 0.72703075, 0.80747097),
                                  RGBA(0.45770893, 0.72006648, 0.80667756),
                                  RGBA(0.44547249, 0.71311941, 0.80601991),
                                  RGBA(0.43318643, 0.70617126, 0.80549278),
                                  RGBA(0.42110294, 0.69916972, 0.80506683),
                                  RGBA(0.40925101, 0.69211059, 0.80473246),
                                  RGBA(0.3976693, 0.68498786, 0.80448272),
                                  RGBA(0.38632002, 0.67781125, 0.80431024),
                                  RGBA(0.37523981, 0.67057537, 0.80420832),
                                  RGBA(0.36442578, 0.66328229, 0.80417474),
                                  RGBA(0.35385939, 0.65593699, 0.80420591),
                                  RGBA(0.34358916, 0.64853177, 0.8043),
                                  RGBA(0.33355526, 0.64107876, 0.80445484),
                                  RGBA(0.32383062, 0.63356578, 0.80467091),
                                  RGBA(0.31434372, 0.62600624, 0.8049475),
                                  RGBA(0.30516161, 0.618389, 0.80528692),
                                  RGBA(0.29623491, 0.61072284, 0.80569021),
                                  RGBA(0.28759072, 0.60300319, 0.80616055),
                                  RGBA(0.27923924, 0.59522877, 0.80669803),
                                  RGBA(0.27114651, 0.5874047, 0.80730545),
                                  RGBA(0.26337153, 0.57952055, 0.80799113),
                                  RGBA(0.25588696, 0.57157984, 0.80875922),
                                  RGBA(0.248686, 0.56358255, 0.80961366),
                                  RGBA(0.24180668, 0.55552289, 0.81055123),
                                  RGBA(0.23526251, 0.54739477, 0.8115939),
                                  RGBA(0.22921445, 0.53918506, 0.81267292),
                                  RGBA(0.22397687, 0.53086094, 0.8137141),
                                  RGBA(0.21977058, 0.52241482, 0.81457651),
                                  RGBA(0.21658989, 0.51384321, 0.81528511),
                                  RGBA(0.21452772, 0.50514155, 0.81577278),
                                  RGBA(0.21372783, 0.49630865, 0.81589566),
                                  RGBA(0.21409503, 0.48734861, 0.81566163),
                                  RGBA(0.2157176, 0.47827123, 0.81487615),
                                  RGBA(0.21842857, 0.46909168, 0.81351614),
                                  RGBA(0.22211705, 0.45983212, 0.81146983),
                                  RGBA(0.22665681, 0.45052233, 0.80860217),
                                  RGBA(0.23176013, 0.44119137, 0.80494325),
                                  RGBA(0.23727775, 0.43187704, 0.80038017),
                                  RGBA(0.24298285, 0.42261123, 0.79493267),
                                  RGBA(0.24865068, 0.41341842, 0.78869164),
                                  RGBA(0.25423116, 0.40433127, 0.78155831),
                                  RGBA(0.25950239, 0.39535521, 0.77376848),
                                  RGBA(0.2644736, 0.38651212, 0.76524809),
                                  RGBA(0.26901584, 0.37779582, 0.75621942),
                                  RGBA(0.27318141, 0.36922056, 0.746605),
                                  RGBA(0.27690355, 0.3607736, 0.73659374),
                                  RGBA(0.28023585, 0.35244234, 0.72622103),
                                  RGBA(0.28306009, 0.34438449, 0.71500731),
                                  RGBA(0.28535896, 0.33660243, 0.70303975),
                                  RGBA(0.28708711, 0.32912157, 0.69034504),
                                  RGBA(0.28816354, 0.32200604, 0.67684067),
                                  RGBA(0.28862749, 0.31519824, 0.66278813),
                                  RGBA(0.28847904, 0.30869064, 0.6482815),
                                  RGBA(0.28770912, 0.30250126, 0.63331265),
                                  RGBA(0.28640325, 0.29655509, 0.61811374),
                                  RGBA(0.28458943, 0.29082155, 0.60280913),
                                  RGBA(0.28233561, 0.28527482, 0.58742866),
                                  RGBA(0.27967038, 0.2798938, 0.57204225),
                                  RGBA(0.27665361, 0.27465357, 0.55667809),
                                  RGBA(0.27332564, 0.2695165, 0.54145387),
                                  RGBA(0.26973851, 0.26447054, 0.52634916),
                                  RGBA(0.2659204, 0.25949691, 0.511417),
                                  RGBA(0.26190145, 0.25458123, 0.49668768),
                                  RGBA(0.2577151, 0.24971691, 0.48214874),
                                  RGBA(0.25337618, 0.24490494, 0.46778758),
                                  RGBA(0.24890842, 0.24013332, 0.45363816),
                                  RGBA(0.24433654, 0.23539226, 0.4397245),
                                  RGBA(0.23967922, 0.23067729, 0.4260591),
                                  RGBA(0.23495608, 0.22598894, 0.41262952),
                                  RGBA(0.23018113, 0.22132414, 0.39945577),
                                  RGBA(0.22534609, 0.21670847, 0.38645794),
                                  RGBA(0.22048761, 0.21211723, 0.37372555),
                                  RGBA(0.2156198, 0.20755389, 0.36125301),
                                  RGBA(0.21074637, 0.20302717, 0.34903192),
                                  RGBA(0.20586893, 0.19855368, 0.33701661),
                                  RGBA(0.20101757, 0.19411573, 0.32529173),
                                  RGBA(0.19619947, 0.18972425, 0.31383846),
                                  RGBA(0.19140726, 0.18540157, 0.30260777),
                                  RGBA(0.1866769, 0.1811332, 0.29166583),
                                  RGBA(0.18201285, 0.17694992, 0.28088776),
                                  RGBA(0.17745228, 0.17282141, 0.27044211),
                                  RGBA(0.17300684, 0.16876921, 0.26024893),
                                  RGBA(0.16868273, 0.16479861, 0.25034479),
                                  RGBA(0.16448691, 0.16091728, 0.24075373),
                                  RGBA(0.16043195, 0.15714351, 0.23141745),
                                  RGBA(0.15652427, 0.15348248, 0.22238175),
                                  RGBA(0.15277065, 0.14994111, 0.21368395),
                                  RGBA(0.14918274, 0.14653431, 0.20529486),
                                  RGBA(0.14577095, 0.14327403, 0.19720829),
                                  RGBA(0.14254381, 0.14016944, 0.18944326),
                                  RGBA(0.13951035, 0.13723063, 0.18201072),
                                  RGBA(0.13667798, 0.13446606, 0.17493774),
                                  RGBA(0.13405762, 0.13188822, 0.16820842),
                                  RGBA(0.13165767, 0.12950667, 0.16183275),
                                  RGBA(0.12948748, 0.12733187, 0.15580631),
                                  RGBA(0.12755435, 0.1253723, 0.15014098),
                                  RGBA(0.12586516, 0.12363617, 0.1448459),
                                  RGBA(0.12442647, 0.12213143, 0.13992571),
                                  RGBA(0.12324241, 0.12086419, 0.13539995),
                                  RGBA(0.12232067, 0.11984278, 0.13124644),
                                  RGBA(0.12166209, 0.11907077, 0.12749671),
                                  RGBA(0.12126982, 0.11855309, 0.12415079),
                                  RGBA(0.12114244, 0.11829179, 0.1212385),
                                  RGBA(0.12127766, 0.11828837, 0.11878534),
                                  RGBA(0.12284806, 0.1179729, 0.11772022),
                                  RGBA(0.12619498, 0.11721796, 0.11770203),
                                  RGBA(0.129968, 0.11663788, 0.11792377),
                                  RGBA(0.13410011, 0.11625146, 0.11839138),
                                  RGBA(0.13855459, 0.11606618, 0.11910584),
                                  RGBA(0.14333775, 0.11607038, 0.1200606),
                                  RGBA(0.148417, 0.11626929, 0.12125453),
                                  RGBA(0.15377389, 0.11666192, 0.12268364),
                                  RGBA(0.15941427, 0.11723486, 0.12433911),
                                  RGBA(0.16533376, 0.11797856, 0.12621303),
                                  RGBA(0.17152547, 0.11888403, 0.12829735),
                                  RGBA(0.17797765, 0.11994436, 0.13058435),
                                  RGBA(0.18468769, 0.12114722, 0.13306426),
                                  RGBA(0.19165663, 0.12247737, 0.13572616),
                                  RGBA(0.19884415, 0.12394381, 0.1385669),
                                  RGBA(0.20627181, 0.12551883, 0.14157124),
                                  RGBA(0.21394877, 0.12718055, 0.14472604),
                                  RGBA(0.22184572, 0.12893119, 0.14802579),
                                  RGBA(0.22994394, 0.13076731, 0.15146314),
                                  RGBA(0.23823937, 0.13267611, 0.15502793),
                                  RGBA(0.24676041, 0.13462172, 0.15870321),
                                  RGBA(0.25546457, 0.13661751, 0.16248722),
                                  RGBA(0.26433628, 0.13865956, 0.16637301),
                                  RGBA(0.27341345, 0.14070412, 0.17034221),
                                  RGBA(0.28264773, 0.14277192, 0.1743957),
                                  RGBA(0.29202272, 0.14486161, 0.17852793),
                                  RGBA(0.30159648, 0.14691224, 0.1827169),
                                  RGBA(0.31129002, 0.14897583, 0.18695213),
                                  RGBA(0.32111555, 0.15103351, 0.19119629),
                                  RGBA(0.33107961, 0.1530674, 0.19543758),
                                  RGBA(0.34119892, 0.15504762, 0.1996803),
                                  RGBA(0.35142388, 0.15701131, 0.20389086),
                                  RGBA(0.36178937, 0.1589124, 0.20807639),
                                  RGBA(0.37229381, 0.16073993, 0.21223189),
                                  RGBA(0.38288348, 0.16254006, 0.2163249),
                                  RGBA(0.39359592, 0.16426336, 0.22036577),
                                  RGBA(0.40444332, 0.16588767, 0.22434027),
                                  RGBA(0.41537995, 0.16745325, 0.2282297),
                                  RGBA(0.42640867, 0.16894939, 0.23202755),
                                  RGBA(0.43754706, 0.17034847, 0.23572899),
                                  RGBA(0.44878564, 0.1716535, 0.23932344),
                                  RGBA(0.4601126, 0.17287365, 0.24278607),
                                  RGBA(0.47151732, 0.17401641, 0.24610337),
                                  RGBA(0.48300689, 0.17506676, 0.2492737),
                                  RGBA(0.49458302, 0.17601892, 0.25227688),
                                  RGBA(0.50623876, 0.17687777, 0.255096),
                                  RGBA(0.5179623, 0.17765528, 0.2577162),
                                  RGBA(0.52975234, 0.17835232, 0.2601134),
                                  RGBA(0.54159776, 0.17898292, 0.26226847),
                                  RGBA(0.55348804, 0.17956232, 0.26416003),
                                  RGBA(0.56541729, 0.18010175, 0.26575971),
                                  RGBA(0.57736669, 0.180631, 0.26704888),
                                  RGBA(0.58932081, 0.18117827, 0.26800409),
                                  RGBA(0.60127582, 0.18175888, 0.26858488),
                                  RGBA(0.61319563, 0.1824336, 0.2687872),
                                  RGBA(0.62506376, 0.18324015, 0.26858301),
                                  RGBA(0.63681202, 0.18430173, 0.26795276),
                                  RGBA(0.64842603, 0.18565472, 0.26689463),
                                  RGBA(0.65988195, 0.18734638, 0.26543435),
                                  RGBA(0.67111966, 0.18948885, 0.26357955),
                                  RGBA(0.68209194, 0.19216636, 0.26137175),
                                  RGBA(0.69281185, 0.19535326, 0.25887063),
                                  RGBA(0.70335022, 0.19891271, 0.25617971),
                                  RGBA(0.71375229, 0.20276438, 0.25331365),
                                  RGBA(0.72401436, 0.20691287, 0.25027366),
                                  RGBA(0.73407638, 0.21145051, 0.24710661),
                                  RGBA(0.74396983, 0.21631913, 0.24380715),
                                  RGBA(0.75361506, 0.22163653, 0.24043996),
                                  RGBA(0.7630579, 0.22731637, 0.23700095),
                                  RGBA(0.77222228, 0.23346231, 0.23356628),
                                  RGBA(0.78115441, 0.23998404, 0.23013825),
                                  RGBA(0.78979746, 0.24694858, 0.22678822),
                                  RGBA(0.79819286, 0.25427223, 0.22352658),
                                  RGBA(0.80630444, 0.26198807, 0.22040877),
                                  RGBA(0.81417437, 0.27001406, 0.21744645),
                                  RGBA(0.82177364, 0.27837336, 0.21468316),
                                  RGBA(0.82915955, 0.28696963, 0.21210766),
                                  RGBA(0.83628628, 0.2958499, 0.20977813),
                                  RGBA(0.84322168, 0.30491136, 0.20766435),
                                  RGBA(0.84995458, 0.31415945, 0.2057863),
                                  RGBA(0.85648867, 0.32358058, 0.20415327),
                                  RGBA(0.86286243, 0.33312058, 0.20274969),
                                  RGBA(0.86908321, 0.34276705, 0.20157271),
                                  RGBA(0.87512876, 0.3525416, 0.20064949),
                                  RGBA(0.88100349, 0.36243385, 0.19999078),
                                  RGBA(0.8866469, 0.37249496, 0.1997976),
                                  RGBA(0.89203964, 0.38273475, 0.20013431),
                                  RGBA(0.89713496, 0.39318156, 0.20121514),
                                  RGBA(0.90195099, 0.40380687, 0.20301555),
                                  RGBA(0.90648379, 0.41460191, 0.20558847),
                                  RGBA(0.9106967, 0.42557857, 0.20918529),
                                  RGBA(0.91463791, 0.43668557, 0.21367954),
                                  RGBA(0.91830723, 0.44790913, 0.21916352),
                                  RGBA(0.92171507, 0.45922856, 0.22568002),
                                  RGBA(0.92491786, 0.4705936, 0.23308207),
                                  RGBA(0.92790792, 0.48200153, 0.24145932),
                                  RGBA(0.93073701, 0.49341219, 0.25065486),
                                  RGBA(0.93343918, 0.5048017, 0.26056148),
                                  RGBA(0.93602064, 0.51616486, 0.27118485),
                                  RGBA(0.93850535, 0.52748892, 0.28242464),
                                  RGBA(0.94092933, 0.53875462, 0.29416042),
                                  RGBA(0.94330011, 0.5499628, 0.30634189),
                                  RGBA(0.94563159, 0.56110987, 0.31891624),
                                  RGBA(0.94792955, 0.57219822, 0.33184256),
                                  RGBA(0.95020929, 0.5832232, 0.34508419),
                                  RGBA(0.95247324, 0.59419035, 0.35859866),
                                  RGBA(0.95471709, 0.60510869, 0.37236035),
                                  RGBA(0.95698411, 0.61595766, 0.38629631),
                                  RGBA(0.95923863, 0.62676473, 0.40043317),
                                  RGBA(0.9615041, 0.6375203, 0.41474106),
                                  RGBA(0.96371553, 0.64826619, 0.42928335),
                                  RGBA(0.96591497, 0.65899621, 0.44380444),
                                  RGBA(0.96809871, 0.66971662, 0.45830232),
                                  RGBA(0.9702495, 0.6804394, 0.47280492),
                                  RGBA(0.9723881, 0.69115622, 0.48729272),
                                  RGBA(0.97450723, 0.70187358, 0.50178034),
                                  RGBA(0.9766108, 0.712592, 0.51626837),
                                  RGBA(0.97871716, 0.72330511, 0.53074053),
                                  RGBA(0.98082222, 0.73401769, 0.54520694),
                                  RGBA(0.9829001, 0.74474445, 0.5597019),
                                  RGBA(0.98497466, 0.75547635, 0.57420239),
                                  RGBA(0.98705581, 0.76621129, 0.58870185),
                                  RGBA(0.98913325, 0.77695637, 0.60321626),
                                  RGBA(0.99119918, 0.78771716, 0.61775821),
                                  RGBA(0.9932672, 0.79848979, 0.63231691),
                                  RGBA(0.99535958, 0.80926704, 0.64687278),
                                  RGBA(0.99740544, 0.82008078, 0.66150571),
                                  RGBA(0.9992197, 0.83100723, 0.6764127)]


text:
#================================================

SkipList- and SkipListSet-specific code

=================================================#

#===========================
SkipList constructors
===========================#

function SkipList{T,M}(;
    max_height = DEFAULT_MAX_HEIGHT,
    p = DEFAULT_P,
    node_capacity = DEFAULT_NODE_CAPACITY,
) where {T,M}

    _check_mode(M)

    left_sentinel = LeftSentinel{T,M}(; max_height=max_height, capacity=node_capacity)
    right_sentinel = RightSentinel{T,M}(; max_height=max_height, capacity=node_capacity)
    predecessors = Vector{Node{T,M}}(undef, max_height)
    successors = Vector{Node{T,M}}(undef, max_height)
    height = 1
    length = 0

    for ii = 1:max_height
        link_nodes!(left_sentinel, right_sentinel, ii)
    end

    SkipList{T,M}(
        p,
        max_height,
        node_capacity,
        predecessors,
        successors,
        left_sentinel,
        right_sentinel,
        height,
        length
    )
end

#===========================
SkipList external API
===========================#

height(list::SkipList) = list.height

Base.length(list::SkipList) = list.length

node_capacity(list::SkipList) = list.node_capacity

function Base.insert!(list::SkipList{T,M}, val) where {T,M}
    level_found, predecessors, successors = find_node(list, val)

    # We insert into the predecessor node from our search that sits in the
    # first level of the skip list. If that node is full, we must split it
    # into two lists.
    insertion_node = predecessors[1]

    # If the value was found in the list and we're in :Set mode, we skip over
    # insertion and just return `nothing`
    if M == :Set && level_found != NODE_NOT_FOUND
        nothing
    else
        insertion_node = begin
            if isfull(insertion_node)
                # Insertion would overflow the node, so we must first split it into
                # two nodes.
                old_node, new_node = split!(
                    insertion_node;
                    max_height=max_height(list),
                    capacity=node_capacity(list),
                    p=height_p(list),
                )

                # If the new node has height greater than the old height of the list,
                # we must increase the size of the list.
                if height(list) < height(new_node)
                    for ii = height(list)+1:height(new_node)
                        predecessors[ii] = list.left_sentinel
                        successors[ii] = list.right_sentinel
                    end

                    list.height = height(new_node)
                end

                # Insert the new node between the predecessor / successor nodes.
                interpolate_node!(predecessors, successors, new_node)

                # We insert into the right node if its key is ≤ the insertion value;
                # otherwise, we insert into the left node.
                is_sentinel(old_node) || new_node ≤ val ? new_node : old_node
            else
                insertion_node
            end
        end

        insert!(insertion_node, val)
        list.length += 1

        Some(val)
    end
end

function Base.in(val, list::SkipList)
    level_found, predecessors, successors = find_node(list, val; right_if_member = false)
    level_found != NODE_NOT_FOUND
end

function Base.delete!(list::SkipList, val)
    level_found, predecessors, successors = find_node(list, val; right_if_member = false)
    if level_found == NODE_NOT_FOUND
        return nothing
    end

    deletion_node = successors[1]
    result = delete!(deletion_node, val)

    # If the node is empty, we must delete it and remove it from the list
    if isempty(deletion_node) && !is_sentinel(deletion_node)
        for ii = 1:height(deletion_node)
            link_nodes!(predecessors[ii], next(deletion_node, ii), ii)
        end
    end

    list.length -= 1

    Some(val)
end

# Implementation of the iteration interface for SkipList

Base.iterate(list::SkipList) = Base.iterate(list, (list.left_sentinel, 1))

function Base.iterate(list::SkipList, state)
    node, ii = state

    if length(node) < ii
        if is_right_sentinel(node)
            nothing
        else
            iterate(list, (next(node, 1), 1))
        end
    else
        node.vals[ii], (node, ii+1)
    end
end

#===========================
SkipList internal API
===========================#

"""
Traverse through a skip list, searching for the input value. Returns

- `level_found`: the first level on which a node was found containing the
  input value.
- `predecessors`: a list of nodes with the property that `predecessors[ii]`
  is the rightmost node whose key is `≤ val` in the `ii`th level.
- `successors`: a list of the nodes that come after the predecessor nodes in
  the `predecessors` list.
"""
function find_node(list::SkipList{T,M}, val; right_if_member = true) where {T,M}
    list_height = height(list)
    predecessors = list.predecessor_buffer
    successors = list.successor_buffer

    level_found = NODE_NOT_FOUND

    current_node = list.left_sentinel
    for ii = list_height:-1:1
        # Move to the right until we reach a node whose key is
        # greater than the value we're searching for
        next_node = next(current_node, ii)
        while right_if_member ? (next_node < val || val ∈ next_node) : (next_node < val && val ∉ next_node)
            current_node = next_node
            next_node = next(current_node, ii)
        end

        # Note to future self: trying to figure out how to delete node. Need
        # to reconsider the < inequality when doing search

        if level_found == NODE_NOT_FOUND
            if (right_if_member || is_left_sentinel(current_node)) && val ∈ current_node
                level_found = ii
            elseif !right_if_member && val ∈ next_node
                level_found = ii
            end
        end
        predecessors[ii] = current_node
        successors[ii] = next_node
    end

    level_found, predecessors, successors
end


text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Generate encode table.
const BASE64_ENCODE = [UInt8(x) for x in ['A':'Z'; 'a':'z'; '0':'9'; '+'; '/']]

# '-' and '_' instead of '+' and '/'
const BASE64URL_ENCODE = [UInt8(x) for x in ['A':'Z'; 'a':'z'; '0':'9'; '-'; '_']]

encode_base64(x::UInt8) = @inbounds return BASE64_ENCODE[(x & 0x3f) + 1]
encode_base64url(x::UInt8) = @inbounds return BASE64URL_ENCODE[(x & 0x3f) + 1]
encodepadding()  = UInt8('=')

struct Base64EncodePipe{F<:Function} <: IO
    io::IO
    buffer::Buffer
    encode::F

    function Base64EncodePipe(io::IO; encoder::T=encode_base64) where {T<:Function}
        # The buffer size must be at least 3.
        buffer = Buffer(512)
        pipe = new{T}(io, buffer, encoder)
        finalizer(_ -> close(pipe), buffer)
        return pipe
    end
end

function Base.unsafe_write(pipe::Base64EncodePipe, ptr::Ptr{UInt8}, n::UInt)::Int
    buffer = pipe.buffer
    m = buffer.size
    b1, b2, b3, k = loadtriplet!(buffer, ptr, n)
    @assert k ≥ m
    p = ptr + k - m
    if k < 3
        if k == 1
            buffer[1] = b1
            buffer.size = 1
        elseif k == 2
            buffer[1] = b1
            buffer[2] = b2
            buffer.size = 2
        end
        return p - ptr
    end
    @assert buffer.size == 0

    i = 0
    p_end = ptr + n
    while true
        buffer[i+1] = pipe.encode(b1 >> 2          )
        buffer[i+2] = pipe.encode(b1 << 4 | b2 >> 4)
        buffer[i+3] = pipe.encode(b2 << 2 | b3 >> 6)
        buffer[i+4] = pipe.encode(          b3     )
        i += 4
        if p + 2 < p_end
            b1 = unsafe_load(p, 1)
            b2 = unsafe_load(p, 2)
            b3 = unsafe_load(p, 3)
            p += 3
        else
            break
        end
        if i + 4 > capacity(buffer)
            unsafe_write(pipe.io, pointer(buffer), i)
            i = 0
        end
    end
    if i > 0
        unsafe_write(pipe.io, pointer(buffer), i)
    end

    while p < p_end
        buffer[buffer.size+=1] = unsafe_load(p)
        p += 1
    end
    return p - ptr
end

function Base.write(pipe::Base64EncodePipe, x::UInt8)
    buffer = pipe.buffer
    buffer[buffer.size+=1] = x
    if buffer.size == 3
        unsafe_write(pipe, C_NULL, 0)
    end
    return 1
end

function Base.close(pipe::Base64EncodePipe)
    b1, b2, b3, k = loadtriplet!(pipe.buffer, Ptr{UInt8}(C_NULL), UInt(0))
    if k == 0
        # no leftover and padding
    elseif k == 1
        write(pipe.io,
              pipe.encode(b1 >> 2),
              pipe.encode(b1 << 4),
              encodepadding(),
              encodepadding())
    elseif k == 2
        write(pipe.io,
              pipe.encode(          b1 >> 2),
              pipe.encode(b1 << 4 | b2 >> 4),
              pipe.encode(b2 << 2          ),
              encodepadding())
    else
        @assert k == 3
        write(pipe.io,
              pipe.encode(b1 >> 2          ),
              pipe.encode(b1 << 4 | b2 >> 4),
              pipe.encode(b2 << 2 | b3 >> 6),
              pipe.encode(          b3     ))
    end
    return nothing
end

# Load three bytes from buffer and ptr.
function loadtriplet!(buffer::Buffer, ptr::Ptr{UInt8}, n::UInt)
    b1 = b2 = b3 = 0x00
    if buffer.size == 0
        if n == 0
            k = 0
        elseif n == 1
            b1 = unsafe_load(ptr, 1)
            k = 1
        elseif n == 2
            b1 = unsafe_load(ptr, 1)
            b2 = unsafe_load(ptr, 2)
            k = 2
        else
            b1 = unsafe_load(ptr, 1)
            b2 = unsafe_load(ptr, 2)
            b3 = unsafe_load(ptr, 3)
            k = 3
        end
    elseif buffer.size == 1
        b1 = buffer[1]
        if n == 0
            k = 1
        elseif n == 1
            b2 = unsafe_load(ptr, 1)
            k = 2
        else
            b2 = unsafe_load(ptr, 1)
            b3 = unsafe_load(ptr, 2)
            k = 3
        end
    elseif buffer.size == 2
        b1 = buffer[1]
        b2 = buffer[2]
        if n == 0
            k = 2
        else
            b3 = unsafe_load(ptr, 1)
            k = 3
        end
    else
        @assert buffer.size == 3
        b1 = buffer[1]
        b2 = buffer[2]
        b3 = buffer[3]
        k = 3
    end
    empty!(buffer)
    return b1, b2, b3, k
end

function base64encode(f::Function, args...; context=nothing)
    s = IOBuffer()
    b = Base64EncodePipe(s)
    if context === nothing
        f(b, args...)
    else
        f(IOContext(b, context), args...)
    end
    close(b)
    return String(take!(s))
end
base64encode(args...; context=nothing) = base64encode(write, args...; context=context)

function base64urlencode(f::Function, args...; context=nothing)
    s = IOBuffer()
    b = Base64EncodePipe(s, encoder=encode_base64url)
    if context === nothing
        f(b, args...)
    else
        f(IOContext(b, context), args...)
    end
    close(b)
    return String(take!(s))
end
base64urlencode(args...; context=nothing) = base64urlencode(write, args...; context=context)


text:
@testset "CoreModel: Detailed community stoichiometrix matrix check" begin
    m1 = test_toyModel()
    m2 = test_toyModel()
    ex_rxn_mets = Dict("EX_m1(e)" => "m1[e]", "EX_m3(e)" => "m3[e]")

    c1 = join_with_exchanges(CoreModel, [m1, m2], ex_rxn_mets)

    # test of stoichs are the same
    @test all(c1.S[1:6, 1:7] .== c1.S[7:12, 8:14])
    # test if each models exchange reactions have been added to the environmental exchange properly
    @test sum(c1.S[:, 4]) == 0
    @test sum(c1.S[:, 5]) == 0
    @test sum(c1.S[:, 11]) == 0
    @test sum(c1.S[:, 12]) == 0
    @test sum(c1.S[:, 15]) == -1
    @test sum(c1.S[:, 16]) == -1
    # test if exchange metablites with environment are added properly
    @test c1.S[13, 4] == c1.S[13, 11] == 1
    @test c1.S[14, 5] == c1.S[14, 12] == 1
    # test if environmental exchanges have been added properly
    @test c1.S[13, 15] == c1.S[14, 16] == -1
    # test of bounds set properly
    lb, ub = bounds(c1)
    @test all(lb[1:14] .== -ub[1:14] .== -1000)
    @test all(lb[15:16] .== -ub[15:16] .== 0.0)

    add_community_objective!(
        c1,
        Dict("species_1_biomass[c]" => 1.0, "species_2_biomass[c]" => 1.0),
    )
    @test c1.S[6, end] == -1.0
    @test c1.S[12, end] == -1.0

    c2 = join_with_exchanges(
        CoreModel,
        [m1, m2],
        ex_rxn_mets;
        biomass_ids = ["biomass1", "biomass1"],
    )
    # test if same base stoich matrix
    @test all(c2.S[1:14, 1:16] .== c1.S[:, 1:16])
    # test if biomass reaction and metabolites are added correctly
    @test all(c2.S[:, end] .== 0)
    @test c2.S[15, 7] == 1
    @test c2.S[16, 14] == 1

    update_community_objective!(
        c2,
        "community_biomass",
        Dict("species_1_biomass1" => 0.1, "species_2_biomass1" => 0.9),
    )
    @test c2.S[15, end] == -0.1
    @test c2.S[16, end] == -0.9
end

@testset "CoreModel: Small model join" begin
    m1 = load_model(model_paths["e_coli_core.json"])
    m2 = load_model(CoreModel, model_paths["e_coli_core.json"])

    exchange_rxn_mets = Dict(
        ex_rxn => first(keys(reaction_stoichiometry(m2, ex_rxn))) for
        ex_rxn in reactions(m2) if looks_like_exchange_reaction(ex_rxn)
    )

    biomass_ids = ["BIOMASS_Ecoli_core_w_GAM", "BIOMASS_Ecoli_core_w_GAM"]

    community = join_with_exchanges(
        CoreModel,
        [m1, m2],
        exchange_rxn_mets;
        biomass_ids = biomass_ids,
    )

    env_ex_inds = indexin(keys(exchange_rxn_mets), reactions(community))
    m2_ex_inds = indexin(keys(exchange_rxn_mets), reactions(m2))
    community.xl[env_ex_inds] .= m2.xl[m2_ex_inds]
    community.xu[env_ex_inds] .= m2.xu[m2_ex_inds]

    biomass_ids = Dict(
        "species_1_BIOMASS_Ecoli_core_w_GAM" => 1.0,
        "species_2_BIOMASS_Ecoli_core_w_GAM" => 1.0,
    )

    update_community_objective!(community, "community_biomass", biomass_ids)

    d = flux_balance_analysis_dict(community, Tulip.Optimizer)
    @test size(stoichiometry(community)) == (166, 211)
    @test isapprox(d["community_biomass"], 0.41559777495618294, atol = TEST_TOLERANCE)
end

@testset "CoreModel: Heterogenous model join" begin
    m1 = load_model(CoreModel, model_paths["e_coli_core.json"])
    m2 = load_model(CoreModel, model_paths["iJO1366.mat"])

    exchange_rxn_mets = Dict(
        ex_rxn => first(keys(reaction_stoichiometry(m2, ex_rxn))) for
        ex_rxn in reactions(m2) if looks_like_exchange_reaction(ex_rxn)
    )

    biomass_ids = ["BIOMASS_Ecoli_core_w_GAM", "BIOMASS_Ec_iJO1366_core_53p95M"]

    community = join_with_exchanges(
        CoreModel,
        [m1, m2],
        exchange_rxn_mets;
        biomass_ids = biomass_ids,
    )

    env_ex_inds = indexin(keys(exchange_rxn_mets), reactions(community))
    m2_ex_inds = indexin(keys(exchange_rxn_mets), reactions(m2))
    m1_ex_inds = indexin(keys(exchange_rxn_mets), reactions(m1))

    for (env_ex, m2_ex, m1_ex) in zip(env_ex_inds, m2_ex_inds, m1_ex_inds)
        m2lb = isnothing(m2_ex) ? 0.0 : m2.xl[m2_ex]
        m2ub = isnothing(m2_ex) ? 0.0 : m2.xu[m2_ex]

        m1lb = isnothing(m1_ex) ? 0.0 : m1.xl[m1_ex]
        m1ub = isnothing(m1_ex) ? 0.0 : m1.xu[m1_ex]

        community.xl[env_ex] = m1lb + m2lb
        community.xu[env_ex] = m1ub + m2ub
    end

    biomass_ids = Dict(
        "species_1_BIOMASS_Ecoli_core_w_GAM" => 1.0,
        "species_2_BIOMASS_Ec_iJO1366_core_53p95M" => 1.0,
    )

    update_community_objective!(community, "community_biomass", biomass_ids)

    d = flux_balance_analysis_dict(
        community,
        Tulip.Optimizer;
        modifications = [change_optimizer_attribute("IPM_IterationsLimit", 1000)],
    )

    @test size(stoichiometry(community)) == (2203, 3003)
    @test isapprox(d["community_biomass"], 0.8739215069675402, atol = TEST_TOLERANCE)
end

@testset "CoreModel: Community model modifications" begin
    m1 = load_model(CoreModel, model_paths["e_coli_core.json"])

    exchange_rxn_mets = Dict(
        ex_rxn => first(keys(reaction_stoichiometry(m1, ex_rxn))) for
        ex_rxn in reactions(m1) if looks_like_exchange_reaction(ex_rxn)
    )

    biomass_ids = ["BIOMASS_Ecoli_core_w_GAM"]

    community =
        join_with_exchanges(CoreModel, [m1], exchange_rxn_mets; biomass_ids = biomass_ids)

    env_ex_inds = indexin(keys(exchange_rxn_mets), reactions(community))
    m1_ex_inds = indexin(keys(exchange_rxn_mets), reactions(m1))
    community.xl[env_ex_inds] .= m1.xl[m1_ex_inds]
    community.xu[env_ex_inds] .= m1.xu[m1_ex_inds]

    m2 = load_model(CoreModel, model_paths["e_coli_core.json"])

    community = add_model_with_exchanges(
        community,
        m2,
        exchange_rxn_mets;
        model_name = "species_2",
        biomass_id = "BIOMASS_Ecoli_core_w_GAM",
    )

    biomass_ids = Dict(
        "species_1_BIOMASS_Ecoli_core_w_GAM" => 1.0,
        "species_2_BIOMASS_Ecoli_core_w_GAM" => 1.0,
    )

    update_community_objective!(community, "community_biomass", biomass_ids)

    d = flux_balance_analysis_dict(community, Tulip.Optimizer)

    @test size(stoichiometry(community)) == (166, 211)
    @test isapprox(d["community_biomass"], 0.41559777495618294, atol = TEST_TOLERANCE)
end

@testset "StandardModel: Detailed community stoichiometrix matrix check" begin
    m1 = test_toyModel()
    m2 = test_toyModel()
    ex_rxn_mets = Dict("EX_m1(e)" => "m1[e]", "EX_m3(e)" => "m3[e]")

    c1 = join_with_exchanges(StandardModel, [m1, m2], ex_rxn_mets)
    @test size(stoichiometry(c1)) == (14, 16)

    # test if each models exchange reactions have been added to the environmental exchange properly
    @test c1.reactions["EX_m1(e)"].metabolites["m1[e]"] == -1
    @test c1.reactions["EX_m3(e)"].metabolites["m3[e]"] == -1

    # test if exchange metabolites with environment are added properly
    @test "m1[e]" in metabolites(c1)
    @test "m3[e]" in metabolites(c1)

    # test if environmental exchanges have been added properly
    @test c1.reactions["species_1_EX_m1(e)"].metabolites["m1[e]"] == -1
    @test c1.reactions["species_1_EX_m1(e)"].metabolites["species_1_m1[e]"] == 1
    @test c1.reactions["species_2_EX_m3(e)"].metabolites["m3[e]"] == -1
    @test c1.reactions["species_2_EX_m3(e)"].metabolites["species_2_m3[e]"] == 1

    # test of bounds set properly
    lb, ub = bounds(c1) # this only works because the insertion order is preserved (they get added last)
    @test all(lb[1:14] .== -ub[1:14] .== -1000)
    @test all(lb[15:16] .== -ub[15:16] .== 0.0)

    add_community_objective!(
        c1,
        Dict("species_1_biomass[c]" => 1.0, "species_2_biomass[c]" => 1.0),
    )
    @test c1.reactions["community_biomass"].metabolites["species_2_biomass[c]"] == -1
    @test c1.reactions["community_biomass"].metabolites["species_1_biomass[c]"] == -1

    c2 = join_with_exchanges(
        StandardModel,
        [m1, m2],
        ex_rxn_mets;
        biomass_ids = ["biomass1", "biomass1"],
    )
    @test size(stoichiometry(c2)) == (16, 17)

    # test if biomass reaction and metabolites are added correctly
    @test isempty(c2.reactions["community_biomass"].metabolites)
end

@testset "StandardModel: coarse community models checks" begin
    m1 = load_model(StandardModel, model_paths["e_coli_core.json"])

    exchange_rxn_mets = Dict(
        ex_rxn => first(keys(reaction_stoichiometry(m1, ex_rxn))) for
        ex_rxn in reactions(m1) if looks_like_exchange_reaction(ex_rxn)
    )

    biomass_ids = ["BIOMASS_Ecoli_core_w_GAM", "BIOMASS_Ecoli_core_w_GAM"]

    c = join_with_exchanges(
        StandardModel,
        [m1, m1],
        exchange_rxn_mets;
        biomass_ids = biomass_ids,
    )

    for rid in keys(exchange_rxn_mets)
        c.reactions[rid].lb = m1.reactions[rid].lb
        c.reactions[rid].ub = m1.reactions[rid].ub
    end

    @test c.reactions["species_1_BIOMASS_Ecoli_core_w_GAM"].metabolites["species_1_BIOMASS_Ecoli_core_w_GAM"] ==
          1.0

    biomass_ids = Dict(
        "species_1_BIOMASS_Ecoli_core_w_GAM" => 1.0,
        "species_2_BIOMASS_Ecoli_core_w_GAM" => 1.0,
    )

    update_community_objective!(c, "community_biomass", biomass_ids)

    d = flux_balance_analysis_dict(c, Tulip.Optimizer)
    @test size(stoichiometry(c)) == (166, 211)
    @test isapprox(d["community_biomass"], 0.41559777495618294, atol = TEST_TOLERANCE)
end


text:
## findmin/findmax/minumum/maximum

A = sparse([1.0 3.0 6.0;
            5.0 2.0 4.0])
for (tup, rval, rind) in [((1,), [1.0 2.0 4.0], [1 4 6]),
                          ((2,), reshape([1.0,2.0], 2, 1), reshape([1,4], 2, 1)),
                          ((1,2), fill(1.0,1,1),fill(1,1,1))]
    @test findmin(A, tup) == (rval, rind)
    @test findmin!(similar(rval), similar(rind), A) == (rval, rind)
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((1,), [5.0 3.0 6.0], [2 3 5]),
                          ((2,), reshape([6.0,5.0], 2, 1), reshape([5,2], 2, 1)),
                          ((1,2), fill(6.0,1,1),fill(5,1,1))]
    @test findmax(A, tup) == (rval, rind)
    @test findmax!(similar(rval), similar(rind), A) == (rval, rind)
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end

#issue 23209

A = sparse([1.0 3.0 6.0;
            NaN 2.0 4.0])
for (tup, rval, rind) in [((1,), [NaN 2.0 4.0], [2 4 6]),
                          ((2,), reshape([1.0, NaN], 2, 1), reshape([1,2], 2, 1)),
                          ((1,2), fill(NaN,1,1),fill(2,1,1))]
    @test string(findmin(A, tup)) == string((rval, rind))
    @test string(findmin!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((1,), [NaN 3.0 6.0], [2 3 5]),
                          ((2,), reshape([6.0, NaN], 2, 1), reshape([5,2], 2, 1)),
                          ((1,2), fill(NaN,1,1),fill(2,1,1))]
    @test string(findmax(A, tup)) == string((rval, rind))
    @test string(findmax!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end

A = sparse([1.0 NaN 6.0;
            NaN 2.0 4.0])
for (tup, rval, rind) in [((1,), [NaN NaN 4.0], [2 3 6]),
                          ((2,), reshape([NaN, NaN], 2, 1), reshape([3,2], 2, 1)),
                          ((1,2), fill(NaN,1,1),fill(2,1,1))]
    @test string(findmin(A, tup))  == string((rval, rind))
    @test string(findmin!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((1,), [NaN NaN 6.0], [2 3 5]),
                          ((2,), reshape([NaN, NaN], 2, 1), reshape([3,2], 2, 1)),
                          ((1,2), fill(NaN,1,1),fill(2,1,1))]
    @test string(findmax(A, tup)) == string((rval, rind))
    @test string(findmax!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end

A = sparse([Inf -Inf Inf  -Inf;
            Inf  Inf -Inf -Inf])
for (tup, rval, rind) in [((1,), [Inf -Inf -Inf -Inf], [1 3 6 7]),
                          ((2,), reshape([-Inf -Inf], 2, 1), reshape([3,6], 2, 1)),
                          ((1,2), fill(-Inf,1,1),fill(3,1,1))]
    @test string(findmin(A, tup))  == string((rval, rind))
    @test string(findmin!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((1,), [Inf Inf Inf -Inf], [1 4 5 7]),
                          ((2,), reshape([Inf Inf], 2, 1), reshape([1,2], 2, 1)),
                          ((1,2), fill(Inf,1,1),fill(1,1,1))]
    @test string(findmax(A, tup)) == string((rval, rind))
    @test string(findmax!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end

A = sparse([BigInt(10)])
for (tup, rval, rind) in [((2,), [BigInt(10)], [1])]
    @test string(findmin(A, tup))  == string((rval, rind))
    @test string(findmin!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((2,), [BigInt(10)], [1])]
    @test string(findmax(A, tup)) == string((rval, rind))
    @test string(findmax!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end

A = sparse([BigInt(-10)])
for (tup, rval, rind) in [((2,), [BigInt(-10)], [1])]
    @test string(findmin(A, tup))  == string((rval, rind))
    @test string(findmin!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((2,), [BigInt(-10)], [1])]
    @test string(findmax(A, tup)) == string((rval, rind))
    @test string(findmax!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end

A = sparse([BigInt(10) BigInt(-10)])
for (tup, rval, rind) in [((2,), [BigInt(-10)], [2])]
    @test string(findmin(A, tup))  == string((rval, rind))
    @test string(findmin!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((2,), [BigInt(10)], [1])]
    @test string(findmax(A, tup)) == string((rval, rind))
    @test string(findmax!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end

A = sparse(["a", "b"])
for (tup, rval, rind) in [((1,), ["a"], [1])]
    @test string(findmin(A, tup))  == string((rval, rind))
    @test string(findmin!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(minimum(A, tup)) == string(rval)
    @test string(minimum!(similar(rval), A)) == string(rval)
    @test string(minimum!(copy(rval), A, init=false)) == string(rval)
end

for (tup, rval, rind) in [((1,), ["b"], [2])]
    @test string(findmax(A, tup)) == string((rval, rind))
    @test string(findmax!(similar(rval), similar(rind), A)) == string((rval, rind))
    @test string(maximum(A, tup)) == string(rval)
    @test string(maximum!(similar(rval), A)) == string(rval)
    @test string(maximum!(copy(rval), A, init=false)) == string(rval)
end


text:
module TestFillArrays

using Test
using SIMDIndexing

include("../examples/vdot.jl")
using LinearAlgebra
using FillArrays

arr1 = randn(2^20)
arr2 = Ones{Float64}(length(arr1))

@test vdot(arr1, arr2) ≈ dot(arr1, arr2)

end  # module