text:
type PMLCoef
     vz::SparseMatrixCSC{Float64, Int64}
     vx::SparseMatrixCSC{Float64, Int64}
     pz::SparseMatrixCSC{Float64, Int64}
     px::SparseMatrixCSC{Float64, Int64}
end

# function InitCpml(nz::Int64, nx::Int64, ext::Int64, vmax::Float64, rho::Array{Float64,2}, iflag::Int64)
#     rho = modExpand(rho, ext, iflag)
#     if ext == 5
#        R = 0.01
#     elseif ext == 10
#        R = 0.001
#     elseif ext == 20
#        R = 0.0001
#     else
#        error("unsupported damping layers")
#     end
#     m = 0.25; n = 0.75; ll = 4;
#     if iflag == 1
#        Nz = nz + 2*ext
#        Nx = nx + 2*ext
#        vz = spzeros(Nz, Nx)
#        vx = spzeros(Nz, Nx)
#        pz = spzeros(Nz, Nx)
#        px = spzeros(Nz, Nx)
#        #  upper and left
#        for i = 1 : ext
#            vz[i,:] = -vmax/ext * log(R) * (m*(ext+1-i)/ext + n*((ext+1-i)/ext)^ll) * rho[i,:]
#            vx[:,i] = -vmax/ext * log(R) * (m*(ext+1-i)/ext + n*((ext+1-i)/ext)^ll) * rho[:,i]
#            pz[i,:] = -vmax/ext * log(R) * (m*(ext+1-i)/ext + n*((ext+1-i)/ext)^ll)
#            px[:,i] = -vmax/ext * log(R) * (m*(ext+1-i)/ext + n*((ext+1-i)/ext)^ll)
#        end
#        #  lower
#        for iz = nz+ext+1 : Nz
#            vz[iz,:] = -vmax/ext * log(R) * (m*(iz-nz-ext)/ext + n*((iz-nz-ext)/ext)^ll) * rho[iz,:]
#            pz[iz,:] = -vmax/ext * log(R) * (m*(iz-nz-ext)/ext + n*((iz-nz-ext)/ext)^ll)
#        end
#        #  right
#        for ix = nx+ext+1 : Nx
#            vx[:,ix] = -vmax/ext * log(R) * (m*(ix-nx-ext)/ext + n*((ix-nx-ext)/ext)^ll) * rho[:,ix]
#            px[:,ix] = -vmax/ext * log(R) * (m*(ix-nx-ext)/ext + n*((ix-nx-ext)/ext)^ll)
#        end
#     elseif iflag == 2
#        Nz = nz +   ext
#        Nx = nx + 2*ext
#        vz = spzeros(Nz, Nx)
#        vx = spzeros(Nz, Nx)
#        pz = spzeros(Nz, Nx)
#        px = spzeros(Nz, Nx)
#        #  lower
#        for iz = nz+1 : Nz
#            vz[iz,:] = -vmax/ext * log(R) * (m*(iz-nz)/ext + n*((iz-nz)/ext)^ll) * rho[iz,:]
#            pz[iz,:] = -vmax/ext * log(R) * (m*(iz-nz)/ext + n*((iz-nz)/ext)^ll)
#        end
#        #  left
#        for ix = 1 : ext
#            vx[:,ix] = -vmax/ext * log(R) * (m*(ext+1-ix)/ext + n*((ext+1-ix)/ext)^ll) * rho[:,ix]
#            px[:,ix] = -vmax/ext * log(R) * (m*(ext+1-ix)/ext + n*((ext+1-ix)/ext)^ll)
#        end
#        #  right
#        for ix = nx+ext+1 : Nx
#            px[:,ix] = -vmax/ext * log(R) * (m*(ix-nx-ext)/ext + n*((ix-nx-ext)/ext)^ll) * rho[:,ix]
#            px[:,ix] = -vmax/ext * log(R) * (m*(ix-nx-ext)/ext + n*((ix-nx-ext)/ext)^ll)
#        end
#     end
#     Cpml = PMLCoef(vz, vx, pz, px)
#     return Cpml
# end

function modExpand(par::Array{Float64,2}, ext::Int64, iflag::Int64)
    temp1 = repmat(par[:,  1], 1, ext)
    temp2 = repmat(par[:,end], 1, ext)
    par   = hcat(temp1, par, temp2)
    if iflag == 1
       temp1 = repmat(par[1,  :], ext, 1)
       temp2 = repmat(par[end,:], ext, 1)
       par   = vcat(temp1, par, temp2)
    elseif iflag == 2
       temp2 = repmat(par[end,:], ext, 1)
       par   = vcat(par, temp2)
    end
    return par
end

function modSmooth(par, L)
    n = 2*L + 1
    par1 = modExpand(par, L, 1)
    s = convert(Array{typeof(par1[1]), 1}, hanning(n))
    s = s / sum(s)
    par1 = conv2(s,s,par1)
    par1 = par1[2*L+1:end-2*L, 2*L+1:end-2*L]
    return par1
end

function InitCpml(nz::Int64, nx::Int64, ext::Int64, vmax::Float64, dz::Float64, dx::Float64, iflag::Int64)
      if ext == 10
         R = 0.01
      elseif ext == 20
         R = 0.001
      elseif ext == 30
         R = 0.0001
      else
         error("unsupported damping layers")
      end
      ll = 2;
      if iflag == 1
         Nz = nz + 2*ext
         Nx = nx + 2*ext
         vz = spzeros(Nz, Nx)
         vx = spzeros(Nz, Nx)
         pz = spzeros(Nz, Nx)
         px = spzeros(Nz, Nx)
         #  upper and left
         for i = 1 : ext
             vz[i,:] = -1.5 * vmax/(ext*dz) * log(R) *  ((ext+1-i)/ext)^ll
             vx[:,i] = -1.5 * vmax/(ext*dx) * log(R) *  ((ext+1-i)/ext)^ll
             pz[i,:] = -1.5 * vmax/(ext*dz) * log(R) *  ((ext+1-i)/ext)^ll
             px[:,i] = -1.5 * vmax/(ext*dx) * log(R) *  ((ext+1-i)/ext)^ll
         end
         #  lower
         for iz = nz+ext+1 : Nz
             vz[iz,:] = -1.5 * vmax/(ext*dz) * log(R) * ((iz-nz-ext)/ext)^ll
             pz[iz,:] = -1.5 * vmax/(ext*dz) * log(R) * ((iz-nz-ext)/ext)^ll
         end
         #  right
         for ix = nx+ext+1 : Nx
             vx[:,ix] = -1.5 * vmax/(ext*dx) * log(R) * ((ix-nx-ext)/ext)^ll
             px[:,ix] = -1.5 * vmax/(ext*dx) * log(R) * ((ix-nx-ext)/ext)^ll
         end
      elseif iflag == 2
         Nz = nz +   ext
         Nx = nx + 2*ext
         vz = spzeros(Nz, Nx)
         vx = spzeros(Nz, Nx)
         pz = spzeros(Nz, Nx)
         px = spzeros(Nz, Nx)
         #  lower
         for iz = nz+1 : Nz
             vz[iz,:] = -1.5 * vmax/(ext*dz) * log(R) * ((iz-nz)/ext)^ll
             pz[iz,:] = -1.5 * vmax/(ext*dz) * log(R) * ((iz-nz)/ext)^ll
         end
         #  left
         for ix = 1 : ext
             vx[:,ix] = -1.5 * vmax/(ext*dx) * log(R) * ((ext+1-ix)/ext)^ll
             px[:,ix] = -1.5 * vmax/(ext*dx) * log(R) * ((ext+1-ix)/ext)^ll
         end
         #  right
         for ix = nx+ext+1 : Nx
             vx[:,ix] = -1.5 * vmax/(ext*dx) * log(R) * ((ix-nx-ext)/ext)^ll
             px[:,ix] = -1.5 * vmax/(ext*dx) * log(R) * ((ix-nx-ext)/ext)^ll
         end
      end
      Cpml = PMLCoef(vz, vx, pz, px)
      return Cpml
end

max_stars_repo_name: WneleiGao/AcousticWaveLab

max_issues_repo_name: WneleiGao/AcousticWaveLab

max_forks_repo_name: WneleiGao/AcousticWaveLab


text:
using Plexifications
using Base.Test: @test, @test_throws

@test_throws ErrorException begin
    inv(Nlplex(0, 2))
end

@test begin
    iszerodivisor(Nlplex(0,1))
end

@test begin
    !iszerodivisor(Nlplex(1,1))
end

@test begin
    length(unreal(1)) == 0
end

@test begin
    a = Plexifications.randomBigFloat()
    isreal(Nlplex(a))
end

@test begin
    a = 1
    !isreal(Nlplex(a, a))
end

@test begin
    z = random(Nlplex{Int})
    z == +(z)
end

@test begin
    a = Plexifications.randomBigFloat()
    real(Nlplex(a)) == a
end

@test begin
    io = IOBuffer()
    show(io, Nlplex(1, 2))
    l = String(take!(io))
    r = "[1: 1, A: 2]"
    l == r
end

@test begin
    x = random(Nlplex{BigFloat})
    y = random(Nlplex{BigFloat})
    x != y
end

@test begin
    a = Plexifications.randomBigInt()
    z = random(Nlplex{BigInt})
    l = a + z
    r = z + a
    l == r
end

@test begin
    a = Plexifications.randomBigInt()
    z = random(Nlplex{BigInt})
    l = a - z
    r = -(z - a)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = x + y
    r = y + x
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = x * y
    r = y * x
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = x - y
    r = -(y - x)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    z = random(Nlplex{BigInt})
    l = (x + y) + z
    r = x + (y + z)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    z = random(Nlplex{BigInt})
    l = (x * y) * z
    r = x * (y * z)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    barA(barA(x)) == x
end

@test begin
    x = random(Nlplex{Rational{BigInt}})
    inv(inv(x)) == x
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = barA(x * y)
    r = barA(y) * barA(x)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = barA(x + y)
    r = barA(x) + barA(y)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = barA(x - y)
    r = barA(x) - barA(y)
    l == r
end

@test begin
    x = random(Nlplex{Rational{BigInt}})
    y = random(Nlplex{Rational{BigInt}})
    l = inv(x * y)
    r = inv(y) * inv(x)
    l == r
end

@test begin
    x = random(Nlplex{Rational{BigInt}})
    y = random(Nlplex{Rational{BigInt}})
    l = inv(x / y)
    r = y / x
    l == r
end

@test begin
    x = random(Nlplex{Rational{BigInt}})
    y = random(Nlplex{Rational{BigInt}})
    l = inv(x \ y)
    r = y \ x
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    z = random(Nlplex{BigInt})
    l = x * (y + z)
    r = (x * y) + (x * z)
    l == r
end

@test begin
    a = Plexifications.randomBigInt()
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = a * (x + y)
    r = (a * x) + (a * y)
    l == r
end

@test begin
    a = Plexifications.randomBigInt()
    x = random(Nlplex{BigInt})
    l = a * x
    r = x * a
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    z = random(Nlplex{BigInt})
    l = (x + y) * z
    r = (x * z) + (y * z)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    z = random(Nlplex{BigInt})
    l = x * (y - z)
    r = (x * y) - (x * z)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    z = random(Nlplex{BigInt})
    l = (x - y) * z
    r = (x * z) - (y * z)
    l == r
end

@test begin
    x = random(Nlplex{BigInt})
    abs2(x) > big(0) || abs2(x) == big(0)
end

@test begin
    x = random(Nlplex{BigInt})
    y = random(Nlplex{BigInt})
    l = abs2(x * y)
    r = abs2(x) * abs2(y)
    l == r
end

@test_throws ErrorException begin
    inv(Nlplex(0, 0.0))
end

@test_throws ErrorException begin
    random(Nlplex{Int}) / 0
end

@test_throws ErrorException begin
    0 \ random(Nlplex{Int})
end

@test begin
    a = Plexifications.randomBigRational()
    z = random(Nlplex{Rational{BigInt}})
    l = z / a
    r = a \ z
    l == r
end

@test begin
    a = Plexifications.randomBigRational()
    z = random(Nlplex{Rational{BigInt}})
    l = a / z
    r = z \ a
    l == r
end

@test begin
    z = random(Nlplex{BigInt})
    z == z + zero(Nlplex{BigInt})
end

@test begin
    z = random(Nlplex{BigInt})
    z == z * one(Nlplex{BigInt})
end

@test begin
    z = random(Nlplex{BigInt})
    z == z + zero(z)
end

@test begin
    z = random(Nlplex{BigInt})
    z == z * one(z)
end

ext: jl


text:
# Automatically generated using Clang.jl

const NVML_API_VERSION = 11
const NVML_API_VERSION_STR = "11"

const NVML_VALUE_NOT_AVAILABLE = -1
const NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE = 32
const NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE = 16
const NVML_DEVICE_PCI_BUS_ID_LEGACY_FMT = "%04X:%02X:%02X.0"
const NVML_DEVICE_PCI_BUS_ID_FMT = "%08X:%02X:%02X.0"

# Skipping MacroDefinition: NVML_DEVICE_PCI_BUS_ID_FMT_ARGS ( pciInfo ) ( pciInfo ) -> domain , ( pciInfo ) -> bus , ( pciInfo ) -> device

const NVML_NVLINK_MAX_LINKS = 12

@cenum nvmlGpuLevel_enum::UInt32 begin
    NVML_TOPOLOGY_INTERNAL = 0
    NVML_TOPOLOGY_SINGLE = 10
    NVML_TOPOLOGY_MULTIPLE = 20
    NVML_TOPOLOGY_HOSTBRIDGE = 30
    NVML_TOPOLOGY_NODE = 40
    NVML_TOPOLOGY_SYSTEM = 50
end

const NVML_TOPOLOGY_CPU = NVML_TOPOLOGY_NODE
const NVML_MAX_PHYSICAL_BRIDGE = 128
const nvmlFlagDefault = 0x00
const nvmlFlagForce = 0x01

@cenum nvmlMemoryErrorType_enum::UInt32 begin
    NVML_MEMORY_ERROR_TYPE_CORRECTED = 0
    NVML_MEMORY_ERROR_TYPE_UNCORRECTED = 1
    NVML_MEMORY_ERROR_TYPE_COUNT = 2
end

