text:
# This file is part of JuliaFMI.
# License is MIT: https://servant-om.fh-bielefeld.de/gitlab/AnHeuermann/FMU_JL_Simulator/blob/master/LICENSE.txt

# This file contains wrapper to call FMI functions

include("FMI2Types.jl")
include("FMICallbackFunctions.jl") # Callbacks for logging and memory handling

# ##############################################################################
# Inquire Platform and Version Number of Header Files
# ##############################################################################

"""
```
    fmi2GetTypesPlatform(libHandle::Ptr{Nothing}) -> String

    fmi2GetTypesPlatform(fmu::FMU) -> String
```
Returns string to uniquely identify the "fmi2TypesPlatform.h" header file
used for compilation of the functions of the FMU.
Standard type is "default".
"""
function fmi2GetTypesPlatform(libHandle::Ptr{Nothing})
    func = dlsym(libHandle, :fmi2GetTypesPlatform)

    typesPlatform = ccall(
      func,
      Cstring,
      ()
      )

    return unsafe_string(typesPlatform)
end

function fmi2GetTypesPlatform(fmu::FMU)
    return fmi2GetTypesPlatform(fmu.libHandle)
end

"""
```
    function fmi2GetVersion(libHandle::Ptr{Nothing}) -> String

    function fmi2GetVersion(fmu::FMU) -> String
```
Returns the version of the "fmi2Functions.h" header file which was used to
compile the functions of the FMU.
Standard type is "2.0"
"""
function fmi2GetVersion(libHandle::Ptr{Nothing})
    func = dlsym(libHandle, :fmi2GetVersion)

    version = ccall(
      func,
      Cstring,
      ()
      )

    return unsafe_string(version)
end

function fmi2GetVersion(fmu::FMU)
    return fmi2GetVersion(fmu.libHandle)
end

# ##############################################################################
# Creation, Destruction and Logging of FMU Instances
# ##############################################################################

"""
```
    fmi2Instantiate(fmu::FMU)

    fmi2Instantiate(libHandle::Ptr{Nothing}, instanceName::String, fmuType::fmuType, fmuGUID::String, fmuResourceLocation::String, functions::CallbackFunctions, visible::Bool, loggingOn::Bool)
```
Returns a new instance of a FMU component.
If a null pointer is returned instantiation failed.

## Example calls
```
julia> fmu = loadFMU("path\\\\to\\\\fmu\\\\helloWorld.fmu")
julia> fmu = fmi2Instantiate(fmu)
```
or
```
julia> fmu = loadFMU("path\\\\to\\\\fmu\\\\helloWorld.fmu")
julia> fmi2Component = fmi2Instantiate(fmu.libHandle, fmu.instanceName,
modelExchange, fmu.fmuGUID, fmu.fmuResourceLocation, fmu.callbackFunctions, false)
```
"""
function fmi2Instantiate(libHandle::Ptr{Nothing}, instanceName::String,
    fmuType::fmuType, fmuGUID::String, fmuResourceLocation::String,
    functions::CallbackFunctions, visible::Bool=true, loggingOn::Bool=false)

    func = dlsym(libHandle, :fmi2Instantiate)

    fmi2Component = ccall(
      func,
      Ptr{Cvoid},
      (Cstring, Cint, Cstring, Cstring,
      Ref{CallbackFunctions}, Cint, Cint),
      instanceName, fmuType, fmuGUID, fmuResourceLocation,
      Ref(functions), visible, loggingOn
      )

    if fmi2Component == C_NULL
        throw(FMI2Error("Could not instantiate FMU"))
    end

    return fmi2Component
end

function fmi2Instantiate!(fmu::FMU)
    fmu.fmi2Component = fmi2Instantiate(fmu.libHandle, fmu.instanceName,
        fmu.fmuType, fmu.fmuGUID, fmu.fmuResourceLocation,
        fmu.fmiCallbackFunctions, true, true)

    return fmu
end

"""
```
    fmi2FreeInstance(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})
```
Disposes the given instance, unloads the loaded model, and frees all the
allocated memory and other resources that have been allocated by the functions
of the FMU interface. If a null pointer is provided for `fmi2Component`,
the function call is ignored (does not have an effect).
"""
function fmi2FreeInstance(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    func = dlsym(libHandle, :fmi2FreeInstance)

    ccall(
        func,
        Cvoid,
        (Ptr{Cvoid},),
        fmi2Component
        )
end

function fmi2FreeInstance(fmu::FMU)

    fmi2FreeInstance(fmu.libHandle, fmu.fmi2Component)
end

"""
```
    function fmi2SetDebugLogging(libHandle::Ptr{Nothing}, fmi2Component::Ptr{UInt}, loggingOn::Bool, [nCategories::Int], [categories::Array{String,1}])

    function fmi2SetDebugLogging(fmu::FMU, loggingOn::Bool, [nCategories::Int], [categories::Array{String,1}])
```
Enable or disable debug logging.
If optional argument `categories` is provided and `loggingOn=true` then only
debug messages according to the categories argument shall be printed via the
logger function.
`nCategories` has to be the length of `categories` an is optional as well.
"""
function fmi2SetDebugLogging(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, loggingOn::Bool)

    func = dlsym(libHandle, :fmi2SetDebugLogging)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Cint, Csize_t, Ptr{Cstring}),
        fmi2Component, loggingOn, 0, C_NULL
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetDebugLogging(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, loggingOn::Bool, nCategories::UInt,
    categories::Array{String,1})

    if length(categories) != nCategories
        throw(DimensionMismatch("nCategories=$nCategories does not match length(categories)=$(length(categories))"))
    end

    func = dlsym(libHandle, :fmi2SetDebugLogging)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Cint, Csize_t, Ptr{Cstring}),
        fmi2Component, loggingOn, nCategories, categories
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetDebugLogging(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, loggingOn::Bool, categories::Array{String,1})

    fmi2SetDebugLogging(libHandle, fmi2Component, logginOn,
        UInt(length(categories)), categories)
end

function fmi2SetDebugLogging(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, loggingOn::Bool, nCategories::Int,
    categories::Array{String,1})

    fmi2SetDebugLogging(libHandle, fmi2Component, loggingOn, UInt(nCategories), categories)
end

function fmi2SetDebugLogging(fmu::FMU, loggingOn::Bool, nCategories::Int,
    categories::Array{String,1})

    fmi2SetDebugLogging(fmu.libHandle, fmu.fmi2Component, loggingOn,
        nCategories, categories)
end

function fmi2SetDebugLogging(fmu::FMU, loggingOn::Bool, nCategories::UInt,
    categories::Array{String,1})

    fmi2SetDebugLogging(fmu.libHandle, fmu.fmi2Component, loggingOn,
        nCategories, categories)
end

function fmi2SetDebugLogging(fmu::FMU, loggingOn::Bool,
    categories::Array{String,1})

    fmi2SetDebugLogging(fmu.libHandle, fmu.fmi2Component, loggingOn,
        UInt(length(categories)), categories)
end

function fmi2SetDebugLogging(fmu::FMU, loggingOn::Bool)

    fmi2SetDebugLogging(fmu.libHandle, fmu.fmi2Component, loggingOn)
end

# ##############################################################################
# Initialization, Termination, and Resetting an FMU
# ##############################################################################

"""
```
    fmi2SetupExperiment(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, [toleranceDefined::Bool], [tolerance::Real], startTime::Real, [stopTimeDefined::Bool], [stopTime::Real])

    fmi2SetupExperiment(fmu::FMU, [toleranceDefined::Bool], [tolerance::Real], startTime::Real, [stopTimeDefined::Bool], [stopTime::Real])
```
Informs the `FMU` to setup the experiment. This function can be called after
`fmi2Instantiate` and before `fmi2EnterInitializationMode` is called.
"""
function fmi2SetupExperiment(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, toleranceDefined::Bool, tolerance::Real,
    startTime::Real, stopTimeDefined::Bool=false, stopTime::Real=startTime+1)

    func = dlsym(libHandle, :fmi2SetupExperiment)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Cint, Cdouble, Cdouble, Cint, Cdouble),
        fmi2Component, toleranceDefined, tolerance, startTime, stopTimeDefined,
        stopTime
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetupExperiment(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, startTime::Real, stopTimeDefined::Bool=false,
    stopTime::Real=startTime+1)

    return fmi2SetupExperiment(libHandle, fmi2Component, false, 1e-8,
        startTime, stopTimeDefined, stopTime)
end

function fmi2SetupExperiment(fmu::FMU, toleranceDefined::Bool, tolerance::Real,
    startTime::Real, stopTimeDefined::Bool=false, stopTime::Real=startTime+1)

    return fmi2SetupExperiment(fmu.libHandle, fmu.fmi2Component,
        toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime)
end

function fmi2SetupExperiment(fmu::FMU, startTime::Real,
    stopTimeDefined::Bool=false, stopTime::Real=startTime+1)

    return fmi2SetupExperiment(fmu.libHandle, fmu.fmi2Component,
        false, 1e-8, startTime, stopTimeDefined, stopTime)
end

"""
```
    fmi2EnterInitializationMode(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    fmi2EnterInitializationMode(fmu::FMU)
```
Informs the FMU to enter Initialization Mode. Before calling this function,
function `fmi2SetupExperiment` must be called at least once.
All variables with attribute `initial = "exact"` or `initial="approx"` can be
set with the `fmi2SetReal`, `fmi2SetInteger`, `fmi2SetBoolean` and
`fmi2SetString` functions.
"""
function fmi2EnterInitializationMode(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing})

    func = dlsym(libHandle, :fmi2EnterInitializationMode)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid},),
        fmi2Component
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2EnterInitializationMode(fmu::FMU)

    return fmi2EnterInitializationMode(fmu.libHandle, fmu.fmi2Component)
end

"""
```
    fmi2ExitInitializationMode(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    fmi2ExitInitializationMode(fmu::FMU)
```
Informs the FMU to exit Initialization Mode.
"""
function fmi2ExitInitializationMode(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing})

    func = dlsym(libHandle, :fmi2ExitInitializationMode)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid},),
        fmi2Component
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2ExitInitializationMode(fmu::FMU)

    return fmi2ExitInitializationMode(fmu.libHandle, fmu.fmi2Component)
end

"""
```
    fmi2Terminate(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    fmi2Terminate(fmu::FMU)
```
Informs the FMU that the simulation run is terminated. After calling this
function, the final values of all variables can be inquired with the
`fmi2GetReal!`, `fmi2GetInteger!`, `fmi2GetBoolean!` and `fmi2GetString!`
functions. It is not allowed to call this function after one of the FMI
functions returned with a status `fmi2Error` or `fmi2Fatal`.
"""
function fmi2Terminate(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing})

    func = dlsym(libHandle, :fmi2Terminate)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid},),
        fmi2Component
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2Terminate(fmu::FMU)

    return fmi2Terminate(fmu.libHandle, fmu.fmi2Component)
end

"""
```
    fmi2Reset(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    fmi2Reset(fmu::FMU)
```
Resets the FMU after a simulation run. The FMU goes into the same state as if
`fmi2Instantiate` would have been called. All variables have their default
values. Before starting a new run, `fmi2SetupExperiment` and
`fmi2EnterInitializationMode` have to be called.
"""
function fmi2Reset(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing})

    func = dlsym(libHandle, :fmi2Reset)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid},),
        fmi2Component
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2Reset(fmu::FMU)

    return fmi2Reset(fmu.libHandle, fmu.fmi2Component)