const nvmlMemoryErrorType_t = nvmlMemoryErrorType_enum
const nvmlEccBitType_t = nvmlMemoryErrorType_t
const NVML_SINGLE_BIT_ECC = NVML_MEMORY_ERROR_TYPE_CORRECTED
const NVML_DOUBLE_BIT_ECC = NVML_MEMORY_ERROR_TYPE_UNCORRECTED
const NVML_GRID_LICENSE_BUFFER_SIZE = 128
const NVML_VGPU_NAME_BUFFER_SIZE = 64
const NVML_GRID_LICENSE_FEATURE_MAX_COUNT = 3
const INVALID_GPU_INSTANCE_PROFILE_ID = Float32(0x0fffffff)
const INVALID_GPU_INSTANCE_ID = Float32(0x0fffffff)

# Skipping MacroDefinition: NVML_VGPU_VIRTUALIZATION_CAP_MIGRATION 0 : 0

const NVML_VGPU_VIRTUALIZATION_CAP_MIGRATION_NO = 0x00
const NVML_VGPU_VIRTUALIZATION_CAP_MIGRATION_YES = 0x01

# Skipping MacroDefinition: NVML_VGPU_PGPU_VIRTUALIZATION_CAP_MIGRATION 0 : 0

const NVML_VGPU_PGPU_VIRTUALIZATION_CAP_MIGRATION_NO = 0x00
const NVML_VGPU_PGPU_VIRTUALIZATION_CAP_MIGRATION_YES = 0x01
const NVML_DEVICE_ARCH_KEPLER = 2
const NVML_DEVICE_ARCH_MAXWELL = 3
const NVML_DEVICE_ARCH_PASCAL = 4
const NVML_DEVICE_ARCH_VOLTA = 5
const NVML_DEVICE_ARCH_TURING = 6
const NVML_DEVICE_ARCH_AMPERE = 7
const NVML_DEVICE_ARCH_UNKNOWN = Float32(0x0fffffff)
const NVML_FI_DEV_ECC_CURRENT = 1
const NVML_FI_DEV_ECC_PENDING = 2
const NVML_FI_DEV_ECC_SBE_VOL_TOTAL = 3
const NVML_FI_DEV_ECC_DBE_VOL_TOTAL = 4
const NVML_FI_DEV_ECC_SBE_AGG_TOTAL = 5
const NVML_FI_DEV_ECC_DBE_AGG_TOTAL = 6
const NVML_FI_DEV_ECC_SBE_VOL_L1 = 7
const NVML_FI_DEV_ECC_DBE_VOL_L1 = 8
const NVML_FI_DEV_ECC_SBE_VOL_L2 = 9
const NVML_FI_DEV_ECC_DBE_VOL_L2 = 10
const NVML_FI_DEV_ECC_SBE_VOL_DEV = 11
const NVML_FI_DEV_ECC_DBE_VOL_DEV = 12
const NVML_FI_DEV_ECC_SBE_VOL_REG = 13
const NVML_FI_DEV_ECC_DBE_VOL_REG = 14
const NVML_FI_DEV_ECC_SBE_VOL_TEX = 15
const NVML_FI_DEV_ECC_DBE_VOL_TEX = 16
const NVML_FI_DEV_ECC_DBE_VOL_CBU = 17
const NVML_FI_DEV_ECC_SBE_AGG_L1 = 18
const NVML_FI_DEV_ECC_DBE_AGG_L1 = 19
const NVML_FI_DEV_ECC_SBE_AGG_L2 = 20
const NVML_FI_DEV_ECC_DBE_AGG_L2 = 21
const NVML_FI_DEV_ECC_SBE_AGG_DEV = 22
const NVML_FI_DEV_ECC_DBE_AGG_DEV = 23
const NVML_FI_DEV_ECC_SBE_AGG_REG = 24
const NVML_FI_DEV_ECC_DBE_AGG_REG = 25
const NVML_FI_DEV_ECC_SBE_AGG_TEX = 26
const NVML_FI_DEV_ECC_DBE_AGG_TEX = 27
const NVML_FI_DEV_ECC_DBE_AGG_CBU = 28
const NVML_FI_DEV_RETIRED_SBE = 29
const NVML_FI_DEV_RETIRED_DBE = 30
const NVML_FI_DEV_RETIRED_PENDING = 31
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L0 = 32
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L1 = 33
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L2 = 34
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L3 = 35
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L4 = 36
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L5 = 37
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_TOTAL = 38
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L0 = 39
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L1 = 40
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L2 = 41
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L3 = 42
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L4 = 43
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L5 = 44
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_TOTAL = 45
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L0 = 46
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L1 = 47
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L2 = 48
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L3 = 49
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L4 = 50
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L5 = 51
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_TOTAL = 52
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L0 = 53
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L1 = 54
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L2 = 55
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L3 = 56
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L4 = 57
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L5 = 58
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_TOTAL = 59
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L0 = 60
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L1 = 61
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L2 = 62
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L3 = 63
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L4 = 64
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L5 = 65
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_TOTAL = 66
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L0 = 67
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L1 = 68
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L2 = 69
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L3 = 70
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L4 = 71
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L5 = 72
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_TOTAL = 73
const NVML_FI_DEV_PERF_POLICY_POWER = 74
const NVML_FI_DEV_PERF_POLICY_THERMAL = 75
const NVML_FI_DEV_PERF_POLICY_SYNC_BOOST = 76
const NVML_FI_DEV_PERF_POLICY_BOARD_LIMIT = 77
const NVML_FI_DEV_PERF_POLICY_LOW_UTILIZATION = 78
const NVML_FI_DEV_PERF_POLICY_RELIABILITY = 79
const NVML_FI_DEV_PERF_POLICY_TOTAL_APP_CLOCKS = 80
const NVML_FI_DEV_PERF_POLICY_TOTAL_BASE_CLOCKS = 81
const NVML_FI_DEV_MEMORY_TEMP = 82
const NVML_FI_DEV_TOTAL_ENERGY_CONSUMPTION = 83
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L0 = 84
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L1 = 85
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L2 = 86
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L3 = 87
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L4 = 88
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L5 = 89
const NVML_FI_DEV_NVLINK_SPEED_MBPS_COMMON = 90
const NVML_FI_DEV_NVLINK_LINK_COUNT = 91
const NVML_FI_DEV_RETIRED_PENDING_SBE = 92
const NVML_FI_DEV_RETIRED_PENDING_DBE = 93
const NVML_FI_DEV_PCIE_REPLAY_COUNTER = 94
const NVML_FI_DEV_PCIE_REPLAY_ROLLOVER_COUNTER = 95
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L6 = 96
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L7 = 97
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L8 = 98
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L9 = 99
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L10 = 100
const NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L11 = 101
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L6 = 102
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L7 = 103
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L8 = 104
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L9 = 105
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L10 = 106
const NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L11 = 107
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L6 = 108
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L7 = 109
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L8 = 110
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L9 = 111
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L10 = 112
const NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L11 = 113
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L6 = 114
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L7 = 115
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L8 = 116
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L9 = 117
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L10 = 118
const NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L11 = 119
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L6 = 120
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L7 = 121
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L8 = 122
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L9 = 123
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L10 = 124
const NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L11 = 125
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L6 = 126
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L7 = 127
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L8 = 128
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L9 = 129
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L10 = 130
const NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L11 = 131
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L6 = 132
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L7 = 133
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L8 = 134
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L9 = 135
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L10 = 136
const NVML_FI_DEV_NVLINK_SPEED_MBPS_L11 = 137
const NVML_FI_DEV_NVLINK_THROUGHPUT_DATA_TX = 138
const NVML_FI_DEV_NVLINK_THROUGHPUT_DATA_RX = 139
const NVML_FI_DEV_NVLINK_THROUGHPUT_RAW_TX = 140
const NVML_FI_DEV_NVLINK_THROUGHPUT_RAW_RX = 141
const NVML_FI_DEV_REMAPPED_COR = 142
const NVML_FI_DEV_REMAPPED_UNC = 143
const NVML_FI_DEV_REMAPPED_PENDING = 144
const NVML_FI_DEV_REMAPPED_FAILURE = 145
const NVML_FI_DEV_NVLINK_REMOTE_NVLINK_ID = 146
const NVML_FI_DEV_NVSWITCH_CONNECTED_LINK_COUNT = 147
const NVML_FI_MAX = 148
const nvmlEventTypeSingleBitEccError = Int64(0x0000000000000001)
const nvmlEventTypeDoubleBitEccError = Int64(0x0000000000000002)
const nvmlEventTypePState = Int64(0x0000000000000004)
const nvmlEventTypeXidCriticalError = Int64(0x0000000000000008)
const nvmlEventTypeClock = Int64(0x0000000000000010)
const nvmlEventTypePowerSourceChange = Int64(0x0000000000000080)
const nvmlEventMigConfigChange = Int64(0x0000000000000100)
const nvmlEventTypeNone = Int64(0x0000000000000000)
const nvmlEventTypeAll = ((((((nvmlEventTypeNone | nvmlEventTypeSingleBitEccError) | nvmlEventTypeDoubleBitEccError) | nvmlEventTypePState) | nvmlEventTypeClock) | nvmlEventTypeXidCriticalError) | nvmlEventTypePowerSourceChange) | nvmlEventMigConfigChange
const nvmlClocksThrottleReasonGpuIdle = Int64(0x0000000000000001)
const nvmlClocksThrottleReasonApplicationsClocksSetting = Int64(0x0000000000000002)
const nvmlClocksThrottleReasonUserDefinedClocks = nvmlClocksThrottleReasonApplicationsClocksSetting
const nvmlClocksThrottleReasonSwPowerCap = Int64(0x0000000000000004)
const nvmlClocksThrottleReasonHwSlowdown = Int64(0x0000000000000008)
const nvmlClocksThrottleReasonSyncBoost = Int64(0x0000000000000010)
const nvmlClocksThrottleReasonSwThermalSlowdown = Int64(0x0000000000000020)
const nvmlClocksThrottleReasonHwThermalSlowdown = Int64(0x0000000000000040)
const nvmlClocksThrottleReasonHwPowerBrakeSlowdown = Int64(0x0000000000000080)
const nvmlClocksThrottleReasonDisplayClockSetting = Int64(0x0000000000000100)
const nvmlClocksThrottleReasonNone = Int64(0x0000000000000000)

# Skipping MacroDefinition: nvmlClocksThrottleReasonAll ( nvmlClocksThrottleReasonNone | nvmlClocksThrottleReasonGpuIdle | nvmlClocksThrottleReasonApplicationsClocksSetting | nvmlClocksThrottleReasonSwPowerCap | nvmlClocksThrottleReasonHwSlowdown | nvmlClocksThrottleReasonSyncBoost | nvmlClocksThrottleReasonSwThermalSlowdown | nvmlClocksThrottleReasonHwThermalSlowdown | nvmlClocksThrottleReasonHwPowerBrakeSlowdown | nvmlClocksThrottleReasonDisplayClockSetting \
#)

const NVML_NVFBC_SESSION_FLAG_DIFFMAP_ENABLED = 0x00000001
const NVML_NVFBC_SESSION_FLAG_CLASSIFICATIONMAP_ENABLED = 0x00000002
const NVML_NVFBC_SESSION_FLAG_CAPTURE_WITH_WAIT_NO_WAIT = 0x00000004
const NVML_NVFBC_SESSION_FLAG_CAPTURE_WITH_WAIT_INFINITE = 0x00000008
const NVML_NVFBC_SESSION_FLAG_CAPTURE_WITH_WAIT_TIMEOUT = 0x00000010
const NVML_INIT_FLAG_NO_GPUS = 1
const NVML_INIT_FLAG_NO_ATTACH = 2
const NVML_DEVICE_INFOROM_VERSION_BUFFER_SIZE = 16
const NVML_DEVICE_UUID_BUFFER_SIZE = 80
const NVML_DEVICE_UUID_V2_BUFFER_SIZE = 96
const NVML_DEVICE_PART_NUMBER_BUFFER_SIZE = 80
const NVML_SYSTEM_DRIVER_VERSION_BUFFER_SIZE = 80
const NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE = 80
const NVML_DEVICE_NAME_BUFFER_SIZE = 64
const NVML_DEVICE_NAME_V2_BUFFER_SIZE = 96
const NVML_DEVICE_SERIAL_BUFFER_SIZE = 30
const NVML_DEVICE_VBIOS_VERSION_BUFFER_SIZE = 32

# Skipping MacroDefinition: NVML_CUDA_DRIVER_VERSION_MAJOR ( v ) ( ( v ) / 1000 )
# Skipping MacroDefinition: NVML_CUDA_DRIVER_VERSION_MINOR ( v ) ( ( ( v ) % 1000 ) / 10 )

const NVML_AFFINITY_SCOPE_NODE = 0
const NVML_AFFINITY_SCOPE_SOCKET = 1
const NVML_DEVICE_MIG_DISABLE = 0x00
const NVML_DEVICE_MIG_ENABLE = 0x01
const NVML_GPU_INSTANCE_PROFILE_1_SLICE = 0x00
const NVML_GPU_INSTANCE_PROFILE_2_SLICE = 0x01
const NVML_GPU_INSTANCE_PROFILE_3_SLICE = 0x02
const NVML_GPU_INSTANCE_PROFILE_4_SLICE = 0x03
const NVML_GPU_INSTANCE_PROFILE_7_SLICE = 0x04
const NVML_GPU_INSTANCE_PROFILE_8_SLICE = 0x05
const NVML_GPU_INSTANCE_PROFILE_6_SLICE = 0x06
const NVML_GPU_INSTANCE_PROFILE_COUNT = 0x07
const NVML_COMPUTE_INSTANCE_PROFILE_1_SLICE = 0x00
const NVML_COMPUTE_INSTANCE_PROFILE_2_SLICE = 0x01
const NVML_COMPUTE_INSTANCE_PROFILE_3_SLICE = 0x02
const NVML_COMPUTE_INSTANCE_PROFILE_4_SLICE = 0x03
const NVML_COMPUTE_INSTANCE_PROFILE_7_SLICE = 0x04
const NVML_COMPUTE_INSTANCE_PROFILE_8_SLICE = 0x05
const NVML_COMPUTE_INSTANCE_PROFILE_6_SLICE = 0x06
const NVML_COMPUTE_INSTANCE_PROFILE_COUNT = 0x07
const NVML_COMPUTE_INSTANCE_ENGINE_PROFILE_SHARED = 0x00
const NVML_COMPUTE_INSTANCE_ENGINE_PROFILE_COUNT = 0x01
const nvmlDevice_st = Cvoid
const nvmlDevice_t = Ptr{nvmlDevice_st}

struct nvmlPciInfo_st
    busIdLegacy::NTuple{16, UInt8}
    domain::UInt32
    bus::UInt32
    device::UInt32
    pciDeviceId::UInt32
    pciSubSystemId::UInt32
    busId::NTuple{32, UInt8}
end