end

# ##############################################################################
# Getting Variable Values
# ##############################################################################

"""
```
    fmi2GetReal!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{Float64,1}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int,1}

    fmi2GetReal!(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Array{Float64,1}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int,1}
```
Get values of real variables by providing their value references.
Overwrites provided array `value` with values.
Can be called after calling `fmi2EnterInitializationMode`.
See also `fmi2GetReal`.

## Example call
Get values of real variables with value references 0, 1 and 2
```
julia> value = Array{Float64}(undef,3)
julia> fmi2GetReal!(fmu, [0, 1, 2], value)
julia> println("value: \$value")
```
"""
function fmi2GetReal!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{Float64,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2GetReal)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cdouble}),
        fmi2Component, valueReference, numberOfValueReference, value
        )

    if status != 0
        throw(fmiError(status))
    end

    return value
end

function fmi2GetReal!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{Float64,1})

    return fmi2GetReal!(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2GetReal!(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    numberOfValueReference::Int, value::Array{Float64,1})

    return fmi2GetReal!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), numberOfValueReference, value)
end

function fmi2GetReal!(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    value::Array{Float64,1})

    return fmi2GetReal!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference), value)
end

"""
```
    fmi2GetReal(fmu::FMU, valueReference::Union{Int, UInt, UInt32}) -> value
```
Get value of real variable by providing a value reference.
See also `fmi2GetReal!`.

## Example call
Get value of real variable with value reference 0
```
julia> value = fmi2GetReal(fmu, 0)
julia> println("value: \$value")
```
"""
function fmi2GetReal(fmu::FMU, valueReference::Union{Int, UInt, UInt32})

    return fmi2GetReal!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), 1, Array{Float64}(undef,1))
end

"""
```
    fmi2GetInteger!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{Int32,1}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2GetInteger!(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Array{Int32,1}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}
```
Get values of integer variables by providing their value references.
Overwrites provided array `value` with values.
Can be called after calling `fmi2EnterInitializationMode`.
See also `fmi2GetInteger`.

## Example call
Get values of integer variables with value references 0, 1 and 2
```
julia> value = Array{Int32}(undef,3)
julia> fmi2GetInteger!(fmu, [0, 1, 2], value)
julia> println("value: \$value")
```
"""
function fmi2GetInteger!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{Int32,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2GetInteger)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cint}),
        fmi2Component, valueReference, numberOfValeReference, value
        )

    if status != 0
        throw(fmiError(status))
    end

    return value
end

function fmi2GetInteger!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{Int32,1})

    return fmi2GetInteger!(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2GetInteger!(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    numberOfValueReference::Int, value::Array{Int32,1})

    return fmi2GetInteger!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), numberOfValueReference, value)
end

function fmi2GetInteger!(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    value::Array{Int32,1})

    return fmi2GetInteger!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference), value)
end

"""
```
    fmi2GetInteger(fmu::FMU, valueReference::Union{Int, UInt, UInt32}) -> value
```
Get value of integer variable by providing a value reference.
See also `fmi2GetInteger!`.

## Example call
Get value of integer variable with value reference 0
```
julia> value = fmi2GetInteger(fmu, 0)
julia> println("value: \$value")
```
"""
function fmi2GetInteger(fmu::FMU, valueReference::Union{Int, UInt, UInt32})

    return fmi2GetInteger!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), 1, Array{Int32}(undef,1))
end

"""
```
    fmi2GetBoolean!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{Int32,1}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2GetBoolean!(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Union{Array{Int32,1}, Array{Bool,1}}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}
```
Get values of boolean variables by providing their value references.
Overwrites provided array `value` with values.
Can be called after calling `fmi2EnterInitializationMode`.
See also `fmi2GetBoolean`.

## Example call
Get values of boolean variables with value references 0, 1 and 2
```
julia> value = Array{Bool}(undef,3)
julia> fmi2GetBoolean!(fmu, [0, 1, 2], value)
julia> println("value: \$value")
```
"""
function fmi2GetBoolean!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{Int32,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2GetBoolean)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cint}),
        fmi2Component, valueReference, numberOfValueReference, value
        )

    if status != 0
        throw(fmiError(status))
    end

    return value
end

function fmi2GetBoolean!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{Int32,1})

    return fmi2GetBoolean!(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2GetBoolean!(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    numberOfValueReference::Int, value::Union{Array{Int32,1}, Array{Bool,1}})

    return fmi2GetBoolean!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), numberOfValueReference, value)
end

function fmi2GetBoolean!(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    value::Union{Array{Int32,1}, Array{Bool,1}})

    return fmi2GetBoolean!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference), value)
end

function fmi2GetBoolean!(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    value::Union{Array{Int32,1}, Array{Bool,1}})

    return fmi2GetBoolean!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference),
        convert(Array{Int32,1}, value))
end

"""
```
    fmi2GetBoolean(fmu::FMU, valueReference::Union{Int, UInt, UInt32}) -> value
```
Get value of boolean variable by providing a value reference.
See also `fmi2GetBool!`.

## Example call
Get value of boolean variable with value reference 0
```
julia> value = fmi2GetBoolean(fmu, 0)
julia> println("value: \$value")
```
"""
function fmi2GetBoolean(fmu::FMU, valueReference::Union{Int, UInt, UInt32})

    return fmi2GetBoolean!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), 1, Array{Int32}(undef,1))
end

"""
```
    fmi2GetString!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{String,1}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2GetString!(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Array{String,1}) -> value
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}
```
Get values of string variables by providing their value references.
Overwrites provided array `value` with values. Actually I have no clue whats happening...
Can be called after calling `fmi2EnterInitializationMode`.
See also `fmi2GetString`.

## Example call
Get values of string variables with value references 0, 1 and 2
```
julia> value = Array{String}(undef,3)
julia> fmi2GetString!(fmu, [0, 1, 2], value)
julia> println("value: \$value")
```
"""
function fmi2GetString!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{String,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2GetString)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cstring}),
        fmi2Component, valueReference, numberOfValeReference, value
        )

    if status != 0
        throw(fmiError(status))
    end

    # Return copy of string array, since the FMU is allowed to free the
    # allocated memory at any time
    return copy(value)
end

function fmi2GetString!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{String,1})

    return fmi2GetString!(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2GetString!(fmu::FMU, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{String,1})

    return fmi2GetString!(fmu.libHandle, fmu.fmi2Component, valueReference,
        numberOfValueReference, value)
end

function fmi2GetString!(fmu::FMU, valueReference::Array{UInt32,1},
    value::Array{String,1})

    return fmi2GetString!(fmu.libHandle, fmu.fmi2Component, valueReference,
        length(valueReference), value)
end

"""
```
    fmi2GetString(fmu::FMU, valueReference::Union{Int, UInt, UInt32}) -> value
```
Get value of string variable by providing a value reference.
See also `fmi2GetString!`.

## Example call
Get value of string variable with value reference 0
```
julia> value = fmi2GetString(fmu, 0)
julia> println("value: \$value")
```
"""
function fmi2GetString(fmu::FMU, valueReference::Union{Int, UInt, UInt32})

    return fmi2GetString!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), 1, Array{String}(undef,1))
end

# ##############################################################################
# Setting Variable Values
# ##############################################################################

"""
```
    fmi2SetReal(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{Float64,1})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int,1}

    fmi2SetReal(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Array{Float64,1})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int,1}

    fmi2SetReal(fmu::FMU, valueReference::T, value::Float64)
      where T is one of UInt32, UInt, Int
```
Set values of real variables by providing their value references and values.
Can be called after calling `fmi2EnterInitializationMode`.

## Example calls
Set value of real variable with value reference 0
```
julia> fmi2SetReal(fmu, 0, -42.1337)
```
Set values of real variables with value references 0, 1 and 2
```
julia> fmi2SetReal(fmu, [0, 1, 2], [1.2,3.4,-1.0])
```
"""
function fmi2SetReal(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{Float64,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2SetReal)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cdouble}),
        fmi2Component, valueReference, numberOfValueReference, value
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetReal(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{Float64,1})

    fmi2SetReal(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2SetReal(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    numberOfValueReference::Int, value::Array{Float64,1})

    fmi2SetReal(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), numberOfValueReference, value)
end

function fmi2SetReal(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    value::Array{Float64,1})

    fmi2SetReal(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference), value)
end

function fmi2SetReal(fmu::FMU, valueReference::Union{UInt32, UInt64, Int},
    value::Float64)

    fmi2SetReal(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), length(valueReference), [value])
end

"""
```
    fmi2SetInteger(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{Int32,1})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2SetInteger(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Array{Int32,1})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2SetInteger(fmu::FMU, valueReference::T, value::Int32)
      where T is one of UInt32, UInt, Int
```
Set values of integer variables by providing their value references.
Can be called after calling `fmi2EnterInitializationMode`.

## Example calls
Set value of integer variable with value reference 0
```
julia> fmi2SetInteger(fmu, 0, 42)
```
Set values of integer variables with value references 0, 1 and 2
```
julia> fmi2SetInteger(fmu, [0, 1, 2], [-1, 3, 27])
```
"""
function fmi2SetInteger(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{Int32,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2SetInteger)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cint}),
        fmi2Component, valueReference, numberOfValeReference, value
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetInteger(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{Int32,1})

    fmi2SetInteger(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2SetInteger(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    numberOfValueReference::Int, value::Array{Int32,1})

    fmi2SetInteger(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), numberOfValueReference, value)
end

function fmi2SetInteger(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    value::Array{Int32,1})

    fmi2GetInteger!(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference), value)
end

function fmi2SetInteger(fmu::FMU, valueReference::Union{UInt32, UInt64, Int},
    value::Int32)

    fmi2SetInteger(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), length(valueReference), [value])
end

"""
```
    fmi2SetBoolean(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{Int32,1})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2SetBoolean(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Union{Array{Int32,1}, Array{Bool,1}})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2SetBoolean(fmu::FMU, valueReference::T, value::Int32)
      where T is one of UInt32, UInt, Int
```
Set values of boolean variables by providing their value references.
Can be called after calling `fmi2EnterInitializationMode`.

## Example calls
Set value of boolean variable with value reference 0
```
julia> fmi2SetBoolean(fmu, 0, true)
```
Set values of boolean variables with value references 0, 1 and 2
```
julia> fmi2SetBoolean(fmu, [0, 1, 2], [true, false, false])
```
"""
function fmi2SetBoolean(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{Int32,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2SetBoolean)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cint}),
        fmi2Component, valueReference, numberOfValeReference, value
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetBoolean(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{Int32,1})

    fmi2SetBoolean(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2SetBoolean(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    numberOfValueReference::Int, value::Array{Int32,1})

    fmiSGetBoolean(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), numberOfValueReference, value)
end

function fmiSGetBoolean(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Int,1}},
    value::Array{Int32,1})

    fmi2SetBoolean(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference), value)
end

function fmi2SetBoolean(fmu::FMU, valueReference::Union{Array{UInt32,1}, Array{UInt64,1}, Array{Bool,1}},
    value::Array{Int32,1})

    fmi2SetBoolean(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},valueReference), length(valueReference),
        convert(Array{Int32,1}, value))
end

function fmi2SetBoolean(fmu::FMU, valueReference::Union{Int, UInt, UInt32}, value::Int32)

    fmi2SetBoolean(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), 1, Array{Int32}(value))