const nvmlPciInfo_t = nvmlPciInfo_st

struct nvmlEccErrorCounts_st
    l1Cache::Culonglong
    l2Cache::Culonglong
    deviceMemory::Culonglong
    registerFile::Culonglong
end

const nvmlEccErrorCounts_t = nvmlEccErrorCounts_st

struct nvmlUtilization_st
    gpu::UInt32
    memory::UInt32
end

const nvmlUtilization_t = nvmlUtilization_st

struct nvmlMemory_st
    total::Culonglong
    free::Culonglong
    used::Culonglong
end

const nvmlMemory_t = nvmlMemory_st

struct nvmlBAR1Memory_st
    bar1Total::Culonglong
    bar1Free::Culonglong
    bar1Used::Culonglong
end

const nvmlBAR1Memory_t = nvmlBAR1Memory_st

struct nvmlProcessInfo_st
    pid::UInt32
    usedGpuMemory::Culonglong
    gpuInstanceId::UInt32
    computeInstanceId::UInt32
end

const nvmlProcessInfo_t = nvmlProcessInfo_st

struct nvmlDeviceAttributes_st
    multiprocessorCount::UInt32
    sharedCopyEngineCount::UInt32
    sharedDecoderCount::UInt32
    sharedEncoderCount::UInt32
    sharedJpegCount::UInt32
    sharedOfaCount::UInt32
    gpuInstanceSliceCount::UInt32
    computeInstanceSliceCount::UInt32
    memorySizeMB::Culonglong
end

const nvmlDeviceAttributes_t = nvmlDeviceAttributes_st

struct nvmlRowRemapperHistogramValues_st
    max::UInt32
    high::UInt32
    partial::UInt32
    low::UInt32
    none::UInt32
end

const nvmlRowRemapperHistogramValues_t = nvmlRowRemapperHistogramValues_st

@cenum nvmlBridgeChipType_enum::UInt32 begin
    NVML_BRIDGE_CHIP_PLX = 0
    NVML_BRIDGE_CHIP_BRO4 = 1
end

const nvmlBridgeChipType_t = nvmlBridgeChipType_enum

@cenum nvmlNvLinkUtilizationCountUnits_enum::UInt32 begin
    NVML_NVLINK_COUNTER_UNIT_CYCLES = 0
    NVML_NVLINK_COUNTER_UNIT_PACKETS = 1
    NVML_NVLINK_COUNTER_UNIT_BYTES = 2
    NVML_NVLINK_COUNTER_UNIT_RESERVED = 3
    NVML_NVLINK_COUNTER_UNIT_COUNT = 4
end

const nvmlNvLinkUtilizationCountUnits_t = nvmlNvLinkUtilizationCountUnits_enum

@cenum nvmlNvLinkUtilizationCountPktTypes_enum::UInt32 begin
    NVML_NVLINK_COUNTER_PKTFILTER_NOP = 1
    NVML_NVLINK_COUNTER_PKTFILTER_READ = 2
    NVML_NVLINK_COUNTER_PKTFILTER_WRITE = 4
    NVML_NVLINK_COUNTER_PKTFILTER_RATOM = 8
    NVML_NVLINK_COUNTER_PKTFILTER_NRATOM = 16
    NVML_NVLINK_COUNTER_PKTFILTER_FLUSH = 32
    NVML_NVLINK_COUNTER_PKTFILTER_RESPDATA = 64
    NVML_NVLINK_COUNTER_PKTFILTER_RESPNODATA = 128
    NVML_NVLINK_COUNTER_PKTFILTER_ALL = 255
end

const nvmlNvLinkUtilizationCountPktTypes_t = nvmlNvLinkUtilizationCountPktTypes_enum

struct nvmlNvLinkUtilizationControl_st
    units::nvmlNvLinkUtilizationCountUnits_t
    pktfilter::nvmlNvLinkUtilizationCountPktTypes_t
end

const nvmlNvLinkUtilizationControl_t = nvmlNvLinkUtilizationControl_st

@cenum nvmlNvLinkCapability_enum::UInt32 begin
    NVML_NVLINK_CAP_P2P_SUPPORTED = 0
    NVML_NVLINK_CAP_SYSMEM_ACCESS = 1
    NVML_NVLINK_CAP_P2P_ATOMICS = 2
    NVML_NVLINK_CAP_SYSMEM_ATOMICS = 3
    NVML_NVLINK_CAP_SLI_BRIDGE = 4
    NVML_NVLINK_CAP_VALID = 5
    NVML_NVLINK_CAP_COUNT = 6
end

const nvmlNvLinkCapability_t = nvmlNvLinkCapability_enum

@cenum nvmlNvLinkErrorCounter_enum::UInt32 begin
    NVML_NVLINK_ERROR_DL_REPLAY = 0
    NVML_NVLINK_ERROR_DL_RECOVERY = 1
    NVML_NVLINK_ERROR_DL_CRC_FLIT = 2
    NVML_NVLINK_ERROR_DL_CRC_DATA = 3
    NVML_NVLINK_ERROR_COUNT = 4
end

const nvmlNvLinkErrorCounter_t = nvmlNvLinkErrorCounter_enum
const nvmlGpuTopologyLevel_t = nvmlGpuLevel_enum

@cenum nvmlGpuP2PStatus_enum::UInt32 begin
    NVML_P2P_STATUS_OK = 0
    NVML_P2P_STATUS_CHIPSET_NOT_SUPPORED = 1
    NVML_P2P_STATUS_GPU_NOT_SUPPORTED = 2
    NVML_P2P_STATUS_IOH_TOPOLOGY_NOT_SUPPORTED = 3
    NVML_P2P_STATUS_DISABLED_BY_REGKEY = 4
    NVML_P2P_STATUS_NOT_SUPPORTED = 5
    NVML_P2P_STATUS_UNKNOWN = 6
end

const nvmlGpuP2PStatus_t = nvmlGpuP2PStatus_enum

@cenum nvmlGpuP2PCapsIndex_enum::UInt32 begin
    NVML_P2P_CAPS_INDEX_READ = 0
    NVML_P2P_CAPS_INDEX_WRITE = 1
    NVML_P2P_CAPS_INDEX_NVLINK = 2
    NVML_P2P_CAPS_INDEX_ATOMICS = 3
    NVML_P2P_CAPS_INDEX_PROP = 4
    NVML_P2P_CAPS_INDEX_UNKNOWN = 5
end

const nvmlGpuP2PCapsIndex_t = nvmlGpuP2PCapsIndex_enum

struct nvmlBridgeChipInfo_st
    type::nvmlBridgeChipType_t
    fwVersion::UInt32
end

const nvmlBridgeChipInfo_t = nvmlBridgeChipInfo_st

struct nvmlBridgeChipHierarchy_st
    bridgeCount::Cuchar
    bridgeChipInfo::NTuple{128, nvmlBridgeChipInfo_t}
end

const nvmlBridgeChipHierarchy_t = nvmlBridgeChipHierarchy_st

@cenum nvmlSamplingType_enum::UInt32 begin
    NVML_TOTAL_POWER_SAMPLES = 0
    NVML_GPU_UTILIZATION_SAMPLES = 1
    NVML_MEMORY_UTILIZATION_SAMPLES = 2
    NVML_ENC_UTILIZATION_SAMPLES = 3
    NVML_DEC_UTILIZATION_SAMPLES = 4
    NVML_PROCESSOR_CLK_SAMPLES = 5
    NVML_MEMORY_CLK_SAMPLES = 6
    NVML_SAMPLINGTYPE_COUNT = 7
end

const nvmlSamplingType_t = nvmlSamplingType_enum

@cenum nvmlPcieUtilCounter_enum::UInt32 begin
    NVML_PCIE_UTIL_TX_BYTES = 0
    NVML_PCIE_UTIL_RX_BYTES = 1
    NVML_PCIE_UTIL_COUNT = 2
end

const nvmlPcieUtilCounter_t = nvmlPcieUtilCounter_enum

@cenum nvmlValueType_enum::UInt32 begin
    NVML_VALUE_TYPE_DOUBLE = 0
    NVML_VALUE_TYPE_UNSIGNED_INT = 1
    NVML_VALUE_TYPE_UNSIGNED_LONG = 2
    NVML_VALUE_TYPE_UNSIGNED_LONG_LONG = 3
    NVML_VALUE_TYPE_SIGNED_LONG_LONG = 4
    NVML_VALUE_TYPE_COUNT = 5
end

const nvmlValueType_t = nvmlValueType_enum

struct nvmlValue_st
    dVal::Cdouble
end

const nvmlValue_t = nvmlValue_st

struct nvmlSample_st
    timeStamp::Culonglong
    sampleValue::nvmlValue_t
end

const nvmlSample_t = nvmlSample_st

@cenum nvmlPerfPolicyType_enum::UInt32 begin
    NVML_PERF_POLICY_POWER = 0
    NVML_PERF_POLICY_THERMAL = 1
    NVML_PERF_POLICY_SYNC_BOOST = 2
    NVML_PERF_POLICY_BOARD_LIMIT = 3
    NVML_PERF_POLICY_LOW_UTILIZATION = 4
    NVML_PERF_POLICY_RELIABILITY = 5
    NVML_PERF_POLICY_TOTAL_APP_CLOCKS = 10
    NVML_PERF_POLICY_TOTAL_BASE_CLOCKS = 11
    NVML_PERF_POLICY_COUNT = 12
end

const nvmlPerfPolicyType_t = nvmlPerfPolicyType_enum

struct nvmlViolationTime_st
    referenceTime::Culonglong
    violationTime::Culonglong
end

const nvmlViolationTime_t = nvmlViolationTime_st

@cenum nvmlEnableState_enum::UInt32 begin
    NVML_FEATURE_DISABLED = 0
    NVML_FEATURE_ENABLED = 1
end

const nvmlEnableState_t = nvmlEnableState_enum

@cenum nvmlBrandType_enum::UInt32 begin
    NVML_BRAND_UNKNOWN = 0
    NVML_BRAND_QUADRO = 1
    NVML_BRAND_TESLA = 2
    NVML_BRAND_NVS = 3
    NVML_BRAND_GRID = 4
    NVML_BRAND_GEFORCE = 5
    NVML_BRAND_TITAN = 6
    NVML_BRAND_NVIDIA_VAPPS = 7
    NVML_BRAND_NVIDIA_VPC = 8
    NVML_BRAND_NVIDIA_VCS = 9
    NVML_BRAND_NVIDIA_VWS = 10
    NVML_BRAND_NVIDIA_VGAMING = 11
    NVML_BRAND_QUADRO_RTX = 12
    NVML_BRAND_NVIDIA_RTX = 13
    NVML_BRAND_NVIDIA = 14
    NVML_BRAND_GEFORCE_RTX = 15
    NVML_BRAND_TITAN_RTX = 16
    NVML_BRAND_COUNT = 17
end

const nvmlBrandType_t = nvmlBrandType_enum

@cenum nvmlTemperatureThresholds_enum::UInt32 begin
    NVML_TEMPERATURE_THRESHOLD_SHUTDOWN = 0
    NVML_TEMPERATURE_THRESHOLD_SLOWDOWN = 1
    NVML_TEMPERATURE_THRESHOLD_MEM_MAX = 2
    NVML_TEMPERATURE_THRESHOLD_GPU_MAX = 3
    NVML_TEMPERATURE_THRESHOLD_ACOUSTIC_MIN = 4
    NVML_TEMPERATURE_THRESHOLD_ACOUSTIC_CURR = 5
    NVML_TEMPERATURE_THRESHOLD_ACOUSTIC_MAX = 6
    NVML_TEMPERATURE_THRESHOLD_COUNT = 7
end

const nvmlTemperatureThresholds_t = nvmlTemperatureThresholds_enum

@cenum nvmlTemperatureSensors_enum::UInt32 begin
    NVML_TEMPERATURE_GPU = 0
    NVML_TEMPERATURE_COUNT = 1
end

const nvmlTemperatureSensors_t = nvmlTemperatureSensors_enum

@cenum nvmlComputeMode_enum::UInt32 begin
    NVML_COMPUTEMODE_DEFAULT = 0
    NVML_COMPUTEMODE_EXCLUSIVE_THREAD = 1
    NVML_COMPUTEMODE_PROHIBITED = 2
    NVML_COMPUTEMODE_EXCLUSIVE_PROCESS = 3
    NVML_COMPUTEMODE_COUNT = 4
end

const nvmlComputeMode_t = nvmlComputeMode_enum

@cenum nvmlEccCounterType_enum::UInt32 begin
    NVML_VOLATILE_ECC = 0
    NVML_AGGREGATE_ECC = 1
    NVML_ECC_COUNTER_TYPE_COUNT = 2
end

const nvmlEccCounterType_t = nvmlEccCounterType_enum

@cenum nvmlClockType_enum::UInt32 begin
    NVML_CLOCK_GRAPHICS = 0
    NVML_CLOCK_SM = 1
    NVML_CLOCK_MEM = 2
    NVML_CLOCK_VIDEO = 3
    NVML_CLOCK_COUNT = 4
end

const nvmlClockType_t = nvmlClockType_enum

@cenum nvmlClockId_enum::UInt32 begin
    NVML_CLOCK_ID_CURRENT = 0
    NVML_CLOCK_ID_APP_CLOCK_TARGET = 1
    NVML_CLOCK_ID_APP_CLOCK_DEFAULT = 2
    NVML_CLOCK_ID_CUSTOMER_BOOST_MAX = 3
    NVML_CLOCK_ID_COUNT = 4
end

const nvmlClockId_t = nvmlClockId_enum

@cenum nvmlDriverModel_enum::UInt32 begin
    NVML_DRIVER_WDDM = 0
    NVML_DRIVER_WDM = 1
end

const nvmlDriverModel_t = nvmlDriverModel_enum

@cenum nvmlPStates_enum::UInt32 begin
    NVML_PSTATE_0 = 0
    NVML_PSTATE_1 = 1
    NVML_PSTATE_2 = 2
    NVML_PSTATE_3 = 3
    NVML_PSTATE_4 = 4
    NVML_PSTATE_5 = 5
    NVML_PSTATE_6 = 6
    NVML_PSTATE_7 = 7
    NVML_PSTATE_8 = 8
    NVML_PSTATE_9 = 9
    NVML_PSTATE_10 = 10
    NVML_PSTATE_11 = 11
    NVML_PSTATE_12 = 12
    NVML_PSTATE_13 = 13
    NVML_PSTATE_14 = 14
    NVML_PSTATE_15 = 15
    NVML_PSTATE_UNKNOWN = 32
end

const nvmlPstates_t = nvmlPStates_enum

@cenum nvmlGom_enum::UInt32 begin
    NVML_GOM_ALL_ON = 0
    NVML_GOM_COMPUTE = 1
    NVML_GOM_LOW_DP = 2
end

const nvmlGpuOperationMode_t = nvmlGom_enum

@cenum nvmlInforomObject_enum::UInt32 begin
    NVML_INFOROM_OEM = 0
    NVML_INFOROM_ECC = 1
    NVML_INFOROM_POWER = 2
    NVML_INFOROM_COUNT = 3
end

const nvmlInforomObject_t = nvmlInforomObject_enum

@cenum nvmlReturn_enum::UInt32 begin
    NVML_SUCCESS = 0
    NVML_ERROR_UNINITIALIZED = 1
    NVML_ERROR_INVALID_ARGUMENT = 2
    NVML_ERROR_NOT_SUPPORTED = 3
    NVML_ERROR_NO_PERMISSION = 4
    NVML_ERROR_ALREADY_INITIALIZED = 5
    NVML_ERROR_NOT_FOUND = 6
    NVML_ERROR_INSUFFICIENT_SIZE = 7
    NVML_ERROR_INSUFFICIENT_POWER = 8
    NVML_ERROR_DRIVER_NOT_LOADED = 9
    NVML_ERROR_TIMEOUT = 10
    NVML_ERROR_IRQ_ISSUE = 11
    NVML_ERROR_LIBRARY_NOT_FOUND = 12
    NVML_ERROR_FUNCTION_NOT_FOUND = 13
    NVML_ERROR_CORRUPTED_INFOROM = 14
    NVML_ERROR_GPU_IS_LOST = 15
    NVML_ERROR_RESET_REQUIRED = 16
    NVML_ERROR_OPERATING_SYSTEM = 17
    NVML_ERROR_LIB_RM_VERSION_MISMATCH = 18
    NVML_ERROR_IN_USE = 19
    NVML_ERROR_MEMORY = 20
    NVML_ERROR_NO_DATA = 21
    NVML_ERROR_VGPU_ECC_NOT_SUPPORTED = 22
    NVML_ERROR_INSUFFICIENT_RESOURCES = 23
    NVML_ERROR_UNKNOWN = 999
end

const nvmlReturn_t = nvmlReturn_enum

@cenum nvmlMemoryLocation_enum::UInt32 begin
    NVML_MEMORY_LOCATION_L1_CACHE = 0
    NVML_MEMORY_LOCATION_L2_CACHE = 1
    NVML_MEMORY_LOCATION_DRAM = 2
    NVML_MEMORY_LOCATION_DEVICE_MEMORY = 2
    NVML_MEMORY_LOCATION_REGISTER_FILE = 3
    NVML_MEMORY_LOCATION_TEXTURE_MEMORY = 4
    NVML_MEMORY_LOCATION_TEXTURE_SHM = 5
    NVML_MEMORY_LOCATION_CBU = 6
    NVML_MEMORY_LOCATION_SRAM = 7
    NVML_MEMORY_LOCATION_COUNT = 8
end

const nvmlMemoryLocation_t = nvmlMemoryLocation_enum

@cenum nvmlPageRetirementCause_enum::UInt32 begin
    NVML_PAGE_RETIREMENT_CAUSE_MULTIPLE_SINGLE_BIT_ECC_ERRORS = 0
    NVML_PAGE_RETIREMENT_CAUSE_DOUBLE_BIT_ECC_ERROR = 1
    NVML_PAGE_RETIREMENT_CAUSE_COUNT = 2
end

const nvmlPageRetirementCause_t = nvmlPageRetirementCause_enum

@cenum nvmlRestrictedAPI_enum::UInt32 begin
    NVML_RESTRICTED_API_SET_APPLICATION_CLOCKS = 0
    NVML_RESTRICTED_API_SET_AUTO_BOOSTED_CLOCKS = 1
    NVML_RESTRICTED_API_COUNT = 2
end

const nvmlRestrictedAPI_t = nvmlRestrictedAPI_enum

@cenum nvmlGpuVirtualizationMode::UInt32 begin
    NVML_GPU_VIRTUALIZATION_MODE_NONE = 0
    NVML_GPU_VIRTUALIZATION_MODE_PASSTHROUGH = 1
    NVML_GPU_VIRTUALIZATION_MODE_VGPU = 2
    NVML_GPU_VIRTUALIZATION_MODE_HOST_VGPU = 3
    NVML_GPU_VIRTUALIZATION_MODE_HOST_VSGA = 4
end

const nvmlGpuVirtualizationMode_t = nvmlGpuVirtualizationMode

@cenum nvmlHostVgpuMode_enum::UInt32 begin
    NVML_HOST_VGPU_MODE_NON_SRIOV = 0
    NVML_HOST_VGPU_MODE_SRIOV = 1
end

const nvmlHostVgpuMode_t = nvmlHostVgpuMode_enum

@cenum nvmlVgpuVmIdType::UInt32 begin
    NVML_VGPU_VM_ID_DOMAIN_ID = 0
    NVML_VGPU_VM_ID_UUID = 1
end

const nvmlVgpuVmIdType_t = nvmlVgpuVmIdType

@cenum nvmlVgpuGuestInfoState_enum::UInt32 begin
    NVML_VGPU_INSTANCE_GUEST_INFO_STATE_UNINITIALIZED = 0
    NVML_VGPU_INSTANCE_GUEST_INFO_STATE_INITIALIZED = 1
end

const nvmlVgpuGuestInfoState_t = nvmlVgpuGuestInfoState_enum

@cenum nvmlGridLicenseFeatureCode_t::UInt32 begin
    NVML_GRID_LICENSE_FEATURE_CODE_VGPU = 1
    NVML_GRID_LICENSE_FEATURE_CODE_VWORKSTATION = 2
end

const nvmlVgpuTypeId_t = UInt32
const nvmlVgpuInstance_t = UInt32

struct nvmlVgpuInstanceUtilizationSample_st
    vgpuInstance::nvmlVgpuInstance_t
    timeStamp::Culonglong
    smUtil::nvmlValue_t
    memUtil::nvmlValue_t
    encUtil::nvmlValue_t
    decUtil::nvmlValue_t
end

const nvmlVgpuInstanceUtilizationSample_t = nvmlVgpuInstanceUtilizationSample_st

struct nvmlVgpuProcessUtilizationSample_st
    vgpuInstance::nvmlVgpuInstance_t
    pid::UInt32
    processName::NTuple{64, UInt8}
    timeStamp::Culonglong
    smUtil::UInt32
    memUtil::UInt32
    encUtil::UInt32
    decUtil::UInt32
end

const nvmlVgpuProcessUtilizationSample_t = nvmlVgpuProcessUtilizationSample_st

struct nvmlProcessUtilizationSample_st
    pid::UInt32
    timeStamp::Culonglong
    smUtil::UInt32
    memUtil::UInt32
    encUtil::UInt32
    decUtil::UInt32
end

const nvmlProcessUtilizationSample_t = nvmlProcessUtilizationSample_st

struct nvmlGridLicensableFeature_st
    featureCode::nvmlGridLicenseFeatureCode_t
    featureState::UInt32
    licenseInfo::NTuple{128, UInt8}
    productName::NTuple{128, UInt8}
    featureEnabled::UInt32
end

const nvmlGridLicensableFeature_t = nvmlGridLicensableFeature_st

struct nvmlGridLicensableFeatures_st
    isGridLicenseSupported::Cint
    licensableFeaturesCount::UInt32
    gridLicensableFeatures::NTuple{3, nvmlGridLicensableFeature_t}
end

const nvmlGridLicensableFeatures_t = nvmlGridLicensableFeatures_st
const nvmlDeviceArchitecture_t = UInt32

struct nvmlFieldValue_st
    fieldId::UInt32
    scopeId::UInt32
    timestamp::Clonglong
    latencyUsec::Clonglong
    valueType::nvmlValueType_t
    nvmlReturn::nvmlReturn_t
    value::nvmlValue_t
end

const nvmlFieldValue_t = nvmlFieldValue_st
const nvmlUnit_st = Cvoid
const nvmlUnit_t = Ptr{nvmlUnit_st}

struct nvmlHwbcEntry_st
    hwbcId::UInt32
    firmwareVersion::NTuple{32, UInt8}
end

const nvmlHwbcEntry_t = nvmlHwbcEntry_st

@cenum nvmlFanState_enum::UInt32 begin
    NVML_FAN_NORMAL = 0
    NVML_FAN_FAILED = 1
end

const nvmlFanState_t = nvmlFanState_enum

@cenum nvmlLedColor_enum::UInt32 begin
    NVML_LED_COLOR_GREEN = 0
    NVML_LED_COLOR_AMBER = 1
end

const nvmlLedColor_t = nvmlLedColor_enum

struct nvmlLedState_st
    cause::NTuple{256, UInt8}
    color::nvmlLedColor_t
end

const nvmlLedState_t = nvmlLedState_st

struct nvmlUnitInfo_st
    name::NTuple{96, UInt8}
    id::NTuple{96, UInt8}
    serial::NTuple{96, UInt8}
    firmwareVersion::NTuple{96, UInt8}
end

const nvmlUnitInfo_t = nvmlUnitInfo_st

struct nvmlPSUInfo_st
    state::NTuple{256, UInt8}
    current::UInt32
    voltage::UInt32
    power::UInt32
end

const nvmlPSUInfo_t = nvmlPSUInfo_st

struct nvmlUnitFanInfo_st
    speed::UInt32
    state::nvmlFanState_t
end

const nvmlUnitFanInfo_t = nvmlUnitFanInfo_st

struct nvmlUnitFanSpeeds_st
    fans::NTuple{24, nvmlUnitFanInfo_t}
    count::UInt32
end

const nvmlUnitFanSpeeds_t = nvmlUnitFanSpeeds_st
const nvmlEventSet_st = Cvoid
const nvmlEventSet_t = Ptr{nvmlEventSet_st}

struct nvmlEventData_st
    device::nvmlDevice_t
    eventType::Culonglong
    eventData::Culonglong
    gpuInstanceId::UInt32
    computeInstanceId::UInt32
end

const nvmlEventData_t = nvmlEventData_st

struct nvmlAccountingStats_st
    gpuUtilization::UInt32
    memoryUtilization::UInt32
    maxMemoryUsage::Culonglong
    time::Culonglong
    startTime::Culonglong
    isRunning::UInt32
    reserved::NTuple{5, UInt32}
end

const nvmlAccountingStats_t = nvmlAccountingStats_st

@cenum nvmlEncoderQueryType_enum::UInt32 begin
    NVML_ENCODER_QUERY_H264 = 0
    NVML_ENCODER_QUERY_HEVC = 1
end

const nvmlEncoderType_t = nvmlEncoderQueryType_enum

struct nvmlEncoderSessionInfo_st
    sessionId::UInt32
    pid::UInt32
    vgpuInstance::nvmlVgpuInstance_t
    codecType::nvmlEncoderType_t
    hResolution::UInt32
    vResolution::UInt32
    averageFps::UInt32
    averageLatency::UInt32
end

const nvmlEncoderSessionInfo_t = nvmlEncoderSessionInfo_st

@cenum nvmlFBCSessionType_enum::UInt32 begin
    NVML_FBC_SESSION_TYPE_UNKNOWN = 0
    NVML_FBC_SESSION_TYPE_TOSYS = 1
    NVML_FBC_SESSION_TYPE_CUDA = 2
    NVML_FBC_SESSION_TYPE_VID = 3
    NVML_FBC_SESSION_TYPE_HWENC = 4
end

const nvmlFBCSessionType_t = nvmlFBCSessionType_enum

struct nvmlFBCStats_st
    sessionsCount::UInt32
    averageFPS::UInt32
    averageLatency::UInt32
end

const nvmlFBCStats_t = nvmlFBCStats_st

struct nvmlFBCSessionInfo_st
    sessionId::UInt32
    pid::UInt32
    vgpuInstance::nvmlVgpuInstance_t
    displayOrdinal::UInt32
    sessionType::nvmlFBCSessionType_t
    sessionFlags::UInt32
    hMaxResolution::UInt32
    vMaxResolution::UInt32
    hResolution::UInt32
    vResolution::UInt32
    averageFPS::UInt32
    averageLatency::UInt32
end

const nvmlFBCSessionInfo_t = nvmlFBCSessionInfo_st

@cenum nvmlDetachGpuState_enum::UInt32 begin
    NVML_DETACH_GPU_KEEP = 0
    NVML_DETACH_GPU_REMOVE = 1
end

const nvmlDetachGpuState_t = nvmlDetachGpuState_enum

@cenum nvmlPcieLinkState_enum::UInt32 begin
    NVML_PCIE_LINK_KEEP = 0
    NVML_PCIE_LINK_SHUT_DOWN = 1
end

const nvmlPcieLinkState_t = nvmlPcieLinkState_enum
const nvmlAffinityScope_t = UInt32

@cenum nvmlClockLimitId_enum::UInt32 begin
    NVML_CLOCK_LIMIT_ID_RANGE_START = 4294967040
    NVML_CLOCK_LIMIT_ID_TDP = 4294967041
    NVML_CLOCK_LIMIT_ID_UNLIMITED = 4294967042
end

const nvmlClockLimitId_t = nvmlClockLimitId_enum

struct nvmlVgpuVersion_st
    minVersion::UInt32
    maxVersion::UInt32
end

const nvmlVgpuVersion_t = nvmlVgpuVersion_st

struct nvmlVgpuMetadata_st
    version::UInt32
    revision::UInt32
    guestInfoState::nvmlVgpuGuestInfoState_t
    guestDriverVersion::NTuple{80, UInt8}
    hostDriverVersion::NTuple{80, UInt8}
    reserved::NTuple{6, UInt32}
    vgpuVirtualizationCaps::UInt32
    guestVgpuVersion::UInt32
    opaqueDataSize::UInt32
    opaqueData::NTuple{4, UInt8}
end

const nvmlVgpuMetadata_t = nvmlVgpuMetadata_st

struct nvmlVgpuPgpuMetadata_st
    version::UInt32
    revision::UInt32
    hostDriverVersion::NTuple{80, UInt8}
    pgpuVirtualizationCaps::UInt32
    reserved::NTuple{5, UInt32}
    hostSupportedVgpuRange::nvmlVgpuVersion_t
    opaqueDataSize::UInt32
    opaqueData::NTuple{4, UInt8}
end

const nvmlVgpuPgpuMetadata_t = nvmlVgpuPgpuMetadata_st