end

"""
```
    fmi2SetString(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, valueReference::T, [numberOfValueReference::Int], value::Array{String,1})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2SetString(fmu::FMU, valueReference::T, [numberOfValueReference::Int], value::Array{String,1})
      where T is one of Array{UInt32,1}, Array{UInt,1}, Array{Int32,1}

    fmi2SetString(fmu::FMU, valueReference::T, value::String)
      where T is one of UInt32, UInt, Int
```
Set values of string variables by providing their value references.
Can be called after calling `fmi2EnterInitializationMode`.

## Example calls
Set value of string variable with value reference 0
```
julia> fmi2SetBoolean(fmu, 0, \"foo\")
```
Set values of string variables with value references 0, 1 and 2
```
julia> fmi2SetString(fmu, [0, 1, 2], [\"Hello\", \"FMU\", \"Julia\"])
```
"""
function fmi2SetString(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{String,1})

    if size(valueReference) != size(value)
        throw(DimensionMismatch("Arrays valueReference and value are not the same size."))
    elseif (length(valueReference) != numberOfValueReference)
        throw(DimensionMismatch("Wrong numberOfValueReference.
            Expected $(length(valueReference)) but got $numberOfValueReference."))
    end

    func = dlsym(libHandle, :fmi2SetString)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cuint}, Csize_t, Ref{Cstring}),
        fmi2Component, valueReference, numberOfValeReference, value
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetString(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, valueReference::Array{UInt32,1},
    value::Array{String,1})

    fmi2SetString(libHandle, fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2SetString(fmu::FMU, valueReference::Array{UInt32,1},
    numberOfValueReference::Int, value::Array{String,1})

    fmi2SetString(fmu.libHandle, fmu.fmi2Component, valueReference,
        numberOfValueReference, value)
end

function fmi2SetString(fmu::FMU, valueReference::Array{UInt32,1},
    value::Array{String,1})

    fmi2SetString(fmu.libHandle, fmu.fmi2Component, valueReference,
        length(valueReference), value)
end

function fmi2SetString(fmu::FMU, valueReference::Union{Int, UInt, UInt32},
    value::String)

    fmi2SetString(fmu.libHandle, fmu.fmi2Component,
        convert(Array{UInt32,1},[valueReference]), 1, Array{String}(value))
end

# ##############################################################################
# Getting and Setting the Complete FMU State
# ##############################################################################

"""
Function `fmi2GetFMUstate` not implemeted yet.
Probably not very usefull in Julia context for ModelExchange.
"""
function fmi2GetFMUstate(fmu::FMU)

    #fmi2Status fmi2GetFMUstate (fmi2Component c, fmi2FMUstate* FMUstate);

    error("FMI function not supportet")
end

"""
Function `fmi2SetFMUstate` not implemeted yet.
Probably not very usefull in Julia context for ModelExchange.
"""
function fmi2SetFMUstate(fmu::FMU)

    #fmi2Status fmi2SetFMUstate (fmi2Component c, fmi2FMUstate FMUstate);

    error("FMI function not supportet")
end

"""
Function `fmi2FreeFMUstate` not implemeted yet.
Probably not very usefull in Julia context for ModelExchange.
"""
function fmi2FreeFMUstate(fmu::FMU)

    #fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate);

    error("FMI function not supportet")
end

"""
Function `fmi2SerializedFMUstateSize` not implemeted yet.
Probably not very usefull in Julia context for ModelExchange.
"""
function fmi2SerializedFMUstateSize(fmu::FMU)

    #fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size);

    error("FMI function not supportet")
end

"""
Function `fmi2SerializeFMUstate` not implemeted yet.
Probably not very usefull in Julia context for ModelExchange.
"""
function fmi2SerializeFMUstate(fmu::FMU)

    #fmi2Status fmi2SerializeFMUstate (fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size);

    error("FMI function not supportet")
end

"""
Function `fmi2DeSerializeFMUstate` not implemeted yet.
Probably not very usefull in Julia context for ModelExchange.
"""
function fmi2DeSerializeFMUstate(fmu::FMU)

    #fmi2Status fmi2DeSerializeFMUstate (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate);

    error("FMI function not supportet")
end

# ##############################################################################
# Getting Partial Derivatives
# ##############################################################################

"""
Function `fmi2GetDirectionalDerivative` not implemeted yet.
Probably not very usefull in Julia context for ModelExchange.
"""
function fmi2GetDirectionalDerivative(fmu::FMU)

    #fmi2Status fmi2GetDirectionalDerivative(fmi2Component c,
    #    const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
    #    const fmi2ValueReference vKnown_ref[] , size_t nKnown,
    #    const fmi2Real dvKnown[],
    #    fmi2Real dvUnknown[])

    error("FMI function not supportet")
end

# ##############################################################################
# Providing Independent Variables and Re-initialization of Caching
# ##############################################################################

"""
```
    fmi2SetTime(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, time::Float64)

    fmi2SetTime(fmu::FMU, time::Float64)
```
Set a new time instant and re-initialize caching of variables that depend on
time, provided the newly provided time value is different to the previously set
time value
"""
function fmi2SetTime(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing},
    time::Float64)

    func = dlsym(libHandle, :fmi2SetTime)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Cdouble),
        fmi2Component, time
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetTime(fmu::FMU, time::Float64)
    fmi2SetTime(fmu.libHandle, fmu.fmi2Component, time)
end

"""
```
    fmi2SetContinuousStates(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, states::Array{Float64,1}, [n_states::Int])

    fmi2SetContinuousStates(fmu::FMU, states::Array{Float64,1}, [n_states::Int])
```
Set a new (continuous) state vector and re-initialize caching of variables that
depend on the states. Argument `n_states` is the length of vector `states`
and is provided for checking purposes.
"""
function fmi2SetContinuousStates(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, states::Array{Float64,1}, n_states::Int)

    if length(states) != n_states
        throw(DimensionMismatch("Array states has not length $(length(states)).
            Expected $n_states."))
    end

    func = dlsym(libHandle, :fmi2SetContinuousStates)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cdouble}, Csize_t),
        fmi2Component, states, n_states
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2SetContinuousStates(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, states::Array{Float64,1})

    fmi2SetContinuousStates(libHandle, fmi2Component, states, length(states))
end

function fmi2SetContinuousStates(fmu::FMU, states::Array{Float64,1},
    n_states::Int)

    fmi2SetContinuousStates(fmu.libHandle, fmu.fmi2Component, states, n_states)
end

function fmi2SetContinuousStates(fmu::FMU, states::Array{Float64,1})

    fmi2SetContinuousStates(fmu.libHandle, fmu.fmi2Component, states,
        length(states))
end

"""
```
    fmi2EnterEventMode(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    fmi2EnterEventMode(fmu::FMU)
```
The model enters Event Mode from the Continuous-Time Mode.
"""
function fmi2EnterEventMode(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    func = dlsym(libHandle, :fmi2EnterEventMode)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid},),
        fmi2Component,
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2EnterEventMode(fmu::FMU)

    fmi2EnterEventMode(fmu.libHandle, fmu.fmi2Component)
end

"""
```
    fmi2NewDiscreteStates!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, fmi2EventInfo::EventInfo) -> fmi2EventInfo

    fmi2NewDiscreteStates!(fmu::FMU) -> fmi2EventInfo
```
The FMU is in Event Mode and the super dense time is incremented by this call.
"""
function fmi2NewDiscreteStates!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, fmi2EventInfo::EventInfo)

    func = dlsym(libHandle, :fmi2NewDiscreteStates)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{EventInfo}),
        fmi2Component, fmi2EventInfo
        )

    if status != 0
        throw(fmiError(status))
    end

    return fmi2EventInfo
end

function fmi2NewDiscreteStates!(fmu::FMU)

    return fmi2NewDiscreteStates!(fmu.libHandle, fmu.fmi2Component, fmu.eventInfo)
end

"""
```
    fmi2EnterContinuousTimeMode(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing})

    fmi2EnterContinuousTimeMode(fmu::FMU)
```
The model enters Continuous-Time Mode and all discrete-time equations become
inactive and all relations are "frozen".
This function has to be called when changing from Event Mode into
Continuous-Time Mode.
"""
function fmi2EnterContinuousTimeMode(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing})

    func = dlsym(libHandle, :fmi2EnterContinuousTimeMode)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid},),
        fmi2Component
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2EnterContinuousTimeMode(fmu::FMU)

    fmu.modelState = modelContinuousTimeMode

    fmi2EnterContinuousTimeMode(fmu.libHandle, fmu.fmi2Component)
end

"""
```
    fmi2CompletedIntegratorStep(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, noSetFMUStatePriorToCurrentPoint::Bool) -> (enterEventMode, terminateSimulation)

    fmi2CompletedIntegratorStep(fmu::FMU, noSetFMUStatePriorToCurrentPoint::Bool) -> (enterEventMode, terminateSimulation)
```
This function must be called by the environment after every completed step of
the integrator provided the capability flag
`completedIntegratorStepNotNeeded = false`.
"""
function fmi2CompletedIntegratorStep(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, noSetFMUStatePriorToCurrentPoint::Bool)

    func = dlsym(libHandle, :fmi2CompletedIntegratorStep)

    enterEventModeOut = Ref(UInt32(true))
    terminateSimulationOut = Ref(UInt32(true))

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Cuint, Ref{Cuint}, Ref{Cuint}),
        fmi2Component, noSetFMUStatePriorToCurrentPoint, enterEventModeOut,
        terminateSimulationOut
        )

    if status != 0
        throw(fmiError(status))
    end

    return (Bool(enterEventModeOut[]), Bool(terminateSimulationOut[]))
end

function fmi2CompletedIntegratorStep(fmu::FMU,
    noSetFMUStatePriorToCurrentPoint::Bool)

    return fmi2CompletedIntegratorStep(fmu.libHandle, fmu.fmi2Component,
        noSetFMUStatePriorToCurrentPoint)
end

"""
```
    fmi2GetDerivatives!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, derivatives::Array{Float64,1}, [numberOfDerivatives::Int])

    fmi2GetDerivatives!(fmu::FMU, derivatives::Array{Float64,1}, [numberOfDerivatives::Int])
```
Compute state derivatives at the current time instant and for the current
states.
"""
function fmi2GetDerivatives!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, derivatives::Array{Float64,1},
    numberOfDerivatives::Int)

    if (length(derivatives) != numberOfDerivatives)
        throw(DimensionMismatch("Wrong numberOfDerivatives.
            Expected $(length(derivatives)) but got $numberOfDerivatives."))
    end

    func = dlsym(libHandle, :fmi2GetDerivatives)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cdouble}, Csize_t,),
        fmi2Component, derivatives, numberOfDerivatives
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2GetDerivatives!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, derivatives::Array{Float64,1})

    fmi2GetDerivatives!(libHandle, fmi2Component, derivatives,
        length(derivatives))
end

function fmi2GetDerivatives!(fmu::FMU, derivatives::Array{Float64,1},
    numberOfDerivatives::Int)

    fmi2GetDerivatives!(fmu.libHandle, fmu.fmi2Component, derivatives,
        numberOfDerivatives)
end

function fmi2GetDerivatives!(fmu::FMU, derivatives::Array{Float64,1})

    fmi2GetDerivatives!(fmu.libHandle, fmu.fmi2Component, derivatives,
        length(derivatives))
end