@cenum nvmlVgpuVmCompatibility_enum::UInt32 begin
    NVML_VGPU_VM_COMPATIBILITY_NONE = 0
    NVML_VGPU_VM_COMPATIBILITY_COLD = 1
    NVML_VGPU_VM_COMPATIBILITY_HIBERNATE = 2
    NVML_VGPU_VM_COMPATIBILITY_SLEEP = 4
    NVML_VGPU_VM_COMPATIBILITY_LIVE = 8
end

const nvmlVgpuVmCompatibility_t = nvmlVgpuVmCompatibility_enum

@cenum nvmlVgpuPgpuCompatibilityLimitCode_enum::UInt32 begin
    NVML_VGPU_COMPATIBILITY_LIMIT_NONE = 0
    NVML_VGPU_COMPATIBILITY_LIMIT_HOST_DRIVER = 1
    NVML_VGPU_COMPATIBILITY_LIMIT_GUEST_DRIVER = 2
    NVML_VGPU_COMPATIBILITY_LIMIT_GPU = 4
    NVML_VGPU_COMPATIBILITY_LIMIT_OTHER = 2147483648
end

const nvmlVgpuPgpuCompatibilityLimitCode_t = nvmlVgpuPgpuCompatibilityLimitCode_enum

struct nvmlVgpuPgpuCompatibility_st
    vgpuVmCompatibility::nvmlVgpuVmCompatibility_t
    compatibilityLimitCode::nvmlVgpuPgpuCompatibilityLimitCode_t
end

const nvmlVgpuPgpuCompatibility_t = nvmlVgpuPgpuCompatibility_st

struct nvmlBlacklistDeviceInfo_st
    pciInfo::nvmlPciInfo_t
    uuid::NTuple{80, UInt8}
end

const nvmlBlacklistDeviceInfo_t = nvmlBlacklistDeviceInfo_st

struct nvmlGpuInstancePlacement_st
    start::UInt32
    size::UInt32
end

const nvmlGpuInstancePlacement_t = nvmlGpuInstancePlacement_st

struct nvmlGpuInstanceProfileInfo_st
    id::UInt32
    isP2pSupported::UInt32
    sliceCount::UInt32
    instanceCount::UInt32
    multiprocessorCount::UInt32
    copyEngineCount::UInt32
    decoderCount::UInt32
    encoderCount::UInt32
    jpegCount::UInt32
    ofaCount::UInt32
    memorySizeMB::Culonglong
end

const nvmlGpuInstanceProfileInfo_t = nvmlGpuInstanceProfileInfo_st

struct nvmlGpuInstanceInfo_st
    device::nvmlDevice_t
    id::UInt32
    profileId::UInt32
    placement::nvmlGpuInstancePlacement_t
end

const nvmlGpuInstanceInfo_t = nvmlGpuInstanceInfo_st
const nvmlGpuInstance_st = Cvoid
const nvmlGpuInstance_t = Ptr{nvmlGpuInstance_st}

struct nvmlComputeInstancePlacement_st
    start::UInt32
    size::UInt32
end

const nvmlComputeInstancePlacement_t = nvmlComputeInstancePlacement_st

struct nvmlComputeInstanceProfileInfo_st
    id::UInt32
    sliceCount::UInt32
    instanceCount::UInt32
    multiprocessorCount::UInt32
    sharedCopyEngineCount::UInt32
    sharedDecoderCount::UInt32
    sharedEncoderCount::UInt32
    sharedJpegCount::UInt32
    sharedOfaCount::UInt32
end

const nvmlComputeInstanceProfileInfo_t = nvmlComputeInstanceProfileInfo_st

struct nvmlComputeInstanceInfo_st
    device::nvmlDevice_t
    gpuInstance::nvmlGpuInstance_t
    id::UInt32
    profileId::UInt32
    placement::nvmlComputeInstancePlacement_t
end

const nvmlComputeInstanceInfo_t = nvmlComputeInstanceInfo_st
const nvmlComputeInstance_st = Cvoid
const nvmlComputeInstance_t = Ptr{nvmlComputeInstance_st}


text:
include("NamedViewVector.jl")

using DifferentialEquations
using LinearAlgebra: normalize, norm
using Plots

plotly()

# -- Constants -----------------------------------------------------------------------------
# Gravitational constant
const G0 = 9.80665

# -- Component equations -------------------------------------------------------------------
# Equations of motion
function EOM!(dx, x, p, t)
    @. dx.pos = x.vel
    @. dx.vel = p.F / p.mass
    return nothing
end

# Propellent mass equation
propellent(x, p, t) = -p.F / p.ISP / G0

# Velocity-aligned thrust
thrust_full(vel, ctrl) = ctrl.thrust_lim * normalize(vel)
thrust_off(vel, ctrl) = zero(vel)
function thrust_vel_limited(vel, ctrl)
    vel_mag = norm(vel)
    F = ctrl.k_p * (ctrl.vel_setpoint - vel_mag)
    return clamp(F, 0, ctrl.thrust_lim) / vel_mag * vel
end

# -- Full combined state equations ---------------------------------------------------------
function rocket!(dx, x, p, t)
    # Get force vector
    F = p.thrust(x.body.vel, p)
    F_mag = norm(F)
    F[end] -= G0 # Apply gravity

    # Run equations of motion!
    p_EOM = (F = F, mass = p.vehicle.dry_mass + x.prop_mass)
    EOM!(dx.body,x.body, p_EOM, t)

    # Run propellent equation
    p_prop = (ISP = p.vehicle.ISP, F = F_mag),
    dx.prop_mass = propellent(x.prop_mass, p_prop, t)

    return nothing
end

# -- Event handling ------------------------------------------------------------------------
# Hitting the ground stops the simulation
ground_cond(x, t, integrator) = x.body.pos[end]
ground_affect!(integrator) = terminate!(integrator)
ground_cb = ContinuousCallback(ground_cond, nothing, ground_affect!)

# Running out of propellent stops thrust
prop_cond(x, t, integrator) = x.prop_mass
prop_affect!(integrator) = (integrator.p.thrust = thrust_off)
prop_cb = ContinuousCallback(prop_cond, nothing, prop_affect!)

# Combine callbacks
cb = CallbackSet(ground_cb, prop_cb)

# -- Parameters ----------------------------------------------------------------------------
# Vehicle properties
p_vehicle = (
    dry_mass = 2.0,
    ISP = 150.0,
)

# Throttle control parameters
p_control = (
    thrust = thrust_vel_limited,
    thrust_lim = 100.0,
    vel_setpoint = 1000.0,
    k_p = 1.0,
)

# Parameters
p = (
    vehicle = p_vehicle,
    control = p_control,
)

# -- Initial conditions --------------------------------------------------------------------
# Vehicle body initial conditions
body₀ = (
    pos = [0.0, 0.0, 0.0],
    vel = [0.01, 0.02, 1.0],
)

# Full state initial conditions
vehicle₀ = (
    body = body₀,
    prop_mass = 7.0,
)

# -- Simulation setup ----------------------------------------------------------------------
# Simulation time span
tspan = (0.0, 10000.0)

# -- Run Simulation ------------------------------------------------------------------------
prob = ODEProblem(rocket!, NamedViewVector{Float64}(vehicle₀), tspan, MutableNamedTuple(p))
sol = solve(prob, Tsit5(), callback=cb)

# -- Plot solution -------------------------------------------------------------------------
vel_mag(u) = norm(u.body.vel)
ndof = length(pos₀)
t = range(sol.t[1], sol.t[end], length=1000)

p_pos = plot(sol, vars=1:ndof, legend=:best)
p_vel = plot(sol, vars=ndof+1:2ndof, legend=:best)
plot!(p_vel, sol(t).t, vel_mag.(sol(t).u), legend=:best, lw=2)
p_mass = plot(sol, vars=2ndof+1, legend=:best)

plot(p_pos, p_vel, p_mass, layout=(3,1))

plot(sol, vars=((1:ndof)...,), lw=2)

max_stars_repo_name: jonniedie/ComposableDiffEqs

max_issues_repo_name: jonniedie/ComposableDiffEqs

max_forks_repo_name: jonniedie/ComposableDiffEqs


text:
import Base: +, -
import Base.diff

(+)(ta::TimeArray) = .+ta
(-)(ta::TimeArray) = .-ta

###### lag, lead ################

function lag(ta::TimeArray{T, N}, n::Int=1;
             padding::Bool=false, period::Int=0) where {T, N}

    if period != 0
        @warn("the period kwarg is deprecated, use lag(ta::TimeArray, period::Int) instead")
        n = period
    end

    # TODO: apply `unchecked`
    if padding
        paddedvals = [NaN * ones(n,size(ta, 2)); values(ta)[1:end-n, :]]
        ta = TimeArray(timestamp(ta), paddedvals, colnames(ta), meta(ta))
    else
        ta = TimeArray(timestamp(ta)[1+n:end], values(ta)[1:end-n, :], colnames(ta), meta(ta))
    end

    N == 1 && (ta = ta[colnames(ta)[1]])
    return ta

end  # lag

function lead(ta::TimeArray{T, N}, n::Int=1;
              padding::Bool=false, period::Int=0) where {T, N}

    if period != 0
      @warn("the period kwarg is deprecated, use lead(ta::TimeArray, period::Int) instead")
      n = period
    end

    if padding
        paddedvals = [values(ta)[1+n:end, :]; NaN*ones(n, length(colnames(ta)))]
        ta = TimeArray(timestamp(ta), paddedvals, colnames(ta), meta(ta))
    else
        ta = TimeArray(timestamp(ta)[1:end-n], values(ta)[1+n:end, :], colnames(ta), meta(ta))
    end

    N == 1 && (ta = ta[colnames(ta)[1]])
    return ta

end  # lead

###### diff #####################

function diff(ta::TimeArray, n::Int=1; padding::Bool=false, differences::Int=1)
    cols = colnames(ta)
    for d in 1:differences
        ta = ta .- lag(ta, n, padding=padding)
    end
    colnames(ta)[:] = cols
    return ta
end  # diff

###### percentchange ############

function percentchange(ta::TimeArray, returns::Symbol=:simple;
                       padding::Bool=false, method::AbstractString="")

    if method != ""
        @warn("the method kwarg is deprecated, use percentchange(ta, :methodname) instead")
        returns = Symbol(method)
    end

    cols = colnames(ta)
    ta = returns == :log ? diff(log.(ta), padding=padding) :
         returns == :simple ? expm1.(percentchange(ta, :log, padding=padding)) :
         error("returns must be either :simple or :log")
    colnames(ta)[:] = cols

   return ta

end  # percentchange

###### moving ###################

function moving(f, ta::TimeArray{T, 1}, window::Int;
                padding::Bool = false) where {T}
    tstamps = padding ? timestamp(ta) : timestamp(ta)[window:end]
    vals    = zero(values(ta)[window:end])
    for i=1:length(vals)
        vals[i] = f(values(ta)[i:i+(window-1)])
    end
    padding && (vals = [NaN*ones(window-1); vals])
    TimeArray(tstamps, vals, colnames(ta), meta(ta))
end

function moving(f, ta::TimeArray{T, 2}, window::Int;
                padding::Bool = false) where {T}
    tstamps = padding ? timestamp(ta) : timestamp(ta)[window:end]
    vals    = zero(values(ta)[window:end, :])
    for i=1:size(vals, 1), j=1:size(vals, 2)
        vals[i, j] = f(values(ta)[i:i+(window-1), j])
    end
    padding && (vals = [NaN*fill(1, size(values(ta)[1:(window-1), :])); vals])
    TimeArray(tstamps, vals, colnames(ta), meta(ta))
end

###### upto #####################

function upto(f, ta::TimeArray{T, 1}) where {T}
    vals = zero(values(ta))
    for i=1:length(vals)
        vals[i] = f(values(ta)[1:i])
    end
    TimeArray(timestamp(ta), vals, colnames(ta), meta(ta))
end

function upto(f, ta::TimeArray{T, 2}) where {T}
    vals = zero(values(ta))
    for i=1:size(vals, 1), j=1:size(vals, 2)
        vals[i, j] = f(values(ta)[1:i, j])
    end
    TimeArray(timestamp(ta), vals, colnames(ta), meta(ta))
end

###### basecall #################

basecall(ta::TimeArray, f::Function; cnames=colnames(ta)) =
    TimeArray(timestamp(ta), f(values(ta)), cnames, meta(ta))

###### uniform observations #####

function uniformspaced(ta::TimeArray)
    gap1 = timestamp(ta)[2] - timestamp(ta)[1]
    i, n, is_uniform = 2, length(ta), true
    while is_uniform & (i < n)
        is_uniform = gap1 == (timestamp(ta)[i+1] - timestamp(ta)[i])
        i += 1
    end
    return is_uniform
end  # uniformspaced

function uniformspace(ta::TimeArray{T, N}) where {T, N}
    min_gap = minimum(timestamp(ta)[2:end] - timestamp(ta)[1:end-1])
    newtimestamp = timestamp(ta)[1]:min_gap:timestamp(ta)[end]
    emptyta = TimeArray(collect(newtimestamp), zeros(length(newtimestamp), 0),
                        Symbol[], meta(ta))
    ta = merge(emptyta, ta, :left)
    N == 1 && (ta = ta[colnames(ta)[1]])
    return ta
end  # uniformspace

###### dropnan ####################

dropnan(ta::TimeArray, method::Symbol = :all) =
    method == :all ? ta[findall(reshape(values(any(.!isnan.(ta), dims = 2)), :))] :
    method == :any ? ta[findall(reshape(values(all(.!isnan.(ta), dims = 2)), :))] :
    error("dropnan method must be :all or :any")


text:
"""
    FAM.jl

Description:
    Options, structures, and logic for the Fuzzy ARTMAP (FAM) module.

References:
[1] G. A. Carpenter, S. Grossberg, N. Markuzon, J. H. Reynolds, and D. B. Rosen, “Fuzzy ARTMAP: A Neural Network Architecture for Incremental Supervised Learning of Analog Multidimensional Maps,” IEEE Trans. Neural Networks, vol. 3, no. 5, pp. 698-713, 1992, doi: 10.1109/72.159059.
"""

"""
    opts_FAM(;kwargs)

Implements a Fuzzy ARTMAP learner's options.

# Keyword Arguments
- `rho::Float`: vigilance value, [0, 1], default 0.6.
- `alpha::Float`: choice parameter, alpha > 0, default 1e-7.
- `epsilon::Float`: match tracking parameter, (0, 1), default 1e-3
- `beta::Float`: learning parameter, (0, 1], default 1.0.
- `uncommitted::Bool`: uncommitted node flag, default true.
- `display::Bool`: display flag, default true.
- `max_epoch::Int`: maximum number of epochs during training, default 1.
"""
@with_kw mutable struct opts_FAM <: ARTOpts @deftype Float
    # Vigilance parameter: [0, 1]
    rho = 0.6; @assert rho >= 0.0 && rho <= 1.0
    # Choice parameter: alpha > 0
    alpha = 1e-7; @assert alpha > 0.0
    # Match tracking parameter: (0, 1)
    epsilon = 1e-3; @assert epsilon > 0.0 && epsilon < 1.0
    # Learning parameter: (0, 1]
    beta = 1.0; @assert beta > 0.0 && beta <= 1.0
    # Uncommitted node flag
    uncommitted::Bool = true
    # Display flag
    display::Bool = true
    # Maximum number of epochs during training
    max_epochs::Int = 1
end # opts_FAM()

"""
    FAM <: ARTMAP

Fuzzy ARTMAP struct.

For module options, see [`AdaptiveResonance.opts_FAM`](@ref).

# Option Parameters
- `opts::opts_FAM`: Fuzzy ARTMAP options struct.
- `config::DataConfig`: data configuration struct.

# Working Parameters
- `W::RealMatrix`: category weight matrix.
- `labels::IntegerVector`: incremental list of labels corresponding to each F2 node, self-prescribed or supervised.
- `n_categories::Int`: number of category weights (F2 nodes).
- `epoch::Int`: current training epoch.

# References
1. G. A. Carpenter, S. Grossberg, N. Markuzon, J. H. Reynolds, and D. B. Rosen, “Fuzzy ARTMAP: A Neural Network Architecture for Incremental Supervised Learning of Analog Multidimensional Maps,” IEEE Trans. Neural Networks, vol. 3, no. 5, pp. 698-713, 1992, doi: 10.1109/72.159059.
"""
mutable struct FAM <: ARTMAP
    opts::opts_FAM
    config::DataConfig
    W::RealMatrix
    labels::IntegerVector
    n_categories::Int
    epoch::Int
end # FAM <: ARTMAP

"""
    FAM()

Implements a Fuzzy ARTMAP learner.

# Examples
```julia-repl
julia> FAM()
FAM
    opts: opts_FAM
    ...
```
"""
function FAM()
    opts = opts_FAM()
    FAM(opts)
end # FAM()

"""
    FAM(;kwargs...)

Implements a Fuzzy ARTMAP learner with keyword arguments.

# Examples
```julia-repl
julia> FAM(rho=0.7)
FAM
    opts: opts_FAM
    ...
```
"""
function FAM(;kwargs...)
    opts = opts_FAM(;kwargs...)
    FAM(opts)
end # FAM(;kwargs...)

"""
    FAM(opts)

Implements a Fuzzy ARTMAP learner with specified options.

# Examples
```julia-repl
julia> opts = opts_FAM()
julia> FAM(opts)
FAM
    opts: opts_FAM
    ...
```
"""
function FAM(opts::opts_FAM)
    FAM(opts,                       # opts_FAM
        DataConfig(),               # config
        Array{Float}(undef, 0,0),   # W
        Array{Int}(undef, 0),       # labels
        0,                          # n_categories
        0                           # epoch
    )
end # FAM(opts::opts_FAM)


text:
# reference in tree version of CalibrateEmulateSample
prepend!(LOAD_PATH, [joinpath(@__DIR__, "..")])

using EnsembleKalmanProcesses
using Documenter
# using DocumenterCitations

#----------

api = ["EnsembleKalmanProcessModule" => "API/EnsembleKalmanProcessModule.md",
       "ParameterDistribution" => "API/ParameterDistribution.md",
       "Observations" => "API/Observations.md",
       "DataStorage" => "API/DataStorage.md",
]

examples = ["Template example" => "examples/template_example.md"]

pages = [
    "Home" => "index.md",
    "Installation instructions" => "installation_instructions.md",
    "Prior distributions" => "parameter_distributions.md",
    "Observations" => "observations.md",
    "Ensemble Kalman Inversion" => "ensemble_kalman_inversion.md",
    "Ensemble Kalman Sampler" => "ensemble_kalman_sampler.md",
    "Examples" => examples,
    "API" => api,
    "Glossary" => "glossary.md",
]

#----------

format = Documenter.HTML(
    collapselevel = 1,
    prettyurls = !isempty(get(ENV, "CI", ""))
)

makedocs(
  sitename = "EnsembleKalmanProcesses.jl",
  authors = "CliMA Contributors",
  format = format,
  pages = pages,
  modules = [EnsembleKalmanProcesses],
  doctest = false,
  strict = true,
  clean = true,
  checkdocs = :none,
)

if !isempty(get(ENV, "CI", ""))
  deploydocs(
    repo = "github.com/CliMA/EnsembleKalmanProcesses.jl.git",
    versions = ["stable" => "v^", "v#.#.#", "dev" => "dev"],
    push_preview = true,
    devbranch = "main",
  )
end


text:
# Linear Regression Tests

# OLS test:
OLSRegression = OLS(intercept=true, robust=false)
res = linregress(X, Y, OLSRegression; fast = true)

# OLS robust test:
OLSRegression = OLS(intercept=true, robust=HCEVariance())
res = solve(X, Y, OLSRegression)

# FGLS test
FGLSRegression = FGLS(intercept=true, robust=HCEVariance())
res = linregress(X, Y, FGLSRegression)

# IteratedFGLS test
IteratedFGLSRegression = IteratedFGLS(10, intercept=true, robust=HCEVariance())
res = linregress(X, Y, IteratedFGLSRegression)

true


text:
using Documenter, CUDAnative

const src = "https://github.com/JuliaGPU/CUDAnative.jl"
const dst = "https://juliagpu.gitlab.io/CUDAnative.jl/"

function main()
    makedocs(
        sitename = "CUDAnative.jl",
        authors = "Tim Besard",
        repo = "$src/blob/{commit}{path}#{line}",
        format = Documenter.HTML(
            # Use clean URLs on CI
            prettyurls = get(ENV, "CI", nothing) == "true",
            canonical = dst,
            assets = ["assets/favicon.ico"],
            analytics = "UA-154489943-4",
        ),
        doctest = false,
        pages = Any[
            "Home"    => "index.md",
            "Host" => [
                "host/initialization.md",
                "host/execution.md",
                "host/reflection.md",
            ],
            "Device" => [
                "device/cuda.md",
                "device/array.md"
            ]
        ]
    )
end

isinteractive() || main()


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

@doc raw"""ExecAction describes a \"run in container\" action.

    IoK8sApiCoreV1ExecAction(;
        command=nothing,
    )

    - command::Vector{String} : Command is the command line to execute inside the container, the working directory for the command  is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.
"""
mutable struct IoK8sApiCoreV1ExecAction <: SwaggerModel
    command::Any # spec type: Union{ Nothing, Vector{String} } # spec name: command

    function IoK8sApiCoreV1ExecAction(;command=nothing)
        o = new()
        validate_property(IoK8sApiCoreV1ExecAction, Symbol("command"), command)
        setfield!(o, Symbol("command"), command)
        o
    end
end # type IoK8sApiCoreV1ExecAction

const _property_map_IoK8sApiCoreV1ExecAction = Dict{Symbol,Symbol}(Symbol("command")=>Symbol("command"))
const _property_types_IoK8sApiCoreV1ExecAction = Dict{Symbol,String}(Symbol("command")=>"Vector{String}")
Base.propertynames(::Type{ IoK8sApiCoreV1ExecAction }) = collect(keys(_property_map_IoK8sApiCoreV1ExecAction))
Swagger.property_type(::Type{ IoK8sApiCoreV1ExecAction }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_IoK8sApiCoreV1ExecAction[name]))}
Swagger.field_name(::Type{ IoK8sApiCoreV1ExecAction }, property_name::Symbol) =  _property_map_IoK8sApiCoreV1ExecAction[property_name]

function check_required(o::IoK8sApiCoreV1ExecAction)
    true
end

function validate_property(::Type{ IoK8sApiCoreV1ExecAction }, name::Symbol, val)
end


text:
using FSM

cn = Constants{Float64}()

ebm = EBM{Float64}(
    am=1,
    cm=1,
    dm=1,
    em=1,
    hm=1,
)

Ua = 5.0
Ta = 292.3

@code_warntype surf_exch(ebm, cn, Ta, Ua)

time_surf_exch(ebm, cn, Ta, Ua) = @time surf_exch(ebm, cn, Ta, Ua)

time_surf_exch(ebm, cn, Ta, Ua)
time_surf_exch(ebm, cn, Ta, Ua)


text:
macro delete_cons(model,cref)
    model_string = string(model)
    cref_string = string(cref)
    s = quote
        local con = $cref_string
        # println(con)
        local model_local = Meta.parse($model_string)
        local semi_locals = Base.@locals # get the local vars within the loop
        local model_fixed = remove_local_var(model_local,semi_locals)
        local s = repr(eval(model_fixed))
        local p = Regex("(?<=\\n)(.*\\bconstraint\\b.*\\b$con\\b.*)(?=\\n)")
        # p = Regex("$con")
        # println(p)
        local snew = replace(s,p => "")
        local model_new = Meta.parse(snew)#默认会套上一层quote "x" -> "quote x end"
        eval(model_new)
    end
    return s
end
macro add_upper_cons(model,expression...)#Almost the same as add_lower_cons except for Upper()/Lower()
    model_string = string(model)
    expression_string = [string(e) for e in expression]
    return quote
    local model_local = Meta.parse($model_string)
    local expression_local = [Meta.parse(x) for x in $expression_string]
    @assert length($expression_string) <= 2
    @assert length($expression_string) >= 1
    local semi_locals = Base.@locals # get the local vars within the loop
    local model_fixed = remove_local_var(model_local,semi_locals)
    local s = repr(eval(model_fixed))
    local p = r"\n.*return"
    local blm = match(r"\b.*(?==.*Bilevel)",s).match
    local vars_temp = [split(x.match," ")[3] for x in eachmatch(r"(?<=@variable).*",s)]
    # println(vars_temp)
    local vars = [Meta.parse(replace(x,r"(?<=\[).*(?=\])|\]|\["=>"")) for x in vars_temp] #get the vars defined in the model
    # println(vars)
    if length(expression_local) == 1
        local locals = []
    else
        local cref,locals = remain_cref(expression_local[1])
    end
    local ctr, = remain_opt_var(model_local,expression_local[end],vars,semi_locals,locals)#modify the contraint expression, always the last argument
    ctr = string(ctr)
    cref = string(cref)
    if length(expression_local) == 1
        local constraint = "@constraint(Upper($blm),$(ctr))"
    elseif length(expression_local) == 2
        local constraint = "@constraint(Upper($blm),$(cref),$(ctr))"
    end
    local m = replace(s,p=>(pstr->"$constraint\n"*pstr))
    local model_new = Meta.parse(m)
    # @info("constraint ***$constraint*** added")
    eval(model_new)
    # println(m)
    end
end
macro add_lower_cons(model,expression...)
    model_string = string(model)
    expression_string = [string(e) for e in expression]
    return quote
    local model_local = Meta.parse($model_string)
    local expression_local = [Meta.parse(x) for x in $expression_string]
    @assert length($expression_string) <= 2
    @assert length($expression_string) >= 1
    local semi_locals = Base.@locals # get the local vars within the loop
    local model_fixed = remove_local_var(model_local,semi_locals)
    local s = repr(eval(model_fixed))
    local p = r"\n.*return"
    local blm = match(r"\b.*(?==.*Bilevel)",s).match
    local vars_temp = [split(x.match," ")[3] for x in eachmatch(r"(?<=@variable).*",s)]
    # println(vars_temp)
    local vars = [Meta.parse(replace(x,r"(?<=\[).*(?=\])|\]|\["=>"")) for x in vars_temp] #get the vars defined in the model
    # println(vars)
    if length(expression_local) == 1
        local locals = []
    else
        local cref,locals = remain_cref(expression_local[1])
    end
    local ctr, = remain_opt_var(model_local,expression_local[end],vars,semi_locals,locals)#modify the contraint expression, always the last argument
    ctr = string(ctr)
    cref = string(cref)
    if length(expression_local) == 1
        local constraint = "@constraint(Lower($blm),$(ctr))"
    elseif length(expression_local) == 2
        local constraint = "@constraint(Lower($blm),$(cref),$(ctr))"
    end
    local m = replace(s,p=>(pstr->"$constraint\n"*pstr))
    local model_new = Meta.parse(m)
    # @info("constraint ***$constraint*** added")
    eval(model_new)
    # println(m)
    end
end
function remain_opt_var(model,expression,varlist,semi_locals,local_var=[])
    # println(expression)
    # println(model)
    lv = [x for x in local_var]
    is_numeric = true
    if expression.head == :generator
        append!(lv,[x.args[1] for x in expression.args if x.head == :(=)])
        append!(lv,[x.args[2].args[1] for x in expression.args if x.head == :filter])
    end
    if expression.head == :ref && expression.args[1] == model
        println("success")
        popfirst!(expression.args)#remove model name e.g mdl[:x] -> :(:x)
        var = expression.args[1].value#remove quote :(:x) -> :x
        @assert var in varlist
        expression = var
        return expression,false
    end
    for (k,v) in enumerate(expression.args)
        if typeof(v) == Expr
            expression.args[k],is_numeric_temp = remain_opt_var(model,v,varlist,semi_locals,lv)
        else#Symbol
            if v in lv
                is_numeric_temp = false
            elseif v in keys(semi_locals)
                expression.args[k] = semi_locals[v]
                is_numeric_temp = true
            else
                expression.args[k] = @eval Main $v
                is_numeric_temp = true
            end
        end
        is_numeric = is_numeric && is_numeric_temp
    end
    if is_numeric
        # println(expression)
        expression = @eval Main $expression
    end
    return expression,is_numeric
end
function remove_local_var(m::Expr,locals::Dict)
    model = deepcopy(m)
    @assert model.head == :ref
    if model.args[2] in keys(locals)
        model.args[2] = locals[model.args[2]]
    else
        v = model.args[2]
        model.args[2] = @eval Main $v
    end
    model.args[1] = remove_local_var(model.args[1],locals)
    return model
end
function remove_local_var(m::Symbol,locals::Dict)
    return m
end
function remain_cref(expression)
    local_var = []
    if typeof(expression) == Symbol
        return expression,local_var
    else
        nothing
    end
    @assert expression.head == :ref
    for k in 2:length(expression.args)
        # println(dump(expression.args[k]))
        @assert expression.args[k].head == :kw || expression.args[k].args[1] == :in
        if expression.args[k].head == :kw
            v = expression.args[k].args[2]
            expression.args[k].args[2] = @eval Main $v
            push!(local_var,expression.args[k].args[1])
        else
            v = expression.args[k].args[3]
            expression.args[k].args[3] = @eval Main $v
            push!(local_var,expression.args[k].args[2])
        end
    end
    return expression,local_var