"""
```
    fmi2GetEventIndicators!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, eventIndicators::Array{Float64,1}, [numberOfEventIndiactors::Int])

    fmi2GetEventIndicators!(fmu::FMU, eventIndicators::Array{Float64,1}, [numberOfEventIndiactors::Int])
```
Compute event indicators at the current time instant and for the current
states.
"""
function fmi2GetEventIndicators!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, eventIndicators::Array{Float64,1},
    numberOfEventIndiactors::Int)

    if (length(eventIndicators) != numberOfEventIndiactors)
        throw(DimensionMismatch("Wrong numberOfEventIndiactors.
            Expected $(length(eventIndicators)) but got $numberOfEventIndiactors."))
    end

    func = dlsym(libHandle, :fmi2GetEventIndicators)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cdouble}, Csize_t,),
        fmi2Component, eventIndicators, numberOfEventIndiactors
        )

    if status != 0
        throw(fmiError(status))
    end
end

function fmi2GetEventIndicators!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, eventIndicators::Array{Float64,1})

    fmi2GetEventIndicators!(libHandle, fmi2Component, eventIndicators,
        length(eventIndicators))
end

function fmi2GetEventIndicators!(fmu::FMU, eventIndicators::Array{Float64,1},
    numberOfEventIndiactors::Int)

    fmi2GetEventIndicators!(fmu.libHandle, fmu.fmi2Component, eventIndicators,
        numberOfEventIndiactors)
end

function fmi2GetEventIndicators!(fmu::FMU, eventIndicators::Array{Float64,1})

    fmi2GetEventIndicators!(fmu.libHandle, fmu.fmi2Component, eventIndicators,
        length(eventIndicators))
end

"""
```
    fmi2GetContinuousStates!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, states::Array{Float64,1}, [n_states::Int]) -> states

    fmi2GetContinuousStates!(fmu::FMU, states::Array{Float64,1}, [n_states::Int]) -> states
```
Return the new (continuous) state vector `states`. Argument `n_states` is the
length of vector `states`and is provided for checking purposes.
This function has to be called directly after calling function
`fmi2EnterContinuousTimeMode` if it returns with
`eventInfo->valuesOfContinuousStatesChanged = true`.
"""
function fmi2GetContinuousStates!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, states::Array{Float64,1}, n_states::Int)

    if length(states) != n_states
        throw(DimensionMismatch("Wrong n_states.
            Expected $(length(states)) but got $n_states."))
    end

    func = dlsym(libHandle, :fmi2GetContinuousStates)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cdouble}, Csize_t),
        fmi2Component, states, n_states
        )

    if status != 0
        throw(fmiError(status))
    end

    return states
end

function fmi2GetContinuousStates!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, states::Array{Float64,1})

    return fmi2GetContinuousStates!(libHandle, fmi2Component, states, length(states))
end

function fmi2GetContinuousStates!(fmu::FMU, states::Array{Float64,1},
    n_states::Int)

    return fmi2GetContinuousStates!(fmu.libHandle, fmu.fmi2Component, states, n_states)
end

function fmi2GetContinuousStates!(fmu::FMU, states::Array{Float64,1})

    return fmi2GetContinuousStates!(fmu.libHandle, fmu.fmi2Component, states,
        length(states))
end