end


text:
using GeneralizedSampling
using Base.Test

println("Testing multiplication with Freq2Wave type...")

#=
Multiplication with a Freq2Wave element should give the same result as
multiplication with the collected matrix.

For both 1D and 2D samples and the 4 combinations of non-uniform samples
and wavelets with and without boundaries are tested with the
multiplications * and '*
=#

EPS = 1e-5

# ------------------------------------------------------------
# 1D

begin
	J = 3
	M = 2^(J+1)
	N = 2^J

	x = rand(N)
	v = rand(M)

	# ----------------------------------------
	# Compute matrices

	# Uniform points, No Boundary
	Usamples = grid(M, 0.5)
	TUNB = Freq2Wave(Usamples, "haar", J)
	AUNB = collect(TUNB)

	y1UNB = TUNB*x
	y2UNB = AUNB*x
	#@show norm(y1UNB - y2UNB)
	@test_approx_eq_eps y1UNB y2UNB EPS

	z1UNB = TUNB'*v
	z2UNB = AUNB'*v
	#@show norm(z1UNB - z2UNB)
	@test_approx_eq_eps z1UNB z2UNB EPS

	# Uniform points, with Boundary
	TUB = Freq2Wave(Usamples, "db2", J)
	AUB = collect(TUB)

	y1UB = TUB*x
	y2UB = AUB*x
	#@show norm(y1UB - y2UB)
	@test_approx_eq_eps y1UB y2UB EPS

	z1UB = TUB'*v
	z2UB = AUB'*v
	#@show norm(z1UB - z2UB)
	@test_approx_eq_eps z1UB z2UB EPS

	# Non-uniform points
	K = N/2 # bandwidth
	NUsamples = N*rand(M) - K

	# Non-Uniform points, No Boundary
	TNUNB = Freq2Wave(NUsamples, "haar", J, K)
	ANUNB = collect(TNUNB)

	y1NUNB = TNUNB*x
	y2NUNB = ANUNB*x
	#@show norm(y1NUNB - y2NUNB)
	@test_approx_eq_eps y1NUNB y2NUNB EPS

	z1NUNB = TNUNB'*v
	z2NUNB = ANUNB'*v
	#@show norm(z1NUNB - z2NUNB)
	@test_approx_eq_eps z1NUNB z2NUNB EPS

	# Non-Uniform points, with Boundary
	TNUB = Freq2Wave(NUsamples, "db2", J, K)
	ANUB = collect(TNUB)

	y1NUB = TNUB*x
	y2NUB = ANUB*x
	#@show norm(y1NUB - y2NUB)
	@test_approx_eq_eps y1NUB y2NUB EPS

	z1NUB = TNUB'*v
	z2NUB = ANUB'*v
	#@show norm(z1NUB - z2NUB)
	@test_approx_eq_eps z1NUB z2NUB EPS
end

# ------------------------------------------------------------
# 2D

begin
	J = 3
	M = 2^(J+1)
	N = 2^J

	x = rand(N^2)
	v = rand(M^2)

	# TODO: Run this in loop
	# ----------------------------------------
	# Compute matrices

	# Uniform points, No Boundary
	Usamples = grid((M,M), 0.5)
	TUNB = Freq2Wave(Usamples, "haar", J)
	AUNB = collect(TUNB)

	y1UNB = TUNB*x
	y2UNB = AUNB*x
	#@show norm(y1UNB - y2UNB)
	@test_approx_eq_eps y1UNB y2UNB EPS

	z1UNB = TUNB'*v
	z2UNB = AUNB'*v
	#@show norm(z1UNB - z2UNB)
	@test_approx_eq_eps z1UNB z2UNB EPS

	# Uniform points, with Boundary
	TUB = Freq2Wave(Usamples, "db2", J)
	AUB = collect(TUB)

	y1UB = TUB*x
	y2UB = AUB*x
	#@show norm(y1UB - y2UB)
	@test_approx_eq_eps y1UB y2UB EPS

	z1UB = TUB'*v
	z2UB = AUB'*v
	#@show norm(z1UB - z2UB)
	@test_approx_eq_eps z1UB z2UB EPS

	# Non-uniform points
	K = N/2 # bandwidth
	NUsamples = N*rand(M^2,2) - K

	# Non-Uniform points, No Boundary
	TNUNB = Freq2Wave(NUsamples, "haar", J, K)
	ANUNB = collect(TNUNB)

	y1NUNB = TNUNB*x
	y2NUNB = ANUNB*x
	#@show norm(y1NUNB - y2NUNB)
	@test_approx_eq_eps y1NUNB y2NUNB EPS

	z1NUNB = TNUNB'*v
	z2NUNB = ANUNB'*v
	#@show norm(z1NUNB - z2NUNB)
	@test_approx_eq_eps z1NUNB z2NUNB EPS

	# Non-Uniform points, with Boundary
	TNUB = Freq2Wave(NUsamples, "db2", J, K)
	ANUB = collect(TNUB)

	y1NUB = TNUB*x
	y2NUB = ANUB*x
	#@show norm(y1NUB - y2NUB)
	@test_approx_eq_eps y1NUB y2NUB EPS

	z1NUB = TNUB'*v
	z2NUB = ANUB'*v
	#@show norm(z1NUB - z2NUB)
	@test_approx_eq_eps z1NUB z2NUB EPS
end


text:
# ------------------------------------------------------------------
# Licensed under the ISC License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
    WeightedBootstrap(weighter, nsamples; loss=Dict())

Weighted bootstrap with `nsamples` samples drawn with
replacement using the weights produced by `weighter`.
Optionally, specify `loss` function from `LossFunctions.jl`
for some of the variables.
"""
struct WeightedBootstrap{W<:AbstractWeighter} <: AbstractErrorEstimator
  weighter::W
  nsamples::Int
  loss::Dict{Symbol,SupervisedLoss}
end

WeightedBootstrap(weighter::AbstractWeighter, nsamples::Int; loss=Dict()) =
  WeightedBootstrap{typeof(weighter)}(weighter, nsamples, loss)

function Base.error(solver::AbstractLearningSolver,
                    problem::LearningProblem,
                    eestimator::WeightedBootstrap)
  # retrieve problem info
  sdata = sourcedata(problem)
  ovars = outputvars(task(problem))
  loss  = eestimator.loss
  for var in ovars
    if var ∉ keys(loss)
      loss[var] = defaultloss(sdata[1,var])
    end
  end

  # bootstrap parameters
  b = eestimator.nsamples
  n = npoints(sdata)

  # weight source data
  weights = weight(sdata, eestimator.weighter)

  results = pmap(1:b) do _
    # create bootstrap sample
    sinds = sample(1:n, n, replace=true)
    binds = sample(1:n, weights, n, replace=true)
    tinds = setdiff(binds, sinds)

    # training and holdout set
    train = view(sdata, sinds)
    hold  = view(sdata, tinds)

    # solve problem for this sample
    subproblem = LearningProblem(train, hold, task(problem))
    solution   = solve(subproblem, solver)

    result = map(ovars) do var
      y = hold[var]
      ŷ = solution[var]
      var => value(loss[var], y, ŷ, AggMode.Mean())
    end

    # results for bootstrap sample
    Dict(result)
  end

  # average results across samples
  sums = reduce((r₁, r₂) -> merge(+, r₁, r₂), results)
  Dict(var => val / b for (var, val) in sums)
end


text:
abstract type Grid{d} end
#

# # backward backward compatibility
nodes(::Type{<:Union{ListOfPoints,ListOfPoints{d}}}, grid::Grid{d}) where d = nodes(grid)
nodes(::Type{<:Matrix}, grid::Grid) = copy(from_LOP(nodes(grid)))

node(::Type{<:Union{Point,Point{d}}}, grid::Grid{d}, i::Int) where d = node(grid,i)
node(::Type{<:Vector}, grid::Grid, i::Int) = Vector(node(grid,i))

import Base

Base.ndims(grid::Grid{d}) where d = d

function Base.show(io::IO, grid::Grid)
    print(io, typeof(grid))
end

struct EmptyGrid <: Grid{0}
    # this grid does not exist ;-)
end

nodes(grid::EmptyGrid) = nothing
n_nodes(grid::EmptyGrid) = 0
node(grid::EmptyGrid, i::Int) = nothing # fail if i!=1 ?

##########################
# Grid made of one point #
##########################

struct PointGrid{d} <: Grid{d}
    point::SVector{d,Float64}
end

function (::Type{<:PointGrid})(point::Vector{Float64})
    d = length(point)
    PointGrid{d}(SVector{d,Float64}(point...))
end

nodes(grid::PointGrid) = [grid.point]
n_nodes(grid::PointGrid) = 1
node(grid::PointGrid, i::Int) = grid.point # fail if i!=1 ?

#####################
# Unstructured Grid #
#####################

struct UnstructuredGrid{d} <: Grid{d}
    nodes::ListOfPoints{d}
end

# Old-convention
function UnstructuredGrid{d}(nodes::Matrix{Float64}) where d
    N = size(nodes,1)
    @assert d == size(nodes,2)
    UnstructuredGrid{d}(reshape(reinterpret(Point{d}, vec(copy(nodes'))), (N,)))
end

nodes(grid::UnstructuredGrid) = grid.nodes
n_nodes(grid::UnstructuredGrid) = length(grid.nodes)
node(grid::UnstructuredGrid, i::Int) = grid.nodes[i] # fail if i!=1 ?
node(::Type{<:Point}, grid::UnstructuredGrid, i::Int) = node(grid,i)

function Product(a::UnstructuredGrid{d1}, b::UnstructuredGrid{d2}) where d1 where d2
    A = [Base.product(a.nodes, b.nodes)...]
    N = length(A)
    d = d1 + d2
    nodes = reshape(reinterpret(Point{d},(A)),(N,))
    return UnstructuredGrid{d}(nodes)
end

#################
# CartesianGrid #
#################

function mlinspace(min, max, n)
    # this now returns an iterator
    nodes = map((x,y,z)->range(x,stop=y,length=z), min, max, n)
    return Base.product(nodes...)
end

struct CartesianGrid{d} <: Grid{d}
    min::Point{d}
    max::Point{d}
    n::SVector{d,Int}
    nodes::ListOfPoints{d}
end

function (::Type{<:CartesianGrid})(min::SVector{d,Float64}, max::SVector{d,Float64}, n::SVector{d,Int64}) where d
    A = [mlinspace(min, max, n)...]
    N = prod(n)
    mm = reshape(reinterpret(Point{d},vec(A)),(N,))
    return CartesianGrid{d}(min, max, n, mm)
end

(::Type{<:CartesianGrid})(min::Vector{Float64},max::Vector{Float64},n::Vector{Int64}) = CartesianGrid(SVector(min...), SVector(max...), SVector(n...))

nodes(grid::CartesianGrid{d}) where d = grid.nodes
n_nodes(grid::CartesianGrid{d}) where d = length(grid.nodes)
node(grid::CartesianGrid{d}, i::Int) where d = grid.nodes[i]

nodes(::Type{<:ListOfPoints}, grid::CartesianGrid{d}) where d  = grid.nodes
node(::Type{<:Point}, grid::CartesianGrid{d}, i::Int64) where d = node(grid,i)

function Product(a::CartesianGrid{d1}, b::CartesianGrid{d2}) where d1 where d2
  return Dolo.CartesianGrid{d1+d2}( [a.min; b.min], [a.max; b.max], [a.n; b.n])
end

################
# Smolyak Grid #
################

struct SmolyakGrid{d} <: Grid{d}
    smol_params::BM.SmolyakParams{Float64,Vector{Int}}
    nodes::Matrix{Float64}
    B_nodes::Matrix{Float64}
end

function SmolyakGrid{d}(min::Point{d}, max::Point{d}, mu::SVector{d,Int64}) where d
    sp = BM.SmolyakParams(d, Vector(mu), Vector(min), Vector(max))
    nodes = BM.nodes(sp)
    B_nodes = BM.evalbase(sp, nodes)
    return SmolyakGrid{d}(sp, nodes, B_nodes)
end

SmolyakGrid(min::Point{d}, max::Point{d}, mu::SVector{d,Int64}) where d = SmolyakGrid{d}(min,max,mu)
SmolyakGrid(min::Point{d}, max::Point{d}, mu::Int64) where d = SmolyakGrid{d}(min, max, SVector([mu for i=1:d]...))
SmolyakGrid{d}(min::Point{d}, max::Point{d}, mu::Int64) where d = SmolyakGrid{d}(min, max, SVector([mu for i=1:d]...))

function SmolyakGrid(min::Vector{Float64},max::Vector{Float64},mu::Union{Vector{Int64},Int64})
    d = length(min)
    mmu = mu isa Int ? ffill(mu,d) : mu
    @assert d == length(max) == length(mmu)
    SmolyakGrid{d}(SVector(min...), SVector(max...), SVector(mu...))
end
#
function SmolyakGrid{d}(min::Vector{Float64},max::Vector{Float64},mu::Union{Vector{Int64},Int64}) where d
    mmu = mu isa Int ? fill(mu,d) : mu
    @assert d == length(min) == length(max) == length(mmu)
    SmolyakGrid{d}(SVector(min...), SVector(max...), SVector(mu...))
end

nodes(grid::SmolyakGrid{d}) where d  = reshape(reinterpret(Point{d}, vec(copy(grid.nodes'))),( size(grid.nodes,1),))
n_nodes(grid::SmolyakGrid) = size(grid.nodes,1)
node(grid::SmolyakGrid{d}, i::Int) where d = Point{d}(grid.nodes[i,:]...)

###############
# Random Grid #
###############

struct RandomGrid{d} <: Grid{d}
    min::SVector{d,Float64}
    max::SVector{d,Float64}
    n::Int64
    nodes::ListOfPoints{d}
end

function  (::Type{<:Union{RandomGrid,RandomGrid{d}}})(min::Point{d}, max::Point{d}, n::Int) where d
    nodes = reshape(reinterpret(Point{d}, vec(rand(d, n))), (n,))  # on [0, 1]
    for nn=1:length(n)
        nodes[nn] = nodes[nn] .* (max-min) + min
    end
    RandomGrid(min, max, n, copy(nodes))
end

function RandomGrid(min::Vector{Float64}, max::Vector{Float64}, n::Int)
    d = length(min)
    @assert d == length(max)
    dim_err = DimensionMismatch("min was length $d, max must be also")
    length(max) == d || dim_err
    all(max .> min) || error("max must be greater than min")
    RandomGrid{d}(SVector(min...),SVector(max...),n)
end

function RandomGrid{d}(min::Vector{Float64}, max::Vector{Float64}, n::Int) where d
    @assert d == length(min)
    RandomGrid(min,max,d)
end

nodes(grid::RandomGrid) = grid.nodes
nodes(::Type{<:ListOfPoints}, grid::RandomGrid) = nodes(grid)

n_nodes(grid::RandomGrid) = length(grid.nodes)

node(grid::RandomGrid,i::Int) = grid.nodes[i]


text:
#!/usr/bin/env julia
using Covid19Inc, PGFPlotsX
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\usepackage{fontspec}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\setmainfont{Asana-Math}")
p = Covid19Inc.covid_pop(752, :i10o90, "2020-04-25") |> Covid19Inc.covidpl
pgfsave("../../images/752_covid19_2020-04-25.svg", p)

max_stars_repo_name: klpn/static-dust

max_issues_repo_name: klpn/static-dust

max_forks_repo_name: klpn/static-dust


text:
# This file is a part of MGVI.jl, licensed under the MIT License (MIT).
#
function _unshaped(x::Number)
    [x]
end

function _unshaped(x::Tuple)
    vcat(x...)
end

function _unshaped(x::NamedTuple)
    vcat(values(x)...)
end

function _unshaped(x::AbstractVector)
    x
end

function unshaped_params(d::Distribution)
    vcat(map(_unshaped, params(d))...)
end

function unshaped_params(ntd::NamedTupleDist)
    vcat(map(unshaped_params, values(ntd))...)
end

function unshaped_params(dp::Product)
    reduce(vcat, map(unshaped_params, dp.v))
end

function _uppertriang_to_vec(m::AbstractMatrix)
    # ToDo: Improve implementation
    reduce(vcat, [m[1:i, i] for i in 1:size(m, 1)])
end

function ChainRulesCore.rrule(::typeof(MGVI._uppertriang_to_vec), m::AbstractMatrix)
    res = MGVI._uppertriang_to_vec(m)

   # ToDo: Use ChainRulesCore.ProjectTo (requires ChainRulesCore >= v0.10.11).

    function _uppertriang_to_vec_pullback(thunked_x)
        x = unthunk(thunked_x)
        # ToDo: Improve implementation
        triang_n = size(res, 1)
        n = size(m, 1)
        pb_res = zero(m)
        for j in 1:n
            pb_res[j, 1:j] .= x[j*(j-1)÷2+1:j*(j+1)÷2]
        end
        ChainRulesCore.NoTangent(), pb_res
    end

    res, _uppertriang_to_vec_pullback
end

function unshaped_params(d::MvNormal)
    μ, σ = params(d)
    vcat(μ, _uppertriang_to_vec(σ))
end

function unshaped_params(d::TuringDenseMvNormal)
    μ = d.m
    σ = d.C.L*d.C.U
    vcat(μ, _uppertriang_to_vec(σ))
end


text:
##### Show tendencies

export show_tendencies

using PrettyTables

format_tend(tend_type) = "$(nameof(typeof(tend_type)))"

format_tends(tend_types) = "(" * join(format_tend.(tend_types), ", ") * ")"

"""
    show_tendencies(
        bl;
        include_module = false,
        table_complete = false,
    )

Show a table of the tendencies for each
prognostic variable for the given balance law.

## Arguments
 - `include_module[ = false]` will print not remove the module where each
   prognostic variable is defined (e.g., `Atmos.Mass`).
 - `table_complete[ = false]` will print a warning (if false) that the
   tendency table is incomplete.

Requires definitions for
 - [`prognostic_vars`](@ref)
 - [`eq_tends`](@ref)
for the balance law.
"""
function show_tendencies(bl; include_module = false, table_complete = false)
    prog_vars = prognostic_vars(bl)
    if !isempty(prog_vars)
        header = [
            "Equation" "Flux{FirstOrder}" "Flux{SecondOrder}" "Source"
            "(Y_i)" "(F_1)" "(F_2)" "(S)"
        ]
        if include_module
            eqs = collect(string.(typeof.(prog_vars)))
        else
            eqs = collect(last.(split.(string.(typeof.(prog_vars)), ".")))
        end
        fmt_tends(tt) = map(prog_vars) do pv
            format_tends(eq_tends(pv, bl, tt))
        end |> collect
        F1 = fmt_tends(Flux{FirstOrder}())
        F2 = fmt_tends(Flux{SecondOrder}())
        S = fmt_tends(Source())
        data = hcat(eqs, F1, F2, S)
        table_complete || @warn "This table is temporarily incomplete"
        println("\nPDE: ∂_t Y_i + (∇•F_1(Y))_i + (∇•F_2(Y,G)))_i = (S(Y,G))_i")
        pretty_table(
            data,
            header,
            header_crayon = crayon"yellow bold",
            subheader_crayon = crayon"green bold",
            crop = :none,
        )
        println("")
    else
        msg = "Defining `prognostic_vars` and\n"
        msg *= "`eq_tends` for $(nameof(typeof(bl))) will\n"
        msg *= "enable printing a table of tendencies."
        @info msg
    end
    return nothing
end


text:
draw_action_from_policy(s::Integer, 𝐩::AbstractVector{<:Integer}) = 𝐩[s]
draw_action_from_policy(s::Integer, 𝐏::AbstractMatrix{<:Real}) = (1:size(𝐏, 2))[findfirst(cumsum(𝐏[s, :]) .> rand())]

function draw_action_from_policy(fmdp::FiniteMDP, s::Integer, P::Union{AbstractVector{<:Integer},AbstractMatrix{<:Real}}, ε::Real)
    if rand() > ε
        a = draw_action_from_policy(s, P)
    else
        a = random_action(fmdp)
    end
    return a
end

# TODO: This particular piece of code appears elsewhere... (v_from_Q?) merge
draw_action_from_Q(s::Integer, Q::AbstractMatrix{<:Real}) = (1:size(Q, 2))[argmax(replace(Q[s, :], NaN => -Inf))]

function draw_action_from_Q(s::Integer, Q::AbstractMatrix{<:Real}, ε::Real)
    if rand() > ε
        a = draw_action_from_Q(s, Q)
    else
        a = rand(1:size(Q, 2))
    end
    return a
end

const TERMINAL_STATE_CODE = -1
const TERMINAL_STATE_TRIPPLE = (TERMINAL_STATE_CODE, 0, 0.0)

function create_simulator_from_policy(fmdp::FiniteMDP, policy::Union{AbstractVector{<:Integer},AbstractMatrix{<:Real}}, ε, maxiter::Integer)
    function inner(s0::Integer, a0::Integer)
        episode = Vector{Tuple{Int,Int,Float64}}()
        s, r = act_once(fmdp, s0, a0)
        push!(episode, (s0, a0, r))
        for _ = 1:maxiter
            if s == terminal_state(fmdp)
                push!(episode, TERMINAL_STATE_TRIPPLE)
                break
            end
            a = draw_action_from_policy(fmdp, s, policy, ε)
            (s_next, r) = act_once(fmdp, s, a)
            push!(episode, (s, a, r))
            s = s_next
        end
        return episode
    end
end

create_simulator_from_policy(fmdp::FiniteMDP, policy::Union{AbstractVector{<:Integer},AbstractMatrix{<:Real}}, maxiter::Integer) =
    create_simulator_from_policy(fmdp, policy, 0.0, maxiter)

function create_simulator_from_Q(fmdp::FiniteMDP, Q::AbstractMatrix{<:Real}, ε::Real, maxiter::Integer)
    function inner(s0::Integer, a0::Integer)
        episode = Vector{Tuple{Int,Int,Float64}}()
        s, r = act_once(fmdp, s0, a0)
        push!(episode, (s0, a0, r))
        for _ = 1:maxiter
            if s == terminal_state(fmdp)
                push!(episode, TERMINAL_STATE_TRIPPLE)
                break
            end
            a = draw_action_from_Q(s, Q, ε)
            (s_next, r) = act_once(fmdp, s, a)
            push!(episode, (s, a, r))
            s = s_next
        end
        return episode
    end
end

create_simulator_from_Q(fmdp::FiniteMDP, Q::AbstractMatrix{<:Real}, maxiter::Integer) =
    create_simulator_from_Q(fmdp, Q, ε, maxiter)


text:
@testset "experience_sample_model" begin
    m = ExperienceBasedSampleModel()

    update!(m, (1, 1, 1.0, false, 2))

    @test haskey(m.experiences, 1)
    @test haskey(m.experiences[1], 1)

    update!(m, (2, 2, -1.0, true, 3))

    @test haskey(m.experiences, 1)
    @test haskey(m.experiences, 2)
    @test haskey(m.experiences[1], 1)
    @test haskey(m.experiences[2], 2)

    @test m.experiences[2][2] == (reward = -1.0, terminal = true, nextstate = 3)
end


text:
"""

```
sphericalshellvolume(i,step)
```

Computes the volume of the spherical shell defined within [(i-1)*step,i*step].

"""
function sphericalshellvolume(i, step)
    rmin = (i - 1) * step
    return (4 * pi / 3) * ((rmin + step)^3 - rmin^3)
end


text:
push!(LOAD_PATH, "..")

using
    Documenter,
    Literate,
    Oceananigans,
    Oceananigans.Operators,
    Oceananigans.Grids,
    Oceananigans.Diagnostics,
    Oceananigans.OutputWriters,
    Oceananigans.TurbulenceClosures,
    Oceananigans.TimeSteppers,
    Oceananigans.AbstractOperations

#####
##### Generate examples
#####

const EXAMPLES_DIR = joinpath(@__DIR__, "..", "examples")
const OUTPUT_DIR   = joinpath(@__DIR__, "src/generated")

examples = [
    "one_dimensional_diffusion.jl",
    "two_dimensional_turbulence.jl",
    "ocean_wind_mixing_and_convection.jl",
    "ocean_convection_with_plankton.jl",
    "internal_wave.jl"
]

for example in examples
    example_filepath = joinpath(EXAMPLES_DIR, example)
    Literate.markdown(example_filepath, OUTPUT_DIR, documenter=true)
end

#####
##### Build and deploy docs
#####

# Set up a timer to print a dot '.' every 60 seconds. This is to avoid Travis CI timing out when
# building demanding Literate.jl examples.
Timer(t -> println("."), 0, interval=60)

format = Documenter.HTML(
    collapselevel = 1,
       prettyurls = get(ENV, "CI", nothing) == "true",
        canonical = "https://climate-machine.github.io/Oceananigans.jl/latest/"
)

makedocs(
   modules = [Oceananigans, Oceananigans.Operators, Oceananigans.TurbulenceClosures],
   doctest = true,
   clean   = true,
 checkdocs = :all,
    format = format,
   authors = "Ali Ramadhan, Gregory Wagner, John Marshall, Jean-Michel Campin, Chris Hill",
  sitename = "Oceananigans.jl",
     pages = [
                              "Home" => "home.md",
         "Installation instructions" => "installation_instructions.md",
                        "Using GPUs" => "using_gpus.md",

         "Examples" => [
             "One-dimensional diffusion"        => "generated/one_dimensional_diffusion.md",
             "Two-dimensional turbulence"       => "generated/two_dimensional_turbulence.md",
             "Ocean wind mixing and convection" => "generated/ocean_wind_mixing_and_convection.md",
             "Ocean convection with plankton"   => "generated/ocean_convection_with_plankton.md",
             "Internal wave"                    => "generated/internal_wave.md"
         ],

         "Model setup" => [
                       "Overview" => "model_setup/overview.md",
                   "Architecture" => "model_setup/architecture.md",
                    "Number type" => "model_setup/number_type.md",
                           "Grid" => "model_setup/grids.md",
                          "Clock" => "model_setup/clock.md",
            "Coriolis (rotation)" => "model_setup/coriolis.md",
                        "Tracers" => "model_setup/tracers.md",
            "Buoyancy and equation of state" =>
                                     "model_setup/buoyancy_and_equation_of_state.md",
            "Boundary conditions" => "model_setup/boundary_conditions.md",
              "Forcing functions" => "model_setup/forcing_functions.md",
               "Model parameters" => "model_setup/model_parameters.md",
            "Turbulent diffusivity closures and LES models" =>
                                     "model_setup/turbulent_diffusivity_closures_and_les_models.md",
                    "Diagnostics" => "model_setup/diagnostics.md",
                 "Output writers" => "model_setup/output_writers.md",
                  "Time stepping" => "model_setup/time_stepping.md",
            "Setting initial conditions" =>
                                     "model_setup/setting_initial_conditions.md"
         ],

         "Physics" => [
            "Navier-Stokes and tracer conservation equations" =>
                                                "physics/navier_stokes_and_tracer_conservation.md",
            "Coordinate system and notation" => "physics/coordinate_system_and_notation.md",
              "The Boussinesq approximation" => "physics/boussinesq_approximation.md",
                           "Coriolis forces" => "physics/coriolis_forces.md",
            "Buoyancy model and equations of state" =>
                                                "physics/buoyancy_and_equations_of_state.md",
                       "Turbulence closures" => "physics/turbulence_closures.md",
            "Surface gravity waves and the Craik-Leibovich approximation" =>
                                                "physics/surface_gravity_waves.md"
        ],

         "Numerical implementation" => [
             "Pressure decomposition" => "numerical_implementation/pressure_decomposition.md",
             "Time stepping"          => "numerical_implementation/time_stepping.md",
             "Finite volume method"   => "numerical_implementation/finite_volume.md",
             "Spatial operators"      => "numerical_implementation/spatial_operators.md",
             "Boundary conditions"    => "numerical_implementation/boundary_conditions.md",
             "Poisson solvers"        => "numerical_implementation/poisson_solvers.md",
             "Large eddy simulation"  => "numerical_implementation/large_eddy_simulation.md"
         ],

         "Verification experiments" => [
             "Taylor-Green vortex"     => "verification/taylor_green_vortex.md",
             "Stratified Couette flow" => "verification/stratified_couette_flow.md"
         ],

                        "Gallery" => "gallery.md",
         "Performance benchmarks" => "benchmarks.md",
            "Contributor's guide" => "contributing.md",
                        "Library" => "library.md",

         "Appendix" => [
             "Staggered grid"         => "appendix/staggered_grid.md",
             "Fractional step method" => "appendix/fractional_step.md",
         ],

         "Index"      => "index.md"
     ]
)

deploydocs(repo = "github.com/climate-machine/Oceananigans.jl.git")