"""
```
    fmi2GetNominalsOfContinuousStates!(libHandle::Ptr{Nothing}, fmi2Component::Ptr{Nothing}, x_nominal::Array{Float64,1}, [n_nominal::Int]) -> x_nominal

    fmi2GetNominalsOfContinuousStates!(fmu::FMU, x_nominal::Array{Float64,1}, [n_nominal::Int]) -> x_nominal
```
Return the nominal values of the continuous states. This function should always
be called after calling function `fmi2NewDiscreteStates` if it returns with
`eventInfo->nominalsOfContinuousStatesChanged = true` since then the nominal
values of the continuous states have changed.
"""
function fmi2GetNominalsOfContinuousStates!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, x_nominal::Array{Float64,1}, n_nominal::Int)

    if length(x_nominal) != n_nominal
        throw(DimensionMismatch("Wrong n_nominal.
            Expected $(length(x_nominal)) but got $n_nominal."))
    end

    func = dlsym(libHandle, :fmi2GetNominalsOfContinuousStates)

    status = ccall(
        func,
        Cuint,
        (Ptr{Cvoid}, Ref{Cdouble}, Csize_t),
        fmi2Component, x_nominal, n_nominal
        )

    if status != 0
        throw(fmiError(status))
    end

    return x_nominal
end

function fmi2GetNominalsOfContinuousStates!(libHandle::Ptr{Nothing},
    fmi2Component::Ptr{Nothing}, x_nominal::Array{Float64,1}, n_nominal::Int)

    return fmi2GetNominalsOfContinuousStates!(libHandle, fmi2Component,
        x_nominal, length(x_nominal))
end

function fmi2GetNominalsOfContinuousStates!(fmu::FMU,
    x_nominal::Array{Float64,1}, n_nominal::Int)

    return fmi2GetNominalsOfContinuousStates!(fmu.libHandle, fmu.fmi2Component,
        x_nominal, n_nominal)
end

function fmi2GetNominalsOfContinuousStates!(fmu::FMU,
    x_nominal::Array{Float64,1})

    return fmi2GetNominalsOfContinuousStates!(fmu.libHandle, fmu.fmi2Component,
        x_nominal, length(x_nominal))
end

max_stars_repo_name: cuihantao/JuliaFMI

max_issues_repo_name: cuihantao/JuliaFMI

max_forks_repo_name: cuihantao/JuliaFMI


text:
const DVISVGM_PATH = Ref{String}()

function dvisvg()
    if !isassigned(DVISVGM_PATH)
       DVISVGM_PATH[] = readchomp(`which dvisvgm`)
    end
    return DVISVGM_PATH[]
end

function compile_latex(
        document::AbstractString;
        tex_engine = `lualatex`,
        options = `-halt-on-error`,
        format = "dvi"
    )
    return mktempdir() do dir

        # dir=mktempdir()
        # Begin by compiling the latex in a temp directory
        # Unfortunately for us, Luatex does not like to compile
        # straight to stdout; it really wants a filename.
        # We make a temporary directory for it to output to.
        latex = open(`$tex_engine $options -output-directory=$dir -output-format=$format -jobname=temp`, "r+")
        print(latex, document) # print the TeX document to stdin
        close(latex.in)      # close the file descriptor to let LaTeX know we're done
        suc = success(latex)
        dircontents = joinpath.(dir, readdir(dir))

        !suc && (println(read(joinpath(dir, "temp.log"), String)))

        # We want to keep file writes to a minimum.  Everything should stay in memory.
        # Therefore, we exit the directory at this point, so that all auxiliary files
        # can be deleted.
        return read(joinpath(dir, "temp.$format"))

    end
end

latex2dvi(args...; kwargs...) = compile_latex(args...; format = "dvi", kwargs...)
latex2pdf(args...; kwargs...) = compile_latex(args...; format = "pdf", kwargs...)

function dvi2svg(
        dvi::Vector{UInt8};
        bbox = .2, # minimal bounding box
        options = ``
    )
    # dvisvgm will allow us to convert the DVI file into an SVG which
    # can be rendered by Rsvg.  In this case, we are able to provide
    # dvisvgm a DVI file from stdin, and receive a SVG string from
    # stdout.  This greatly simplifies the pipeline, and anyone with
    # a working TeX installation should have these utilities available.
    dvisvgm = open(`$(dvisvg()) --bbox=$bbox $options --no-fonts --stdin --stdout`, "r+")

    write(dvisvgm, dvi)

    close(dvisvgm.in)

    return read(dvisvgm.out, String) # read the SVG in as a String
end

function pdf2svg(pdf::Vector{UInt8})
    pdftocairo = open(`pdftocairo -svg - -`, "r+")

    write(pdftocairo, pdf)

    close(pdftocairo.in)

    return read(pdftocairo.out, String)
end

# function dvi2png(dvi::Vector{UInt8}; dpi = 72.0, libgs = nothing)
#
#     # dvisvgm will allow us to convert the DVI file into an SVG which
#     # can be rendered by Rsvg.  In this case, we are able to provide
#     # dvisvgm a DVI file from stdin, and receive a SVG string from
#     # stdout.  This greatly simplifies the pipeline, and anyone with
#     # a working TeX installation should have these utilities available.
#     dvipng = open(`dvipng --bbox=$bbox $options --no-fonts  --stdin --stdout `, "r+")
#
#     write(dvipng, dvi)
#
#     close(dvipng.in)
#
#     return read(dvipng.out, String) # read the SVG in as a String
# end

function svg2img(svg::String, dpi = 72.0)

    # First, we instantiate an Rsvg handle, which holds a parsed representation of
    # the SVG.  Then, we set its DPI to the provided DPI (usually, 300 is good).
    handle = Rsvg.handle_new_from_data(svg)
    Rsvg.handle_set_dpi(handle, Float64(dpi))

    # We can find the final dimensions (in pixel units) of the Rsvg image.
    # Then, it's possible to store the image in a native Julia array,
    # which simplifies the process of rendering.
    d = Rsvg.handle_get_dimensions(handle)

    # NOTE
    # I did not check if this needs to be filled, but rsvg2img needs it...
    w, h = d.width, d.height
    img = fill(Colors.ARGB32(1,1,1,0), w, h)

    # Cairo allows you to use a Matrix of ARGB32, which simplifies rendering.
    cs = Cairo.CairoImageSurface(img)
    c = Cairo.CairoContext(cs)

    # Render the parsed SVG to a Cairo context
    Rsvg.handle_render_cairo(c, handle)

    # The image is rendered transposed, so we need to flip it.
    return rotr90(permutedims(img))
end

function rsvg2img(handle::Rsvg.RsvgHandle, dpi = 72.0)
    Rsvg.handle_set_dpi(handle, Float64(dpi))

    # We can find the final dimensions (in pixel units) of the Rsvg image.
    # Then, it's possible to store the image in a native Julia array,
    # which simplifies the process of rendering.
    d = Rsvg.handle_get_dimensions(handle)

    # Cairo does not draw "empty" pixels, so we need to fill here
    w, h = d.width, d.height
    img = fill(Colors.ARGB32(1,1,1,0), w, h)

    # Cairo allows you to use a Matrix of ARGB32, which simplifies rendering.
    cs = Cairo.CairoImageSurface(img)
    c = Cairo.CairoContext(cs)

    # Render the parsed SVG to a Cairo context
    Rsvg.handle_render_cairo(c, handle)

    # The image is rendered transposed, so we need to flip it.
    return rotr90(permutedims(img))
end

function svg2rsvg(svg::String, dpi = 72.0)
    handle = Rsvg.handle_new_from_data(svg)
    Rsvg.handle_set_dpi(handle, Float64(dpi))
    return handle
end

function rsvg2recordsurf(handle::Rsvg.RsvgHandle)
    surf = Cairo.CairoRecordingSurface()
    ctx  = Cairo.CairoContext(surf)
    Rsvg.handle_render_cairo(ctx, handle)
    return (surf, ctx)
end

function render_surface(ctx::CairoContext, surf)
    Cairo.save(ctx)

    Cairo.set_source(ctx, surf, 0.0, 0.0)

    Cairo.paint(ctx)

    Cairo.restore(ctx)
    return
end

ext: jl


text:
## Loading modules
using Distributed
using DataFrames
using CSV
addprocs(6)

## Settin up directories

@everywhere dir = @__DIR__ ;
datadir=dir*"/data/oildata.csv" ;
resultsdir=dir*"/results/"

## Load modules in parallel
@everywhere include(dir*"/modules/MyModules.jl")

@everywhere begin
    using .MyModules
    using Random
    using SharedArrays
    ## Setting seed
    Random.seed!(66636)
end

@everywhere Param=Par(nfast=1000)

## Big 6

pt, qt = load_data_select(datadir)
set="Big6"

# Run tests

# Run base case
include("Main.jl")

# A) Test alternative transition kernel

include("RP_Cour_ME_sem_algo.jl")

# B) Test alternative acceptance rule with current
# transition kernel

# include("RP_Cour_ME_sem_alt.jl")

# C) Annual test

include("Main_annual.jl")

## OPEC

OPEC=[:saudiarabia, :iran, :venezuela, :uae, :nigeria, :kuwait]
pt, qt = load_data_select(datadir, select=OPEC)
set="OPEC"

# Run tests

# Run base case
include("Main.jl")
GC.gc()
# A) Test alternative transition kernel
include("RP_Cour_ME_sem_algo.jl")
GC.gc()
# C) Annual test
include("Main_annual.jl")
GC.gc()
## Non-OPEC
NonOPEC=[:unitedstates, :china, :mexico, :uk, :canada, :norway]
pt, qt = load_data_select(datadir, select=NonOPEC)
set="NonOPEC"

# Run tests

# Run base case
include("Main.jl")
GC.gc()
# A) Test alternative transition kernel
include("RP_Cour_ME_sem_algo.jl")
GC.gc()
# C) Annual test
include("Main_annual.jl")
GC.gc()
## OPEC no Saudia Arabia
OPEC_NSA=[:iran, :venezuela, :uae, :nigeria, :kuwait, :iraq]
pt, qt = load_data_select(datadir, select=OPEC_NSA)
set="OPEC_NSA"

# Run tests

# Run base case
include("Main.jl")
GC.gc()
# A) Test alternative transition kernel
include("RP_Cour_ME_sem_algo.jl")
GC.gc()
# C) Annual test
include("Main_annual.jl")
GC.gc()

max_stars_repo_name: hans-mtz/SCR

max_issues_repo_name: hans-mtz/SCR

max_forks_repo_name: hans-mtz/SCR


text:
@timedtestset "abstract_data_set" begin
    rng, N, D = MersenneTwister(123456), 10, 2
    x, X = randn(rng, N), randn(rng, D, N)

    # Test BlockDataSet.
    @timedtestset "BlockData" begin
        DX = ColVecs(X)
        DxX = BlockData([x, DX])
        @test size(DxX) == (2N,)
        @test length(DxX) == 2N
        @test DxX == DxX
        @test DxX == BlockData([x, DX])
        @test length([x for x in DxX]) == 2N
        @test getindex(DxX, 1) === x[1]
        @test getindex(DxX, 2) === x[2]
        @test getindex(DxX, N) === x[N]
        @test getindex(DxX, N + 1) == DX[1]
        @test view(DxX, 2, 1) == view(DX, 1)
        @test view(DxX, 2, N) == view(DX, N)
        @test eachindex(DxX) isa BlockVector
        @test eachindex(DxX) == mortar([1:N, N+1:2N], [N, N])

        # Test iteration.
        @test [x for x in DxX][1] == x[1]
        @test [x for x in DxX][N] == x[end]
        @test [x for x in DxX][N + 1] == DX[1]
        @test [x for x in DxX][end] == DX[end]

        # Test that identically typed arrays yield the appropriate element type.
        @test eltype(BlockData([randn(5), randn(4)])) == Float64
        @test eltype(DxX) == Any
        @test eltype(BlockData([DX, DX])) <: AbstractVector{Float64}
        @test eltype(BlockData([eachindex(DX), eachindex(DX)])) == Int

        # Convenience constructor.
        @test BlockData(x, DX) == DxX
    end
end


text:
module SolverTests
using Base.Test;
using FactCheck;
using ValidatedNumerics;
using IntervalLinearEquations;

function interval_approx_eq(a_interval :: Interval{Float64}, b_interval :: Interval{Float64})
    isapprox(a_interval.lo, b_interval.lo) &&
    isapprox(a_interval.hi, b_interval.hi)
end

facts("Solve 2x2 system with number matrix") do
    bVector = [
        @interval(-2.0, 2.0); @interval(-2.0, 2.0);
    ] :: Array{Interval{Float64}};
    aMatrix = [
        @interval(2, 4) @interval(-2, 1);
        @interval(-1, 2) @interval(2, 4);
    ] :: Array{Interval{Float64}};

    result = IntervalLinearEquations.solve("G", eye(aMatrix), bVector, 0.1, 10, 1.0)
    @fact result --> bVector
end

facts("Solve 2x2 system with random matrix") do
    xVector = [
        @interval(-1.0, 2.0); @interval(-1.0, 2.0);
    ] :: Array{Interval{Float64}};
    aMatrix = [
        @interval(-2, 4) @interval(-3, 0);
        @interval(-1, 0) @interval(2, 5);
    ] :: Array{Interval{Float64}};
    bVector = aMatrix * xVector

    solution = IntervalLinearEquations.solve("G", aMatrix, bVector, 0.1, 10, 1.0)
    bFromSolution = aMatrix * solution
    @fact all(map(interval_approx_eq, bVector, bFromSolution)) --> true
    @fact all(map(interval_approx_eq, solution, xVector)) --> true
end

facts("Solve 2x2 system with interval matrix") do
    bVector = [
        @interval(-2.0, 2.0); @interval(-2.0, 2.0);
    ] :: Array{Interval{Float64}};
    aMatrix = [
        @interval(2, 4) @interval(-2, 1);
        @interval(-1, 2) @interval(2, 4);
    ] :: Array{Interval{Float64}};
    preciseX = [
        @interval(-0.33333333333333337, 0.33333333333333337);
        @interval(-0.33333333333333337, 0.33333333333333337);
    ] :: Array{Interval{Float64}};

    solution = IntervalLinearEquations.solve("G", aMatrix, bVector, 0.1, 10, 1.0)
    bFromSolution = aMatrix * solution
    @fact all(map(interval_approx_eq, bVector, bFromSolution)) --> true
    @fact all(map(interval_approx_eq, solution, preciseX)) --> true
end

end


text:
"""
    struct SolverSet{
        TS<:AbstractSetup,
        TP<:AbstractPhysicalSpace,
        TV<:Union{AbstractVelocitySpace,Nothing},
        TG<:AbstractProperty,
        TI<:Union{AbstractCondition,Nothing},
        TO<:AbstractString,
    } <: AbstractSolverSet
        # setup
        set::TS
        # physical space
        pSpace::TP
        # velocity space
        vSpace::TV
        # gas property
        gas::TG
        # initial and boundary condition
        ib::TI
        # file system
        outputFolder::TO
    end

Structure of solver setup

"""
struct SolverSet{
    TS<:AbstractSetup,
    TP<:AbstractPhysicalSpace,
    TV<:Union{AbstractVelocitySpace,Nothing},
    TG<:AbstractProperty,
    TI<:Union{AbstractCondition,Nothing},
    TO<:AbstractString,
} <: AbstractSolverSet
    # setup
    set::TS
    # physical space
    pSpace::TP
    ps::TP
    # velocity space
    vSpace::TV
    vs::TV
    # gas property
    gas::TG
    # initial and boundary condition
    ib::TI
    # file system
    outputFolder::TO
end

function SolverSet(
    SET::AbstractSetup,
    PS::AbstractPhysicalSpace,
    VS::Union{AbstractVelocitySpace,Nothing},
    GAS::AbstractProperty,
    IB::Union{AbstractCondition,Nothing},
    DIR::AbstractString = @__DIR__,
)
    return SolverSet{typeof(SET),typeof(PS),typeof(VS),typeof(GAS),typeof(IB),typeof(DIR)}(
        SET,
        PS,
        PS,
        VS,
        VS,
        GAS,
        IB,
        DIR,
    )
end

function SolverSet(configfilename::T) where {T<:AbstractString}
    # generate variables from configuration file
    dict = read_cfg(configfilename)

    # setup
    set = set_setup(dict)

    # physical space
    ps = set_geometry(dict)

    # velocity space
    vs = set_velocity(dict)

    # gas property
    gas = set_property(dict)

    # initial & boundary condition
    ib = set_ib(dict, set, ps, vs, gas)

    # create working directory
    identifier = string(Dates.now(), "/")
    #outputFolder = string("../out/", replace(identifier, ":"=>"."))
    outputFolder = replace(identifier, ":" => ".")
    mkdir(outputFolder)
    mkdir(string(outputFolder, "data/"))
    cp(configfilename, string(outputFolder, "config.txt"))

    # create new struct
    return SolverSet(set, ps, vs, gas, ib, outputFolder)
end

function SolverSet(dict::T) where {T<:AbstractDict}
    # setup
    set = set_setup(; dict...)

    # physical space
    ps = set_geometry(; dict...)

    # velocity space
    vs = set_velocity(; dict...)

    # gas property
    gas = set_property(dict)

    # initial & boundary condition
    ib = set_ib(dict, set, ps, vs, gas)

    # create working directory
    identifier = string(Dates.now(), "/")
    outputFolder = replace(identifier, ":" => ".")
    mkdir(outputFolder)
    mkdir(string(outputFolder, "data/"))
    CSV.write(string(outputFolder, "config.csv"), dict)

    # create new struct
    return SolverSet(set, ps, vs, gas, ib, outputFolder)
end

"""
    set_setup(dict::T) where {T<:AbstractDict}
    set_setup(;
        matter,
        case,
        space,
        flux,
        collision,
        nSpecies,
        interpOrder,
        limiter,
        boundary,
        cfl,
        maxTime,
        kwargs...,
    )

Generate AbstractPhysicalSpace

"""
function set_setup(dict::T) where {T<:AbstractDict}
    set = Setup(
        dict[:matter],
        dict[:case],
        dict[:space],
        dict[:flux],
        dict[:collision],
        dict[:nSpecies],
        dict[:interpOrder],
        dict[:limiter],
        dict[:boundary],
        dict[:cfl],
        dict[:maxTime],
    )

    return set
end

function set_setup(;
    matter,
    case,
    space,
    flux,
    collision,
    nSpecies,
    interpOrder,
    limiter,
    boundary,
    cfl,
    maxTime,
    kwargs...,
)
    set = Setup(
        matter,
        case,
        space,
        flux,
        collision,
        nSpecies,
        interpOrder,
        limiter,
        boundary,
        cfl,
        maxTime,
    )

    return set
end

"""
    set_geometry(dict::T) where {T<:AbstractDict}
    set_geometry(;
        space,
        x0,
        x1,
        nx,
        nxg,
        y0 = nothing,
        y1 = nothing,
        ny = nothing,
        nyg = nothing,
        kwargs...,
    )

Generate AbstractPhysicalSpace

"""
function set_geometry(dict::T) where {T<:AbstractDict}
    try
        return UnstructPSpace(dict[:mesh])
    catch
        if parse(Int, dict[:space][1]) == 1
            return PSpace1D(dict[:x0], dict[:x1], dict[:nx], dict[:nxg])
        elseif parse(Int, dict[:space][1]) == 2
            return PSpace2D(
                dict[:x0],
                dict[:x1],
                dict[:nx],
                dict[:y0],
                dict[:y1],
                dict[:ny],
                dict[:nxg],
                dict[:nyg],
            )
        else
            throw("No preset available for 3D simulation, please set it up manually.")
        end
    end

    return nothing
end

function set_geometry(;
    space,
    x0,
    x1,
    nx,
    nxg,
    y0 = nothing,
    y1 = nothing,
    ny = nothing,
    nyg = nothing,
    kwargs...,
)

    Dx = parse(Int, space[1])
    if Dx == 1
        pSpace = PSpace1D(x0, x1, nx, nxg)
    elseif Dx == 2
        pSpace = PSpace2D(x0, x1, nx, y0, y1, ny, nxg, nyg)
    else
        throw("No preset available for 3D simulation, please set it up manually.")
    end

    return pSpace

end

"""
    set_velocity(dict::T) where {T<:AbstractDict}
    set_velocity(;
        space,
        nSpecies,
        umin,
        umax,
        nu,
        vMeshType,
        nug,
        mi = nothing,
        me = nothing,
        vmin = nothing,
        vmax = nothing,
        nv = nothing,
        nvg = nothing,
        wmin = nothing,
        wmax = nothing,
        nw = nothing,
        nwg = nothing,
        kwargs...,
    )

Generate AbstractVelocitySpace

"""
function set_velocity(dict::T) where {T<:AbstractDict}
    for key in keys(dict)
        s = key
        @eval $s = $(dict[key])
    end

    Dv = parse(Int, space[5])
    if Dv == 0
        vSpace = nothing
    elseif Dv == 1
        if nSpecies == 1
            vSpace = VSpace1D(umin, umax, nu, vMeshType, nug)
        elseif nSpecies == 2
            ue0 = umin * sqrt(mi / me)
            ue1 = umax * sqrt(mi / me)
            vSpace = MVSpace1D(umin, umax, ue0, ue1, nu, vMeshType, nug)
        else
            throw("The velocity space only supports up to two species.")
        end
    elseif Dv == 2
        if nSpecies == 1
            vSpace = VSpace2D(umin, umax, nu, vmin, vmax, nv, vMeshType, nug, nvg)
        elseif nSpecies == 2
            ue0 = umin * sqrt(mi / me)
            ue1 = umax * sqrt(mi / me)
            ve0 = vmin * sqrt(mi / me)
            ve1 = vmax * sqrt(mi / me)
            vSpace = MVSpace2D(
                umin,
                umax,
                ue0,
                ue1,
                nu,
                vmin,
                vmax,
                ve0,
                ve1,
                nv,
                vMeshType,
                nug,
                nvg,
            )
        else
            throw("The velocity space only supports up to two species.")
        end
    elseif Dv == 3
        if nSpecies == 1
            vSpace = VSpace3D(
                umin,
                umax,
                nu,
                vmin,
                vmax,
                nv,
                wmin,
                wmax,
                nw,
                vMeshType,
                nug,
                nvg,
                nwg,
            )
        elseif nSpecies == 2
            ue0 = umin * sqrt(mi / me)
            ue1 = umax * sqrt(mi / me)
            ve0 = vmin * sqrt(mi / me)
            ve1 = vmax * sqrt(mi / me)
            we0 = wmin * sqrt(mi / me)
            we1 = wmax * sqrt(mi / me)
            vSpace = MVSpace3D(
                umin,
                umax,
                ue0,
                ue1,
                nu,
                vmin,
                vmax,
                ve0,
                ve1,
                nv,
                wmin,
                wmax,
                we0,
                we1,
                nw,
                vMeshType,
                nug,
                nvg,
                nwg,
            )
        else
            throw("The velocity space only supports up to two species.")
        end
    end

    return vSpace
end

function set_velocity(;
    space,
    nSpecies,
    umin,
    umax,
    nu,
    vMeshType,
    nug,
    mi = nothing,
    me = nothing,
    vmin = nothing,
    vmax = nothing,
    nv = nothing,
    nvg = nothing,
    wmin = nothing,
    wmax = nothing,
    nw = nothing,
    nwg = nothing,
    kwargs...,
)
    Dv = parse(Int, space[5])
    if Dv == 0
        vSpace = nothing
    elseif Dv == 1
        if nSpecies == 1
            vSpace = VSpace1D(umin, umax, nu, vMeshType, nug)
        elseif nSpecies == 2
            ue0 = umin * sqrt(mi / me)
            ue1 = umax * sqrt(mi / me)
            vSpace = MVSpace1D(umin, umax, ue0, ue1, nu, vMeshType, nug)
        else
            throw("The velocity space only supports up to two species.")
        end
    elseif Dv == 2
        if nSpecies == 1
            vSpace = VSpace2D(umin, umax, nu, vmin, vmax, nv, vMeshType, nug, nvg)
        elseif nSpecies == 2
            ue0 = umin * sqrt(mi / me)
            ue1 = umax * sqrt(mi / me)
            ve0 = vmin * sqrt(mi / me)
            ve1 = vmax * sqrt(mi / me)
            vSpace = MVSpace2D(
                umin,
                umax,
                ue0,
                ue1,
                nu,
                vmin,
                vmax,
                ve0,
                ve1,
                nv,
                vMeshType,
                nug,
                nvg,
            )
        else
            throw("The velocity space only supports up to two species.")
        end
    elseif Dv == 3
        if nSpecies == 1
            vSpace = VSpace3D(
                umin,
                umax,
                nu,
                vmin,
                vmax,
                nv,
                wmin,
                wmax,
                nw,
                vMeshType,
                nug,
                nvg,
                nwg,
            )
        elseif nSpecies == 2
            ue0 = umin * sqrt(mi / me)
            ue1 = umax * sqrt(mi / me)
            ve0 = vmin * sqrt(mi / me)
            ve1 = vmax * sqrt(mi / me)
            we0 = wmin * sqrt(mi / me)
            we1 = wmax * sqrt(mi / me)
            vSpace = MVSpace3D(
                umin,
                umax,
                ue0,
                ue1,
                nu,
                vmin,
                vmax,
                ve0,
                ve1,
                nv,
                wmin,
                wmax,
                we0,
                we1,
                nw,
                vMeshType,
                nug,
                nvg,
                nwg,
            )
        else
            throw("The velocity space only supports up to two species.")
        end
    end

    return vSpace
end

"""
    set_property(dict::T) where {T<:AbstractDict}

Generate AbstractProperty

"""
function set_property(dict::T) where {T<:AbstractDict}
    for key in keys(dict)
        s = key
        @eval $s = $(dict[key])
    end

    Dx = parse(Int, dict[:space][1])
    γD = map(parse(Int, dict[:space][3]), parse(Int, dict[:space][5])) do x, y # (x)f(y)v
        if x == 0
            return Dx
        elseif x == 1 # 1f
            if y >= 3 # 3v
                return 3
            else # 1v
                return Dx
            end
        elseif x == 2 # 2f
            return Dx
        elseif x >= 3 # 3f / 4f
            return 3
        else
            return nothing
        end
    end
    γ = heat_capacity_ratio(dict[:inK], γD)

    if matter == "radiation"

        gas = Radiation(dict[:knudsen], dict[:sigmaS], dict[:sigmaA])

    elseif matter == "gas"

        if nSpecies == 1
            μᵣ = ref_vhs_vis(dict[:knudsen], dict[:alphaRef], dict[:omegaRef])
            gas = Gas(
                dict[:knudsen],
                dict[:mach],
                dict[:prandtl],
                dict[:inK],
                γ,
                dict[:omega],
                dict[:alphaRef],
                dict[:omegaRef],
                μᵣ,
            )
        elseif nSpecies == 2
            kne = dict[:knudsen] * (dict[:me] / dict[:mi])
            gas = Mixture(
                [dict[:knudsen], kne],
                dict[:mach],
                dict[:prandtl],
                dict[:inK],
                γ,
                dict[:mi],
                dict[:ni],
                dict[:me],
                dict[:ne],
            )
        else
            throw("The gas property only supports up to two species.")
        end

    elseif matter == "plasma"

        kne = dict[:knudsen] * (dict[:me] / dict[:mi])
        if Dx == 1
            gas = Plasma1D(
                [dict[:knudsen], kne],
                dict[:mach],
                dict[:prandtl],
                dict[:inK],
                γ,
                dict[:mi],
                dict[:ni],
                dict[:me],
                dict[:ne],
                dict[:lD],
                dict[:rL],
                dict[:sol],
                dict[:echi],
                dict[:bnu],
            )
        elseif Dx == 2
            gas = Plasma2D(
                [dict[:knudsen], kne],
                dict[:mach],
                dict[:prandtl],
                dict[:inK],
                γ,
                dict[:mi],
                dict[:ni],
                dict[:me],
                dict[:ne],
                dict[:lD],
                dict[:rL],
                dict[:sol],
                dict[:echi],
                dict[:bnu],
            )
        else
            throw("The plasma property only supports up to 2D case.")
        end

    end

    return gas
end

"""
    set_ib(dict::T, set, ps, vs, gas) where {T<:AbstractDict}
    set_ib(set, pSpace, vSpace, gas, Um = 0.15, Vm = 0.0, Tm = 1.0)

Generate AbstractIB

"""
function set_ib(dict::T, set, ps, vs, gas) where {T<:AbstractDict}
    if haskey(dict, :uLid)
        ib = set_ib(set, ps, vs, gas, uLid, vLid, tLid)
    else
        ib = set_ib(set, ps, vs, gas)
    end

    return ib
end

function set_ib(set, pSpace, vSpace, gas, Um = 0.15, Vm = 0.0, Tm = 1.0)
    fname = begin
        if set.case == "shock"
            "ib_rh"
        elseif set.case == "brio-wu"
            "ib_briowu"
        else
            "ib_" * string(set.case)
        end
    end

    ib = begin
        if parse(Int, set.space[3]) == 0
            fw, bc = config_ib(set, pSpace, vSpace, gas)
            IB(fw, bc)
        elseif parse(Int, set.space[3]) in [3, 4] && gas isa AbstractPlasma
            fw, ff, fE, fB, fL, bc = config_ib(set, pSpace, vSpace, gas)
            iname = "IB" * set.space[3] * "F"
            eval(Symbol(iname))(fw, ff, fE, fB, fL, bc)
        elseif set.case == "cavity"
            fw, ff, bc = config_ib(set, pSpace, vSpace, gas, Um, Vm, Tm)
            iname = "IB" * set.space[3] * "F"
            eval(Symbol(iname))(fw, ff, bc)
        else
            fw, ff, bc = config_ib(set, pSpace, vSpace, gas)
            iname = "IB" * set.space[3] * "F"
            eval(Symbol(iname))(fw, ff, bc)
        end
    end

    return ib
end


text:
module MessageRequest

export body_is_a_stream, body_was_streamed

import ..Layer, ..request
using ..URIs
using ..Messages
import ..Messages.bodylength
using ..Headers
using ..Form

"""
    request(MessageLayer, method, ::URI, headers, body) -> HTTP.Response

Construct a [`Request`](@ref) object and set mandatory headers.
"""

struct MessageLayer{Next <: Layer} <: Layer end
export MessageLayer

function request(::Type{MessageLayer{Next}},
                 method::String, url::URI, headers::Headers, body;
                 http_version=v"1.1",
                 target=resource(url),
                 parent=nothing, iofunction=nothing, kw...) where Next

    defaultheader(headers, "Host" => url.host)

    if !hasheader(headers, "Content-Length") &&
       !hasheader(headers, "Transfer-Encoding") &&
       !hasheader(headers, "Upgrade")
        l = bodylength(body)
        if l != unknown_length
            setheader(headers, "Content-Length" => string(l))
        elseif method == "GET" && iofunction isa Function
            setheader(headers, "Content-Length" => "0")
        end
    end

    req = Request(method, target, headers, bodybytes(body);
                  parent=parent, version=http_version)

    return request(Next, url, req, body; iofunction=iofunction, kw...)
end

bodylength(body) = unknown_length
bodylength(body::AbstractVector{UInt8}) = length(body)
bodylength(body::AbstractString) = sizeof(body)
bodylength(body::Form) = length(body)
bodylength(body::Vector{T}) where T <: AbstractString = sum(sizeof, body)
bodylength(body::Vector{T}) where T <: AbstractArray{UInt8,1} = sum(length, body)
bodylength(body::IOBuffer) = nb_available(body)
bodylength(body::Vector{IOBuffer}) = sum(nb_available, body)

const body_is_a_stream = UInt8[]
const body_was_streamed = Vector{UInt8}("[Message Body was streamed]")
bodybytes(body) = body_is_a_stream
bodybytes(body::Vector{UInt8}) = body
bodybytes(body::IOBuffer) = read(body)
bodybytes(body::AbstractVector{UInt8}) = Vector{UInt8}(body)
bodybytes(body::AbstractString) = Vector{UInt8}(body)
bodybytes(body::Vector) = length(body) == 1 ? bodybytes(body[1]) :
                                              body_is_a_stream

end # module MessageRequest


text:
using JuliaProbo
using Plots
using Test
using JuliaFormatter

ENV["GKSwstype"] = "nul"
GUI = false
FORMATTER = true

if FORMATTER
    format("../src")
    format_file("../test/ch03_test.jl")
    format_file("../test/ch04_test.jl")
    format_file("../test/ch05_test.jl")
    format_file("../test/ch06_test.jl")
    format_file("../test/ch07_test.jl")
    format_file("../test/ch08_test.jl")
    format_file("../test/ch09_test.jl")
    # Somehow this file fails
    # format_file("../test/ch10_test.jl")
    format_file("../test/ch12_test.jl")
end

include("ch03_test.jl")
include("ch04_test.jl")
include("ch05_test.jl")
include("ch06_test.jl")
include("ch07_test.jl")
include("ch08_test.jl")
include("ch09_test.jl")
include("ch10_test.jl")
include("ch12_test.jl")

max_stars_repo_name: soblin/JuliaProbo

max_issues_repo_name: soblin/JuliaProbo

max_forks_repo_name: soblin/JuliaProbo


text:
using Oceananigans.Utils: with_tracers
using Oceananigans.TurbulenceClosures: with_tracers

@inline zeroforcing(args...) = 0

const assumed_field_locations = Dict(:tracer => (Cell, Cell, Cell),
                                          :u => (Face, Cell, Cell),
                                          :v => (Cell, Face, Cell),
                                          :w => (Face, Cell, Face))

"""
    ModelForcing(; u=zeroforcing, v=zeroforcing, w=zeroforcing, tracer_forcings...)

Return a named tuple of forcing functions for each solution field.

Example
=======

julia> u_forcing = SimpleForcing((x, y, z, t) -> exp(z) * cos(t))

julia> model = IncompressibleModel(forcing=ModelForcing(u=u_forcing))
"""
function ModelForcing(; u=zeroforcing, v=zeroforcing, w=zeroforcing, tracer_forcings...)
    u = for_field_name(:u, u)
    v = for_field_name(:v, v)
    w = for_field_name(:w, w)

    # Re-build tracer forcings
    tracer_names = Tuple(f.first for f in tracer_forcings)
    tracer_functions = Tuple(for_field_name(f.first, f.second) for f in tracer_forcings)
    tracer_forcings = NamedTuple{tracer_names}(tracer_functions)

    return merge((u=u, v=v, w=w), tracer_forcings)
end

for_field_name(field_name, forcing_function) = forcing_function # Fallback for ordinary functions

""" Returns a SimpleForcing object at `field_name`'s assumed location. """
function for_field_name(field_name, f::SimpleForcing)

    # Deduce the location of `field_name`.
    X, Y, Z = field_name ∈ (:u, :v, :w) ? assumed_field_locations[field_name] :
                                          assumed_field_locations[:tracer]

    return SimpleForcing{X, Y, Z}(field_name, f.forcing, f.parameters, f.field_in_signature)
end

default_tracer_forcing(args...) = zeroforcing

ModelForcing(tracers, proposal_forcing) = with_tracers(tracers, proposal_forcing, default_tracer_forcing,
                                                       with_velocities=true)


text:
import RowEchelon

#=
Homework 5
Section 2.2
Problem 2
=#

# Initialize the Matrix
A = [3 2 ; 8 5]

# Calculate the Inverse
invA = inv(A)

println("The Inverse of A is:")
println(invA)


text:
module Test_MiniBsp

using Modia3D
using Modia3D.StaticArrays
using Modia3D.ModiaMath
using Modia3D.Unitful

# Materials
massProperties = "Aluminium"
vmat1   = Modia3D.Material(color="LightBlue", transparency=0.5, wireframe=false)
vblue   = Modia3D.Material(color="LightBlue" , transparency=0.5)
vred    = Modia3D.Material(color="Red", transparency=0.5)
vgreen  = Modia3D.Material(color="Green", transparency=0.5)
vblack  = Modia3D.Material(color="Black", transparency=0.5)
vyellow = Modia3D.Material(color="Yellow", transparency=0.5)
vpink   = Modia3D.Material(color="Pink", transparency=0.5)
cmat    = "Steel"
vMatAABB = Modia3D.Material(color="Grey", transparency=0.95)

# dimensions
Lx  = 0.7
Dx = 0.5
Ly    = 0.2
Lz   = 1.0

groundWidth  = 1.0
groundHeight = 0.01
cyl  = Modia3D.Cylinder(1.2*Ly, Ly/2)
Tcyl = ModiaMath.rot1(90u"°")
TGround = ModiaMath.rot1(-90u"°")

@assembly CollisionSolids() begin

world = Modia3D.Object3D(Modia3D.CoordinateSystem(1.0))

#world_f1 = Modia3D.Object3D(world , r=[0.0, 0.5, 0.5])

blau1     = Modia3D.Part(Modia3D.Solid(Modia3D.SolidBox(Lx,Ly,Lz), "Aluminium", vblue;contactMaterial = cmat),    [ [0.0, 0.0, -Lz/2],[ 0.0, 0.0, Lz/2] ] )
#blau2     = Modia3D.Part(Modia3D.Solid(Modia3D.SolidBox(Lx,Ly,Lz), "Aluminium", vblue; contactMaterial = cmat),   [ [0.0, 0.0, -Lz/2], [ 0.0, 0.0, Lz/2] ] )

rotM1      = Modia3D.Part(Modia3D.Solid(Modia3D.SolidPipe(Dx,Lz), nothing, vred; contactMaterial = cmat),          [[0.0, 0.0, -Lz/2], [ 0.0, 0.0, Lz/2]] )
#rotM2      = Modia3D.Part(Modia3D.Solid(Modia3D.SolidCylinder(Dx, Lz), nothing, vred; contactMaterial = cmat),     [[0.0, 0.0, -Lz/2], [ 0.0, 0.0, Lz/2]])

#=
schwarz1  = Modia3D.Part(Modia3D.Solid(Modia3D.SolidCone(Dx,Lz; relativeTipDiameter=0.0), nothing, vblack; contactMaterial = cmat),  [ [0.0, 0.0, 0.0]] )
rosa1     = Modia3D.Part(Modia3D.Solid(Modia3D.SolidBox(Lx,Ly,Lz), "Aluminium", vpink; contactMaterial = cmat),   [ [0.0, 0.0, -Lz/2],[ 0.0, 0.0, Lz/2] ] )
green1    = Modia3D.Part(Modia3D.Solid(Modia3D.SolidBeam(Lx,Ly,Lz), nothing, vgreen; contactMaterial = cmat),     [ [0.0, 0.0, -Lz/2],[ 0.0, 0.0, Lz/2] ] )
green2    = Modia3D.Part(Modia3D.Solid(Modia3D.SolidBeam(Lx,Ly,Lz), nothing, vgreen; contactMaterial = cmat),     [ [0.0, 0.0, -Lz/2]] )
gelb1     = Modia3D.Part(Modia3D.Solid(Modia3D.SolidBox(Lx,Ly,Lz), "Aluminium", vyellow; contactMaterial = cmat), [ [0.0, 0.0, -Lz/2],[ 0.0, 0.0, Lz/2] ] )
gelb2     = Modia3D.Part(Modia3D.Solid(Modia3D.SolidEllipsoid(Lx,Ly,Lz), "Aluminium", vyellow; contactMaterial = cmat), [ [0.0, 0.0, -Lz/2] ] )
gelb3     = Modia3D.Part(Modia3D.Solid(Modia3D.SolidSphere(Dx), "Aluminium", vyellow; contactMaterial = cmat),    [ [0.0, 0.0, -Lz/2] ] )

=#

Modia3D.connect(world, blau1.frame0;  R=ModiaMath.rot2(160u"°"))
#Modia3D.connect(blau1.frames[1], blau2.frames[2]; R=ModiaMath.rot2(45u"°"))

Modia3D.connect(blau1.frames[1], rotM1.frame0;  fixed=false, R=ModiaMath.rot3(90u"°"))
#Modia3D.connect(rotM1.frames[2], rotM2.frames[1]; R=ModiaMath.rot2(45u"°"))

#=
rev2 = Modia3D.Revolute(blau2.frames[2], rosa1.frames[1]; phi_start =-pi/2)

rev5 = Modia3D.Revolute(blau1.frames[2], schwarz1.frames[1]; phi_start =-pi/2)

rev3 = Modia3D.Revolute(rosa1.frames[2], green1.frames[1])

Modia3D.connect(green1.frame0, green2.frames[1]; R=ModiaMath.rot2(45u"°"))
rev4 = Modia3D.Revolute(green1.frames[2], gelb1.frames[1])

Modia3D.connect(gelb1.frames[2],gelb2.frames[1]; R=ModiaMath.rot2(130u"°"))
Modia3D.connect(gelb1.frames[2], gelb3.frames[1]; R=ModiaMath.rot2(90u"°"))

=#
end

collisionSolids = CollisionSolids(sceneOptions= Modia3D.SceneOptions(visualizeFrames=true,defaultFrameLength=0.3,enableContactDetection=true, nz_max = 8))

Modia3D.initAnalysis!(collisionSolids)

tStart=0.0
tEnd  =1.0

for time = range(tStart, stop=tEnd, length=101)
  s = Modia3D.linearMovement(2*Lx, tStart, tEnd, time)
  #=
  delta_phi = Modia3D.linearMovement(pi/3, tStart, tEnd, time)

  Modia3D.setAngle!(collisionSolids.rev2,-pi/2 + delta_phi)
  Modia3D.setAngle!(collisionSolids.rev3, delta_phi)
  Modia3D.setAngle!(collisionSolids.rev4,-delta_phi)
  Modia3D.setAngle!(collisionSolids.rev5, delta_phi)
=#
  Modia3D.set_r!(collisionSolids.rotM1.frame0, [0, 0, -s])

  Modia3D.updatePosition!(collisionSolids)
  # Modia3D.getDistances!(collisionTest)

  # Modia3D.setComputationFlag(collisionSolids)
  Modia3D.visualize!(collisionSolids,time)

  time += 0.01
end

Modia3D.closeAnalysis!(collisionSolids)
println("... success of Test_MiniBsp.jl!")
end


text:
using Plots

dx = 0.01
L = 10
x = 0:dx:L
n = length(x)
nquart = Int(floor(n/4))

f = zeros(n)
f[nquart:3nquart] .= 1

A0 = (2nquart+1)*dx*2/L
fFS = A0/2

for k = 1:100
    Ak = sum(f.*cos.(2pi*k*x/L))*dx*2/L
    Bk = sum(f.*sin.(2pi*k*x/L))*dx*2/L
    global fFS = Ak*cos.(2pi*k*x/L) .+ Bk*sin.(2pi*k*x/L) .+ fFS
end

p1 = plot(x, f)
plot!(x, fFS)


text:
include("diagadd!.jl")

function updateA!(A::Array{Any,1}, D::Array{Any,1}, DataMat::Array{Any,1}, P::Array{Any,1}, τ::Float64, DictSize::Int64)
    # Update tempDictCoef by Eq. (8)

    for (i, Dᵢ) in enumerate(D)
        @inbounds TempDict::Matrix{Float64} = Dᵢ
        @inbounds TempData::Matrix{Float64} = DataMat[i]
        tempDictCoef::Matrix{Float64}       = TempDict' * TempDict
        tempDictDataCoef::Matrix{Float64}   = TempDict' * TempData
        @inbounds C::Matrix{Float64}        = P[i] * TempData
        diagadd!(tempDictCoef, τ)
        tempDictDataCoef += C .* τ
        @inbounds A[i]                      = tempDictCoef \ tempDictDataCoef
    end
end


text:
module WorkingGeoMakieCombo

using GeoMakie, Makie
export testmap1, testmap2

function testmap1()
    lons = LinRange(-179.5, 179.5, 360)
    lats = LinRange(-89.5, 89.5, 180)

    field = [exp(cosd(l)) + 3(y/90) for l in lons, y in lats]

    source = LonLat()
    dest = WinkelTripel()

    xs, ys = xygrid(lons, lats)
    Proj4.transform!(source, dest, vec(xs), vec(ys))

    scene = surface(xs, ys; color = field, shading = false, show_axis = false, scale_plot = false)

    geoaxis!(scene, extrema(lons), extrema(lats); crs = (src = source, dest = dest,))

    # coastlines!(scene; crs = (src = source, dest = dest,))
end

function testmap2()
    lons = LinRange(1, 30, 360)
    lats = LinRange(51, 74, 180)

    field = [exp(cosd(l)) + 3(y/90) for l in lons, y in lats]

    source = LonLat()
    dest = WinkelTripel()

    xs, ys = xygrid(lons, lats)
    Proj4.transform!(source, dest, vec(xs), vec(ys))

    scene = surface(xs, ys; color = field, shading = false, show_axis = false, scale_plot = false)

    geoaxis!(scene, extrema(lons), extrema(lats); crs = (src = source, dest = dest,))

    # coastlines!(scene; crs = (src = source, dest = dest,))
end

end # module

max_stars_repo_name: niclasmattsson/WorkingGeoMakieCombo

max_issues_repo_name: niclasmattsson/WorkingGeoMakieCombo

max_forks_repo_name: niclasmattsson/WorkingGeoMakieCombo


text:
using Images, ImageView, GtkReactive

get_point(p::XY{UserUnit}) = Mark(round(p.y.val, 2), round(p.x.val, 2))

function fetch_image(file::String)
    img = load(file)
    imgtmp = deepcopy(img)
    ms = quantile(vec(img), [.1, .999])
    return (img, imgtmp, ms)
end

function build_slider(M::Float64, message::String)
    s = slider(linspace(0,1,2^16), value=1 - M)
    b = GtkBox(:h)
    push!(b, label(message), s)
    setproperty!(b, :expand, widget(s), true)
    return (s, b)
end

function get_startpoints(f1::String, f2::String)
    # build composite image
    img1, img1tmp, ms1 = fetch_image(f1)
    img2, img2tmp, ms2 = fetch_image(f2)
    imgc = colorview(RGB, img1tmp, img2tmp, img1tmp)
    # build sliders
    M = [ms1[2], ms2[2]]
    s1, b1 = build_slider(M[1], "First frame (magenta):")
    s2, b2 = build_slider(M[2], "Last frame (green):")
    # start the gui
    const g = imshow(imgc, name="Shift-click to add tip, Shift-ctrl-click to remove tip, close window when done")
    const w = g["gui"]["window"]
    const c = g["gui"]["canvas"]
    const zr = g["roi"]["zoomregion"]
    const m = [ms1[1], ms2[1]]
    # connect the sliders to the gui
    foreach(s1, s2) do M1, M2
        img1tmp .= imadjustintensity(img1, (m[1], 1 - M1))
        img2tmp .= imadjustintensity(img2, (m[2], 1 - M2))
        push!(zr, value(zr).currentview)
    end
    push!(g["gui"]["vbox"], b1, b2)
    showall(w)
    # pointing
    const add = Signal(XY{UserUnit}(1,1))
    const remove = Signal(XY{UserUnit}(1,1))
    const roots = foldp(push!, XY{UserUnit}[], add)
    const points = foldp([], add) do a, xy
        push!(a, ImageView.annotate!(g, AnnotationPoint(xy.x.val, xy.y.val, shape='.', size=10, color=RGB(0,0,1))))
    end
    sigstart = map(c.mouse.buttonpress) do btn
        if btn.button == 1 # mouse click
            if btn.modifiers & 0x01 == 0x01 #shift
                if btn.modifiers & 0x04 == 0x04 # Ctrl and Shift
                    push!(remove, btn.position)
                else
                    if !outside(get_point(btn.position)) # make sure the point is inside, reject otherwise
                        push!(add, btn.position)
                    end
                end
            end
        end
    end
    GtkReactive.gc_preserve(w, sigstart)
    removeidx = map(remove) do xy
        idx = Int[]
        for (i, root) in enumerate(value(roots))
            dxy = xy - root
            if sqrt(dxy.x.val^2 + dxy.y.val^2) < 50
                push!(idx, i)
            end
        end
        return idx
    end
    foreach(removeidx) do i
        deleteat!(value(roots), i)
        for j in i
            delete!(g, value(points)[j])
        end
        deleteat!(value(points), i)
    end
    close = Condition()
    Gtk.signal_connect(w, :destroy) do widget
        notify(close)
    end
    wait(close)
    return get_point.(value(roots))
end

function get_startpoints(stage::Stage)
    path = joinpath(stage.home, stage.base, "stage $(stage.id)")
    mkpath(path)
    file = joinpath(path, "start_points.csv")
    if isfile(file)
        info("Starting points already exist for stage #$(stage.id). Using those (delete $file if you want to choose new starting points)…")
        a = readcsv(file, Float64)
        n = size(a, 1)
        return [Mark(a[i,1], a[i,2]) for i in 1:n]
    else
        for f in readdir(path)
            ff = joinpath(path, f)
            if isdir(ff)
                r"^root \d*$"(f) && rm(ff, recursive=true)
            else
                "roots.png" == f && rm(ff)
            end
        end
        startpoints = get_startpoints(stage.timelapse[1].dark, stage.timelapse[end].dark)
        isempty(startpoints) || writecsv(file, startpoints)
        return startpoints
    end
end


text:
module consoles

import Term: highlight, theme

import ..renderables: AbstractRenderable
import ..style: apply_style

export Console, console, err_console, console_height, console_width, tprint

# ---------------------------------------------------------------------------- #
#                                    TPRINT                                    #
# ---------------------------------------------------------------------------- #

"""
    tprint

Similar to standard lib's `print` function but with added
styling functionality
"""
function tprint end

"""
    tprint(x::AbstractString)

Apply style to a string and print it to a new line
"""
tprint(x::AbstractString) = (println ∘ apply_style)(x)

"""
    tprint(x::AbstractRenderable)

Print an `AbstractRenderable`.

Equivalent to `println(x)`
"""
tprint(x::AbstractRenderable) = println(x)

"""
    tprint(x::Symbol)

Print highlighted as a Symbol
"""
tprint(x::Symbol) = tprint(highlight(":" * string(x), theme, :symbol))

"""
    tprint(x::Number)

Print highlighted as a Number
"""
tprint(x::Number) = tprint(highlight(string(x), theme, :number))

"""
    tprint(x::Function)

Print highlighted as a Function
"""
tprint(x::Function) = tprint(highlight(string(x), theme, :func))

"""
    tprint(x)

When no dedicated method is present, print the string representation
"""
tprint(x) = tprint(string(x))

function tprint(args...)
    map(tprint, args)
    return nothing
end

# ---------------------------------------------------------------------------- #
#                                    CONSOLE                                   #
# ---------------------------------------------------------------------------- #
"""
    Console

The `Console` object stores information about the dimensions of the output(::IO)
where objects will be printed
"""
struct Console
    io::IO
    width::Int
    height::Int
end

Console(io::IO) = Console(io, displaysize(io)[2], displaysize(io)[1])
Console() = Console(stdout)

console = Console(stdout)
err_console = Console(stderr)

"""
    console_height()

Get the current console height.
"""
console_height() = displaysize(stdout)[1]
console_height(io::IO) = displaysize(io)[1]

"""
    console_width()

Get the current console width.
"""
console_width() = displaysize(stdout)[2]
console_width(io::IO) = displaysize(io)[2]

end


text:
deco_tight    = make_estim_decorator([0.001, 0.01, 0.05]) # the default
deco_standard = make_estim_decorator([0.01, 0.05, 0.1])
deco_latex    = make_estim_decorator([0.01, 0.05, 0.1],
                                     wrapper=s -> "^\\sym{$s}")
deco_1pc      = make_estim_decorator([0.01])

@testset "decorations" begin
    @testset "deco_tight" begin
        @test deco_tight(123, 0.0) == "123***"
        @test deco_tight(123, 0.001) == "123***"
        @test deco_tight(123, 0.01) == "123**"
        @test deco_tight(123, 0.02) == "123*"
        @test deco_tight(123, 0.1) == "123"
    end

    @testset "deco_standard" begin
        @test deco_standard(123, 0.0) == "123***"
        @test deco_standard(123, 0.01) == "123***"
        @test deco_standard(123, 0.02) == "123**"
        @test deco_standard(123, 0.1) == "123*"
        @test deco_standard(123, 0.2) == "123"
    end

    @testset "deco_latex" begin
        @test deco_latex(123, 0.0) == "123^\\sym{***}"
        @test deco_latex(123, 0.01) == "123^\\sym{***}"
        @test deco_latex(123, 0.02) == "123^\\sym{**}"
        @test deco_latex(123, 0.1) == "123^\\sym{*}"
        @test deco_latex(123, 0.2) == "123"
    end

    @testset "deco_1pc" begin
        @test deco_1pc(123, 0.0) == "123*"
        @test deco_1pc(123, 0.01) == "123*"
        @test deco_1pc(123, 0.02) == "123"
    end
end