text:
"""
    struct Grouping <: StatsModels.AbstractContrasts end

A placeholder type to indicate that a categorical variable is only used for
grouping and not for contrasts.  When creating a [`CategoricalTerm`](@ref), this
skips constructing the contrasts matrix which makes it robust to large numbers
of levels, while still holding onto the vector of levels and constructing the
level-to-index mapping (`invindex` field of the [`ContrastsMatrix`](@ref).).

Note that calling `modelcols` on a `CategoricalTerm{Grouping}` is an error.

# Examples

```julia
julia> schema((; grp = string.(1:100_000)))
# out-of-memory error

julia> schema((; grp = string.(1:100_000)), Dict(:grp => Grouping()))
"""
struct Grouping <: StatsModels.AbstractContrasts
end

# return an empty matrix
StatsModels.contrasts_matrix(::Grouping, baseind, n) = zeros(0,0)
StatsModels.termnames(::Grouping, levels::AbstractVector, baseind::Integer) = levels

# this is needed until StatsModels stops assuming all contrasts have a .levels field
Base.getproperty(g::Grouping, prop::Symbol) =
    prop == :levels ? nothing : getfield(g, prop)

# special-case categorical terms with Grouping contrasts.
StatsModels.modelcols(::CategoricalTerm{Grouping}, d::NamedTuple) =
    error("can't create model columns directly from a Grouping term")


text:
using Base.Test

push!(LOAD_PATH, "src")
push!(LOAD_PATH, "../src")

import JuliaIntro: page
@test 1 == page.start

import Slide: pages
for slide in pages
  @test isa(slide, Base.Markdown.MD)
end

ext: jl


text:
module CellArrayApply

using Gridap
using Gridap.Helpers
using Gridap.CachedArrays
using Gridap.Kernels: _compute_T, _compute_N
using Gridap.CellNumberApply: _checks
using Gridap.CellNumberApply: _getvalues
using Gridap.Kernels: _size_for_broadcast

import Gridap: apply
import Base: iterate
import Base: length
import Base: size
import Base: getindex
import Base: IndexStyle
import Gridap.CellNumberApply: _apply

function apply(k::ArrayKernel,v::Vararg{<:CellValue})
  CellArrayFromKernel(k,v...)
end

function apply(k::ArrayKernel,v::Vararg{<:IndexCellValue})
  IndexCellArrayFromKernel(k,v...)
end

function _apply(f,v,::Val{true})
  k = ArrayKernelFromBroadcastedFunction(f)
  apply(k,v...)
end

struct CellArrayFromKernel{T,N,K,V} <: IterCellArray{T,N,CachedArray{T,N,Array{T,N}}}
  kernel::K
  cellvalues::V
end

function CellArrayFromKernel(k::ArrayKernel,v::Vararg{<:CellValue})
  _checks(v)
  T = _compute_T(k,v)
  N = _compute_N(k,v)
  K = typeof(k)
  V = typeof(v)
  CellArrayFromKernel{T,N,K,V}(k,v)
end

function length(self::CellArrayFromKernel)
  vi, = self.cellvalues
  length(vi)
end

@inline function iterate(self::CellArrayFromKernel{T,N}) where {T,N}
  zipped = zip(self.cellvalues...)
  znext = iterate(zipped)
  v = CachedArray(T,N)
  _iterate(self,znext,zipped,v)
end

@inline function iterate(self::CellArrayFromKernel,state)
  zipped, zstate, v = state
  znext = iterate(zipped,zstate)
  _iterate(self,znext,zipped,v)
end

@inline function _iterate(self::CellArrayFromKernel,znext,zipped,v)
  if znext === nothing; return nothing end
  a, zstate = znext
  s = _compute_sizes(a...)
  z = compute_size(self.kernel,s...)
  setsize!(v,z)
  compute_value!(v,self.kernel,a...)
  state = (zipped,zstate,v)
  (v, state)
end

const _bs = _size_for_broadcast

# TODO use a generated function?
_compute_sizes(a...) = @notimplemented
_compute_sizes(a1) = (_bs(a1),)
_compute_sizes(a1,a2) = (_bs(a1),_bs(a2))
_compute_sizes(a1,a2,a3) = (_bs(a1),_bs(a2),_bs(a3))
_compute_sizes(a1,a2,a3,a4) = (_bs(a1),_bs(a2),_bs(a3),_bs(a4))
_compute_sizes(a1,a2,a3,a4,a5) = (_bs(a1),_bs(a2),_bs(a3),_bs(a4),_bs(a5))
_compute_sizes(a1,a2,a3,a4,a5,a6) = (_bs(a1),_bs(a2),_bs(a3),_bs(a4),_bs(a5),_bs(a6))

struct IndexCellArrayFromKernel{T,N,K,V} <: IndexCellArray{T,N,CachedArray{T,N,Array{T,N}},1}
  kernel::K
  cellvalues::V
  cache::CachedArray{T,N,Array{T,N}}
end

function IndexCellArrayFromKernel(k::ArrayKernel,v::Vararg{<:CellValue})
  _checks(v)
  T = _compute_T(k,v)
  N = _compute_N(k,v)
  K = typeof(k)
  V = typeof(v)
  cache = CachedArray(T,N)
  IndexCellArrayFromKernel{T,N,K,V}(k,v,cache)
end

function length(self::IndexCellArrayFromKernel)
  vi, = self.cellvalues
  length(vi)
end

size(self::IndexCellArrayFromKernel) = (length(self),)

function getindex(self::IndexCellArrayFromKernel,i::Integer)
  a = _getvalues(i,self.cellvalues...)
  s = _compute_sizes(a...)
  z = compute_size(self.kernel,s...)
  v = self.cache
  setsize!(v,z)
  compute_value!(v,self.kernel,a...)
  v
end

end # module


text:
using StochasticDiffEq, Test
function f(du,u,p,t)
  du[1] = u[2]
  du[2] = -9.81
end

function g(du,u,p,t)
  nothing
end

function condtion(u,t,integrator) # Event when event_f(u,p,t,k) == 0
  u[1]
end

affect! = nothing
function affect_neg!(integrator)
  integrator.u[2] = -integrator.u[2]
end

# Continuous callback
callback = ContinuousCallback(condtion,affect!,affect_neg!)

u0 = [50.0,0.0]
tspan = (0.0,15.0)
prob = SDEProblem(f,g,u0,tspan)

sol = solve(prob,SRIW1(),callback=callback,adaptive=false,dt=3/4)

@test minimum(sol[1,:]) > -1e-12 && minimum(sol[1,:]) < 1e-12

sol = solve(prob,SRIW1(),callback=callback,save_everystep=false)
t = sol.t[end÷2] # this is the callback time point
sol = solve(prob,SRIW1(),callback=callback,saveat=t)
@test count(x->x==t, sol.t) == 2
sol = solve(prob,SRIW1(),callback=callback,saveat=t-eps(t))
@test count(x->x==t, sol.t) == 2

function g(du,u,p,t)
  du[2] = .125*u[2]
end

prob = SDEProblem(f,g,u0,tspan)

sol = solve(prob,SRIW1(),callback=callback)

sol = solve(prob,EM(),callback=callback,dt=1/4)

# Discrete callback
tstop = [5.;8.]
condition_dc = (u,t,integrator) -> t in tstop
affect!_dc = (integrator) -> integrator.u .= 1.0
save_positions = (true,true)
callback_dc = DiscreteCallback(condition_dc, affect!_dc, save_positions=save_positions)
sol = solve(prob, SRIW1(), callback=callback_dc, tstops=tstop, saveat=tstop)
@test count(x->x==tstop[1], sol.t) == 2
@test count(x->x==tstop[2], sol.t) == 2
sol = solve(prob, SRIW1(), callback=callback_dc, tstops=tstop, saveat=prevfloat.(tstop))
@test count(x->x==tstop[1], sol.t) == 2
@test count(x->x==tstop[2], sol.t) == 2

###
# https://github.com/SciML/DifferentialEquations.jl/issues/802
###

function HM_neuron!(du,u,Params,t)
    # Membrane voltage
    du[1] = -u[1]^3 + 3.0 * u[1]^2 + u[2] - u[3] + u[4]*u[1];

    # Fast channel
    du[2] = 1.0 - 5.0 * u[1]^2 - u[2];

    # Slow channel
    val = Params.s * (u[1] + 8.0/5.0);
    du[3] = Params.r * (val - u[3]);

    # Synapse
    du[4] = -u[4]/Params.syntau;
end

function HM_noise!(du,u,Params,t)
    du[1] = 0.1;
    du[2] = 0.0;
    du[3] = 0.0;
    du[4] = 0.0;
end

tvals = range(0.0,stop=1999.9,length=20000);
struct P
    r::Float64
    s::Float64
    I::Float64
    syntau::Float64
    gSyn::Float64
end

params = P(0.001,1,0.0,5,0.0);
x0 = Float64[-1.6,-11.8,0.0,0.0];

condition2(u,t,integrator) = u[1];
affect2!(integrator) = integrator.u[4] = integrator.u[4] - params.gSyn; # Inhibitory exponential decay synapse
cb = ContinuousCallback(condition2,affect2!,nothing);
prob = SDEProblem(HM_neuron!,HM_noise!,x0,(0.0,1999.9),params);
sol  = solve(prob,ImplicitEM(),reltol = 1e-4, abstol = 1e-6,dense = true,callback=cb);
sol  = solve(prob,SKenCarp(),reltol = 1e-4, abstol = 1e-6,dense = true,callback=cb);

max_stars_repo_name: JuliaDiffEq/StochasticDiffEq


text:
"""
    make_twospirals(;    n_samples::Int = 2000,
                             start_degrees::Int = 90,
                             total_degrees::Int = 570,
                             noise::Float64 = 0.2
Generate two spirals dataset. Return a Nx3 matrix, where each line contains the X,Y coordinates and the class of an instance.
# Arguments
- `n_samples::Int = 2000`: The total number of points generated.
- `start_degrees::Int = 90`: Determines how far from the origin the spirals start.
- `total_degrees::Int = 570`: Controls the lenght of the spirals.
- `noise::Float64 = 0.2`: Determines the noise in the dataset.
Reference: [link](https://la.mathworks.com/matlabcentral/fileexchange/41459-6-functions-for-generating-artificial-datasets)
"""
function make_twospirals(; n_samples::Int = 2000,
                               start_degrees::Int = 90,
                               total_degrees::Int = 570,
                               noise::Float64 = 0.2)
   start_degrees = deg2rad(start_degrees);

   N1 = floor(Int, n_samples / 2);
   N2 = n_samples - N1;

   n = start_degrees .+ sqrt.(rand(N1,1)) .* deg2rad(total_degrees);
   d1 = [-cos.(n).*n + rand(N1,1).*noise sin.(n).*n+rand(N1,1).*noise];

   n = start_degrees .+ sqrt.(rand(N2,1)) .* deg2rad(total_degrees);
   d2 = [cos.(n).*n+rand(N2,1)*noise -sin.(n).*n+rand(N2,1)*noise];

   features = [d1; d2]
   labels = [zeros(Int, N1); ones(Int, N2)]

   return convert(features, labels);
end

"""
      make_halfkernel(; n_samples::Int = 1000,
                               minx::Int = -20,
                               r1::Int = 20,
                               r2::Int = 35,
                               noise::Float64 = 4.0,
                               ratio::Float64 = 0.6)
Generates two half ellipses, one inside the other
# Arguments
- `n_samples::Int = 1000`: The total number of points generated
- `r1::Int = 20`:
- `r2::Int = 35`:
- `minx::Int = -20`:
- `noise::Float64 = 0.2`: Determines the noise in the dataset.
- `ratio::Float64 = 0.6)`:
Reference: [link](https://la.mathworks.com/matlabcentral/fileexchange/41459-6-functions-for-generating-artificial-datasets)
"""
function make_halfkernel(; n_samples::Int = 1000,
                               minx::Int = -20,
                               r1::Int = 20,
                               r2::Int = 35,
                               noise::Float64 = 4.0,
                               ratio::Float64 = 0.6)

   N = floor(Int, n_samples / 2)

   phi1 = rand(N, 1) * pi
   inner = [minx .+ r1 .* sin.(phi1) .- .5 .* noise .+ noise .* rand(N, 1) r1 .* ratio .* cos.(phi1) .- .5 .* noise .+ noise .* rand(N,1)]
   l1 = ones(Int, N)

   phi2 = rand(N,1) * pi
   outer = [minx .+ r2 .* sin.(phi2) .- .5 .* noise  .+ noise .* rand(N,1) r2 .* ratio .* cos.(phi2) .- .5 .* noise  .+ noise .* rand(N,1)]
   l2 = zeros(Int, N)

   features = [inner; outer]
   labels = [l1; l2]

   return convert(features, labels)
end

"""
      make_outlier(;n_samples::Int = 600,
                                 r::Int = 20,
                                 dist::Int = 30,
                                 outliers::Float64 = 0.04,
                                 noise::Float64 = 5.0)
Generates outlier dataset.
# Arguments
- `n_samples::600 = 1000`: The total number of points generated.
- `r::Int = 20`: Radius of lateral blobs.
- `dist::Int = 30`: Determine the distance between the labels.
- `noise::Float64 = 5.0`: Determines the noise in the dataset.
Reference: [link](https://la.mathworks.com/matlabcentral/fileexchange/41459-6-functions-for-generating-artificial-datasets)
"""
function make_outlier(;n_samples::Int = 600,
                           r::Int = 20,
                           dist::Int = 30,
                           outliers::Float64 = 0.04,
                           noise::Float64 = 5.0)

   n1 = round(Int, (n_samples * (0.5 - outliers)) )
   n2 = n1
   n3 = round(Int, n_samples * outliers)
   n4 = n_samples - n1 - n2 - n3

   phi1 = rand(n1, 1) * pi
   r1 = sqrt.(rand(n1, 1)) * r
   p1 = [ -dist .+ (r1 .* sin.(phi1)) r1 .* cos.(phi1)]
   l1 = zeros(Int, n1)

   phi2 = rand(n2, 1) * pi
   r2 = sqrt.(rand(n2, 1)) * r
   p2 = [ dist .- r2.*sin.(phi2) r2.*cos.(phi2)]
   l2 = 3 * ones(Int, n2)

   p3 = [ rand(n3, 1) * noise   dist .+ rand(n3, 1) * noise ]
   l3 = 2 * ones(Int, n3)

   p4 = [ rand(n4, 1) * noise -dist .+ rand(n4, 1) * noise ]
   l4 = ones(Int, n4)

   features = [p1; p2; p3; p4]
   labels = [l1; l2; l3; l4]

   return convert(features, labels)
end


text:
"""
Creates a DataFrame from a JuMP DenseAxisArray or SparseAxisArray.

# Arguments

  - `array`: JuMP DenseAxisArray or SparseAxisArray to convert
  - `key::OptimizationContainerKey`:
"""
function axis_array_to_dataframe(
    array::Union{DenseAxisArray, SparseAxisArray},
    key::OptimizationContainerKey,
)
    return DataFrames.DataFrame(to_matrix(array), get_column_names(key, array))
end

function axis_array_to_dataframe(array::Matrix{Float64}, key::OptimizationContainerKey)
    return DataFrames.DataFrame(array, get_column_names(key, array))
end

function to_matrix(df::DataFrames.DataFrame)
    return Matrix{Float64}(vals)
end

function to_matrix(df_row::DataFrames.DataFrameRow{DataFrames.DataFrame, DataFrames.Index})
    return reshape(Vector(df_row), 1, size(df_row)[1])
end

function write_data(
    vars_results::Dict,
    time::DataFrames.DataFrame,
    save_path::AbstractString,
)
    for (k, v) in vars_results
        var = DataFrames.DataFrame()
        if size(time, 1) == size(v, 1)
            var = hcat(time, v)
        else
            var = v
        end
        file_path = joinpath(save_path, "$(k).csv")
        CSV.write(file_path, var)
    end
end

function write_data(
    data::DataFrames.DataFrame,
    save_path::AbstractString,
    file_name::String,
)
    if isfile(save_path)
        save_path = dirname(save_path)
    end
    file_path = joinpath(save_path, "$(file_name).csv")
    CSV.write(file_path, data)
    return
end

# writing a dictionary of dataframes to files
function write_data(vars_results::Dict, save_path::String; kwargs...)
    name = get(kwargs, :name, "")
    for (k, v) in vars_results
        keyname = encode_key_as_string(k)
        file_path = joinpath(save_path, "$name$keyname.csv")
        @debug "writing" file_path
        if isempty(vars_results[k])
            @debug "$name$k is empty, not writing $file_path"
        else
            CSV.write(file_path, vars_results[k])
        end
    end
end


text:
# Performance tests comparing different method dispatch implementations

using Base.Test

@enum ECompoundingType EContinuous=1 ESimple=2 EExponential=3

abstract TCompoundType

type TContinuous <: TCompoundType end
type TSimple <: TCompoundType end
type TExponential <: TCompoundType end

function ediscount_factor(compounding::ECompoundingType, r::Real, t::Real)
	if compounding == EContinuous
		return 1.0 / exp(r*t)
	elseif compounding == ESimple
		return 1.0 / (1 + r*t)
	elseif compounding == EExponential
		return 1.0 / ((1+r)^t)
	else
		error("Unknown compounding type $(compounding)")
	end
end

function vdiscount_factor(::Type{Val{EContinuous}}, r::Real, t::Real)
	return 1.0 / exp(r*t)
end

function vdiscount_factor(::Type{Val{ESimple}}, r::Real, t::Real)
	return 1.0 / (1 + r*t)
end

function vdiscount_factor(::Type{Val{EExponential}}, r::Real, t::Real)
	return 1.0 / ((1+r)^t)
end

function tdiscount_factor(::TContinuous, r::Real, t::Real)
	return 1.0 / exp(r*t)
end

function tdiscount_factor(::TSimple, r::Real, t::Real)
	return 1.0 / (1 + r*t)
end

function tdiscount_factor(::TExponential, r::Real, t::Real)
	return 1.0 / ((1+r)^t)
end

function tdiscount_factor(c::TCompoundType, r::Real, t::Real)
	error("not implemented for type $(typeof(c))")
end

Base.call(c::TContinuous, r::Real, t::Real) = 1.0 / exp(r*t)
Base.call(c::TSimple, r::Real, t::Real) = 1.0 / (1 + r*t)
Base.call(c::TExponential, r::Real, t::Real) = 1.0 / ((1+r)^t)

const _compound_functions = [
	(r::Real,t::Real) -> 1.0/exp(r*t),
	(r::Real,t::Real) -> 1.0/(1+r*t),
	(r::Real,t::Real) -> 1.0/((1+r)^t)
]

function rdiscount_factor(compounding::ECompoundingType, r::Real, t::Real)
	return _compound_functions[Int(compounding)](r,t)
end

function rdiscount_factor(c::Int64, r::Real, t::Real)
	return _compound_functions[c](r,t)
end

func_c = TContinuous()
func_s = TSimple()
func_e = TExponential()

# Continuous
ef_c = ediscount_factor(EContinuous, 0.15, 2.0)
vf_c = vdiscount_factor(Val{EContinuous}, 0.15, 2.0)
tf_c = tdiscount_factor(TContinuous(), 0.15, 2.0)
rf_c = rdiscount_factor(EContinuous, 0.15, 2.0)
rif_c = rdiscount_factor(1, 0.15, 2.0)
ff_c = func_c(0.15, 2.0)

# Simple
ef_s = ediscount_factor(ESimple, 0.15, 2.0)
vf_s = vdiscount_factor(Val{ESimple}, 0.15, 2.0)
tf_s = tdiscount_factor(TSimple(), 0.15, 2.0)
rf_s = rdiscount_factor(ESimple, 0.15, 2.0)
rif_s = rdiscount_factor(2, 0.15, 2.0)
ff_s = func_s(0.15, 2.0)

# Exponential
ef_e = ediscount_factor(EExponential, 0.15, 2.0)
vf_e = vdiscount_factor(Val{EExponential}, 0.15, 2.0)
tf_e = tdiscount_factor(TExponential(), 0.15, 2.0)
rf_e = rdiscount_factor(EExponential, 0.15, 2.0)
rif_e = rdiscount_factor(3, 0.15, 2.0)
ff_e = func_e(0.15, 2.0)

@test ef_c == vf_c == tf_c == rf_c == rif_c == ff_c
@test ef_s == vf_s == tf_s == rf_s == rif_s == ff_s
@test ef_e == vf_e == tf_e == rf_e == rif_e == ff_e

#EContinuous=1 ESimple=2 EExponential=3
println("enums with switch code")
@time begin
		for i = 1:10000000
			ediscount_factor(EContinuous, 0.15, 2.0)
			ediscount_factor(ESimple, 0.15, 2.0)
			ediscount_factor(EExponential, 0.15, 2.0)
		end
	end

println("Dispatch via Val Type")
@time begin
		for i = 1:10000000
			vdiscount_factor(Val{EContinuous}, 0.15, 2.0)
			vdiscount_factor(Val{ESimple}, 0.15, 2.0)
			vdiscount_factor(Val{EExponential}, 0.15, 2.0)
		end
	end

println("Dispatch via Const Val Type")
const cValCont = Val{EContinuous}
const cValSim = Val{ESimple}
const cValExp = Val{EExponential}
@time begin
		for i = 1:10000000
			vdiscount_factor(cValCont, 0.15, 2.0)
			vdiscount_factor(cValSim, 0.15, 2.0)
			vdiscount_factor(cValExp, 0.15, 2.0)
		end
	end

println("Dispatch via Type")
@time begin
		for i = 1:10000000
			tdiscount_factor(TContinuous(), 0.15, 2.0)
			tdiscount_factor(TSimple(), 0.15, 2.0)
			tdiscount_factor(TExponential(), 0.15, 2.0)
		end
	end

println("Raw function vector dispatch")
@time begin
		for i = 1:10000000
			rdiscount_factor(EContinuous, 0.15, 2.0)
			rdiscount_factor(ESimple, 0.15, 2.0)
			rdiscount_factor(EExponential, 0.15, 2.0)
		end
	end

println("Raw function vector dispatch with integers")
@time begin
		for i = 1:10000000
			rdiscount_factor(1, 0.15, 2.0)
			rdiscount_factor(2, 0.15, 2.0)
			rdiscount_factor(3, 0.15, 2.0)
		end
	end

println("Functors")
fc = TContinuous()
fs = TSimple()
fe = TExponential()

@time begin
		for i = 1:10000000
			fc(0.15, 2.0)
			fs(0.15, 2.0)
			fe(0.15, 2.0)
		end
	end

println("Const Functors")
const cfc = TContinuous()
const cfs = TSimple()
const cfe = TExponential()

@time begin
		for i = 1:10000000
			cfc(0.15, 2.0)
			cfs(0.15, 2.0)
			cfe(0.15, 2.0)
		end
	end


text:
export MtlLibrary, MtlLibraryFromFile, function_names

const MTLLibrary = Ptr{MtLibrary}

"""
    MtlDevice(i::Integer)

Get a handle to a compute device.
"""
mutable struct MtlLibrary
    handle::MTLLibrary
    device::MtlDevice
end

Base.convert(::Type{MTLLibrary}, lib::MtlLibrary) = lib.handle
Base.unsafe_convert(::Type{MTLLibrary}, lib::MtlLibrary) = convert(MTLLibrary, lib.handle)

Base.:(==)(a::MtlLibrary, b::MtlLibrary) = a.handle == b.handle
Base.hash(lib::MtlLibrary, h::UInt) = hash(lib.handle, h)

## Properties
device(l::MtlLibrary) = l.device
function label(l::MtlLibrary)
    ptr = mtLibraryLabel(l)
    return ptr == C_NULL ? "" : unsafe_string(ptr)
end

function MtlLibrary(device::MtlDevice, src::String, opts::MtlCompileOptions)
    handle = @mtlthrows _errptr mtNewLibraryWithSource(device, src, opts, _errptr)

    obj = MtlLibrary(handle, device)
    finalizer(unsafe_destroy!, obj)

    return obj
end

function MtlLibraryFromFile(device::MtlDevice, path::String)
    handle = @mtlthrows _errptr mtNewLibraryWithFile(device, path, _errptr)

    obj = MtlLibrary(handle, device)
    finalizer(unsafe_destroy!, obj)

    return obj
end

function unsafe_destroy!(lib::MtlLibrary)
    lib.handle !== C_NULL && mtLibraryRelease(lib)
end

function Base.show(io::IO, l::MtlLibrary)
    print(io, "MtlLibrary($(l.device))")
end

function Base.show(io::IO, ::MIME"text/plain", l::MtlLibrary)
    println(io, "MtlLibrary:")
    println(io, " device : ", device(l))
    print(io, " label  : ", label(l))
end

function function_names(l::MtlLibrary)
    _nms = mtLibraryFunctionNames(l)
    names = Vector{String}()
    for i = 0:typemax(Int)
        nm = unsafe_load(_nms + i * 8)
        nm == C_NULL && break
        push!(names, unsafe_string(nm))
    end
    Base.Libc.free(_nms)

    return names
end


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

struct AutoscalingV1Api <: SwaggerApi
    client::Swagger.Client
end

function _swaggerinternal_createAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", IoK8sApiAutoscalingV1HorizontalPodAutoscaler, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

create a HorizontalPodAutoscaler
Param: namespace::String (required)
Param: body::IoK8sApiAutoscalingV1HorizontalPodAutoscaler (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscaler
"""
function createAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_createAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function createAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_createAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

delete collection of HorizontalPodAutoscaler
Param: namespace::String (required)
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: __continue__::String
Param: dryRun::String
Param: fieldSelector::String
Param: gracePeriodSeconds::Int32
Param: labelSelector::String
Param: limit::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, body=body, __continue__=__continue__, dryRun=dryRun, fieldSelector=fieldSelector, gracePeriodSeconds=gracePeriodSeconds, labelSelector=labelSelector, limit=limit, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, body=body, __continue__=__continue__, dryRun=dryRun, fieldSelector=fieldSelector, gracePeriodSeconds=gracePeriodSeconds, labelSelector=labelSelector, limit=limit, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_deleteAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

delete a HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: pretty::String
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: dryRun::String
Param: gracePeriodSeconds::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, body=body, dryRun=dryRun, gracePeriodSeconds=gracePeriodSeconds, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function deleteAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, body=body, dryRun=dryRun, gracePeriodSeconds=gracePeriodSeconds, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_getAutoscalingV1APIResources(_api::AutoscalingV1Api; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1APIResourceList, "/apis/autoscaling/v1/", ["BearerToken"])
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"] : [_mediaType])
    return _ctx
end

"""

get available resources
Return: IoK8sApimachineryPkgApisMetaV1APIResourceList
"""
function getAutoscalingV1APIResources(_api::AutoscalingV1Api; _mediaType=nothing)
    _ctx = _swaggerinternal_getAutoscalingV1APIResources(_api; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function getAutoscalingV1APIResources(_api::AutoscalingV1Api, response_stream::Channel; _mediaType=nothing)
    _ctx = _swaggerinternal_getAutoscalingV1APIResources(_api; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces(_api::AutoscalingV1Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV1HorizontalPodAutoscalerList, "/apis/autoscaling/v1/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

list or watch objects of kind HorizontalPodAutoscaler
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscalerList
"""
function listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces(_api::AutoscalingV1Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces(_api::AutoscalingV1Api, response_stream::Channel; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_listAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV1HorizontalPodAutoscalerList, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

list or watch objects of kind HorizontalPodAutoscaler
Param: namespace::String (required)
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscalerList
"""
function listAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function listAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_patchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", IoK8sApiAutoscalingV1HorizontalPodAutoscaler, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_param(_ctx.query, "force", force)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json-patch+json", "application/merge-patch+json", "application/strategic-merge-patch+json", "application/apply-patch+yaml"] : [_mediaType])
    return _ctx
end

"""

partially update the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApimachineryPkgApisMetaV1Patch (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Param: force::Bool
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscaler
"""
function patchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function patchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", IoK8sApiAutoscalingV1HorizontalPodAutoscaler, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}/status", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_param(_ctx.query, "force", force)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json-patch+json", "application/merge-patch+json", "application/strategic-merge-patch+json", "application/apply-patch+yaml"] : [_mediaType])
    return _ctx
end

"""

partially update status of the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApimachineryPkgApisMetaV1Patch (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Param: force::Bool
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscaler
"""
function patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_readAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV1HorizontalPodAutoscaler, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "exact", exact)  # type Bool
    Swagger.set_param(_ctx.query, "export", __export__)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

read the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: pretty::String
Param: exact::Bool
Param: __export__::Bool
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscaler
"""
function readAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, exact=exact, __export__=__export__, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function readAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, exact=exact, __export__=__export__, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, name::String, namespace::String; pretty=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV1HorizontalPodAutoscaler, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}/status", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

read status of the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: pretty::String
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscaler
"""
function readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, name::String, namespace::String; pretty=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace; pretty=pretty, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String; pretty=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace; pretty=pretty, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_replaceAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", IoK8sApiAutoscalingV1HorizontalPodAutoscaler, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

replace the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApiAutoscalingV1HorizontalPodAutoscaler (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscaler
"""
function replaceAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function replaceAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", IoK8sApiAutoscalingV1HorizontalPodAutoscaler, "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}/status", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

replace status of the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApiAutoscalingV1HorizontalPodAutoscaler (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAutoscalingV1HorizontalPodAutoscaler
"""
function replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces(_api::AutoscalingV1Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/autoscaling/v1/watch/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

watch individual changes to a list of HorizontalPodAutoscaler. deprecated: use the 'watch' parameter with a list operation instead.
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces(_api::AutoscalingV1Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces(_api::AutoscalingV1Api, response_stream::Channel; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_watchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/autoscaling/v1/watch/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

watch changes to an object of kind HorizontalPodAutoscaler. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.
Param: name::String (required)
Param: namespace::String (required)
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, name::String, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function watchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api::AutoscalingV1Api, response_stream::Channel, name::String, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV1NamespacedHorizontalPodAutoscaler(_api, name, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_watchAutoscalingV1NamespacedHorizontalPodAutoscalerList(_api::AutoscalingV1Api, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/autoscaling/v1/watch/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

watch individual changes to a list of HorizontalPodAutoscaler. deprecated: use the 'watch' parameter with a list operation instead.
Param: namespace::String (required)
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAutoscalingV1NamespacedHorizontalPodAutoscalerList(_api::AutoscalingV1Api, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV1NamespacedHorizontalPodAutoscalerList(_api, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function watchAutoscalingV1NamespacedHorizontalPodAutoscalerList(_api::AutoscalingV1Api, response_stream::Channel, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV1NamespacedHorizontalPodAutoscalerList(_api, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export createAutoscalingV1NamespacedHorizontalPodAutoscaler, deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler, deleteAutoscalingV1NamespacedHorizontalPodAutoscaler, getAutoscalingV1APIResources, listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces, listAutoscalingV1NamespacedHorizontalPodAutoscaler, patchAutoscalingV1NamespacedHorizontalPodAutoscaler, patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus, readAutoscalingV1NamespacedHorizontalPodAutoscaler, readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus, replaceAutoscalingV1NamespacedHorizontalPodAutoscaler, replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus, watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces, watchAutoscalingV1NamespacedHorizontalPodAutoscaler, watchAutoscalingV1NamespacedHorizontalPodAutoscalerList


text:
# This file calculate the whole aerodynamic force of the rotor in the hub

function beforce(vall_r,chord,Cl,Cd,α_aero,θ,dr,beta=0.0)
  # vall_r = Array{Vector}(NR,Nbe)
  # for k in 1:NR # 将总速度由旋转坐标系转化到叶素坐标系
  #   for i in 1:Nbe
  #     vall_r[k,i] = rotobe(vall_r[k,i],beta,θ[k,i])
  #   end
  # end
  L = abs(1/2*ρ*norm(vall_r)^2*chord*Cl)
  D = abs(1/2*ρ*norm(vall_r)^2*chord*Cd)
  if α_aero>=0
    L_be = [0,cos(α_aero+π/2),-sin(α_aero+π/2)] # 叶素当地升力单位矢量
  else
    L_be = [0,cos(α_aero-π/2),-sin(α_aero-π/2)]
  end
  D_be = [0,cos(α_aero),-sin(α_aero)] # 叶素当地阻力单位矢量
  L_ro = betoro(L_be,beta,θ) # 旋转坐标系叶素升力单位矢量
  D_ro = betoro(D_be,beta,θ) # 旋转坐标系叶素阻力单位矢量
  Fbez = (L*L_ro[3]+D*D_ro[3])*dr # 旋转坐标系叶素z向力
  Fbey = (L*L_ro[2]+D*D_ro[2])*dr # 旋转坐标系叶素y向力
  return Fbez,Fbey
end

function rotorforce(ψ,vall_r,α_aero,θ,Cl,Cd,filename=pwd()*"\\force_record\\fhub.txt")
  # filebf = open(filename,"w")
  # write(filebf,"List  ZForce  YForce\n")

  Fz_r = 0.0 # 旋转坐标系轴向力
  Fy_r = 0.0 # 旋转坐标系y向力
  MQ = 0.0 # 扭矩
  Mβ_aero = zeros(Float64,NR) # 初始化气动力挥舞力矩
  for k in 1:NR
    # write(filebf,"$(k)\t\n")
    for i in 1:Nbe
      fbe = beforce(vall_r[k,i],ch[k,i],Cl[k,i],Cd[k,i],
                      α_aero[k,i],θ[k,i],dr[k,i])
      fbez = fbe[1]
      fbey = fbe[2]
      MQ += fbey*rb[k,i]
      Mβ_aero[k] += fbez*(rb[k,i]-ecut*R)
      Fz_r += fbez
      Fy_r += fbey
      # write(filebf,"$(i)  $(Fzr)  $(Fyr)\n")
    end
  end

  # write(filebf,"The Whole Force of Z is : $(Fzr)\n")
  # write(filebf,"The Whole Force of Y is : $(Fyr)\n")
  #
  # close(filebf)
  Fy_s = Fy_r*cos(ψ)
  Fx_s = -Fy_r*sin(ψ)
  Fz_s = Fz_r

  return Fx_s,Fy_s,Fz_s,MQ,Mβ_aero
end

max_stars_repo_name: dingzhw/RotorTrim

max_issues_repo_name: helicopterliu/RotorTrim

max_forks_repo_name: helicopterliu/RotorTrim


text:
using Pkg
Pkg.activate(".")

function peaks(x, y)
    z = 3 * (1 - x)^2 * exp(-x^2 - (y + 1)^2)
    z += -10 * (x / 5 - x^3 - y^5) * exp(-x^2 - y^2)
    z += -1/3 * exp(-(x+1)^2 - y^2)
    return z
end

x = range(-3, stop = 3, length = 100)
y = range(-2, stop = 2, length = 80)
levels = collect(-4:0.25:4)
vmin = minimum(levels)
vmax = maximum(levels)

using Plots
pyplot() # Set the backend to PyPlot
plt = contourf(x, y, peaks, levels = levels, clim = (vmin, vmax),
              colorbar_title = "\$\\phi\$",
              colorbar = :right,
              xlabel = "\$x\$",
              ylabel = "\$y\$")
display(plt)
savefig(plt, "test.eps")
savefig(plt, "test.pdf")
savefig(plt, "test.png")
savefig(plt, "test.svg")
savefig(plt, "test.html")

max_stars_repo_name: briochemc/JuliaPlotting

max_issues_repo_name: briochemc/JuliaPlotting

max_forks_repo_name: briochemc/JuliaPlotting


text:
#######################################################################
# History: global In/Out and other exported history variables
const In = Dict{Integer,UTF8String}()
const Out = Dict{Integer,Any}()
_ = __ = __ = ans = nothing

export In, Out, _, __, ___
# (don't export ans to avoid conflicts from "using IJulia" in ordinary REPL;
#  ans is imported into Main by kernel.jl)

# execution counter
_n = 0

#######################################################################
# methods to clear history or any subset thereof

export clear_history # user-visible in IJulia

function clear_history(indices)
    for n in indices
        delete!(In, n, nothing)
        if haskey(Out, n)
            delete!(Out, n)
            # no way to undefine _{n} variable, but we can set it to nothing
            eval(Main, :($(symbol(string("_",n))) = nothing))
        end
    end
end

# since a range could be huge, intersect it with 1:_n first
clear_history{T<:Integer}(r::Ranges{T}) =
    invoke(clear_history, (Any,), intersect(r, 1:_n))

function clear_history()
    clear_history(1:_n)
    global _, __, ___, ans
    ans = _ = __ = ___ = nothing
end

#######################################################################


text:
module MultiFEBases

using Gridap
using Gridap.Helpers

import Gridap: gradient
import Gridap: symmetric_gradient
import Base: div
import Gridap: trace
import Gridap: curl
import Gridap: inner
import Gridap: varinner
import Gridap: outer
import Base: +, -, *
import Base: length, getindex
import Gridap.FESpaces: FEBasis
import Gridap: CellBasis
import Gridap: restrict
import Gridap: Triangulation
import Base: iterate

struct FEBasisWithFieldId{B<:FEBasis}
  febasis::B
  fieldid::Int
end

Triangulation(a::FEBasisWithFieldId) = Triangulation(a.febasis)

function CellBasis(
  trian::Triangulation{D,Z},
  fun::Function,
  b::FEBasisWithFieldId,
  u...) where {D,Z}

  _u = [_prepare_febasis(ui) for ui in u]

  febasis = CellBasis(trian,fun,b.febasis,_u...)
  FEBasisWithFieldId(febasis,b.fieldid)
end

_prepare_febasis(ui) = ui

_prepare_febasis(ui::FEBasisWithFieldId) = ui.febasis

for op in (:+,:-,:(gradient),:(symmetric_gradient),:(div),:(trace),:(curl))
  @eval begin
    function ($op)(a::FEBasisWithFieldId)
      FEBasisWithFieldId($op(a.febasis),a.fieldid)
    end
  end
end

for op in (:+, :-, :*, :outer)
  @eval begin

    function ($op)(a::FEBasisWithFieldId,b::CellField)
      FEBasisWithFieldId($op(a.febasis,b),a.fieldid)
    end

    function ($op)(a::CellField,b::FEBasisWithFieldId)
      FEBasisWithFieldId($op(a,b.febasis),b.fieldid)
    end

    function ($op)(a::FEBasisWithFieldId,b::Number)
      FEBasisWithFieldId($op(a.febasis,b),a.fieldid)
    end

    function ($op)(a::Number,b::FEBasisWithFieldId)
      FEBasisWithFieldId($op(a,b.febasis),b.fieldid)
    end

  end
end

function inner(a::FEBasisWithFieldId,b::CellField)
  block = inner(a.febasis,b)
  blocks = [block,]
  fieldids = [(a.fieldid,),]
  MultiCellMap(blocks,fieldids)
end

function varinner(a::FEBasisWithFieldId,b::CellField)
  inner(a,b)
end

function inner(a::FEBasisWithFieldId,f::Function)
  b = CellField(a.febasis.trian,f)
  inner(a,b)
end

function inner(a::FEBasisWithFieldId,b::FEBasisWithFieldId)
  block = inner(a.febasis,b.febasis)
  blocks = [block,]
  fieldids = [(a.fieldid,b.fieldid),]
  MultiCellMap(blocks,fieldids)
end

function varinner(a::FEBasisWithFieldId,b::FEBasisWithFieldId)
  inner(a,b)
end

function restrict(feb::FEBasisWithFieldId,trian::SkeletonTriangulation)
  sp = restrict(feb.febasis,trian)
  _new_sp(sp,feb.fieldid)
end

function _new_sp(sp::SkeletonPair{Z,T,N},fieldid) where {Z,T,N}
  b1 = FEBasisWithFieldId(sp.cellfield1,fieldid)
  b2 = FEBasisWithFieldId(sp.cellfield2,fieldid)
  SkeletonPair{Z,T,N}(b1,b2)
end

struct MultiFEBasis
  blocks::Vector{<:FEBasisWithFieldId}
end

iterate(m::MultiFEBasis) = iterate(m.blocks)

iterate(m::MultiFEBasis,state) = iterate(m.blocks,state)

function FEBasis(mfes::MultiFESpace)
  blocks = [ FEBasisWithFieldId(FEBasis(v),i) for (i,v) in enumerate(mfes) ]
  MultiFEBasis(blocks)
end

length(mfb::MultiFEBasis) = length(mfb.blocks)

getindex(mfb::MultiFEBasis,i::Integer) = mfb.blocks[i]

function restrict(mfeb::MultiFEBasis,trian::BoundaryTriangulation)
  blocks = [
    FEBasisWithFieldId(restrict(feb.febasis,trian),feb.fieldid)
    for feb in mfeb.blocks ]
  MultiFEBasis(blocks)
end

function restrict(mfeb::MultiFEBasis,trian::SkeletonTriangulation)
  [ restrict(feb,trian) for feb in mfeb.blocks ]
end

end # module MultiFEBases


text:
"""
fillMstat: fill-in the MPCCAtX state structure for the M-stationary conditions.

`fillMstat(:: AbstractMPCCModel, :: MPCCAtX; pnorm :: Float64 = Inf)`

"""
function fillMstat(pb    :: AbstractMPCCModel,  #:: AbstractNLPModel,
                   state :: MPCCAtX;
                   pnorm :: Float64 = Inf)

    ncon, ncc = pb.meta.ncon, pb.meta.ncc

    update!(state, gx = grad(pb, state.x)) #utiliser la fonction fill_in ?

    if length(state.lambda)+length(state.mu)+length(state.lG)+length(state.lH) == 0
     return norm(state.gx, pnorm)
    else
     n = length(state.x)
     pr = 1e-3

     wl = findall(x->(norm(x) <= pr), abs.(-state.x + pb.meta.lvar))
     wu = findall(x->(norm(x) <= pr), abs.(-state.x + pb.meta.uvar))
     lui = zeros(n); lui[wl] .= -1.0; lui[wu] .= 1.0; LUi = (diagm(0 => lui))
     #LUi = (diagm(0 => lui))[:,union(wl,wu)]

     if ncon > 0
      update!(state, Jx = jac(pb, state.x), cx = cons_nl(pb, state.x))
      Jx = zeros(size(state.Jx'))
      wc1 = findall(x->norm(x) <= pr, abs.(state.cx-pb.meta.ucon))
      wc2 = findall(x->norm(x) <= pr, abs.(state.cx-pb.meta.lcon))
      Jx[:,wc1] = (state.Jx')[:,wc1]
      Jx[:,wc2] = -(state.Jx')[:,wc2]
     end

     if ncc > 0
      update!(state, cGx = consG(pb, state.x), cHx = consH(pb, state.x))
      Jx = ncon > 0 ? Jx : zeros(size(state.Jx'))
      wG = findall(x->norm(x) <= pr, abs.(state.Gc))
      wH = findall(x->norm(x) <= pr, abs.(state.Hc))
      Jx[:,ncon.+wG] = (state.Jx')[:,ncon.+wG]
      Jx[:,ncon.+ncc.+wH] = (state.Jx')[:,ncon.+ncc.+wH]
     end

    if ncon + ncc >0
      Jct = hcat(LUi,Jx)
    else
      Jct = LUi
    end

     l = pinv(Jct) * (- state.gx)
     gLagx1 = Jct*l+state.gx
     res_nonlin1 = min.(vcat(l[n+wc1],l[n+wc2]),0.0)

     if !(true in isnan.(vcat(state.mu,state.lambda,state.lG,state.lH)))
      gLagx2 = Jct*vcat(state.mu, state.lambda,state.lG,state.lH)+state.gx
      res_nonlin2 = min.(vcat(state.lambda[wc1],state.lambda[wc2],state.lG[wG],state.lH[wH]),0.0)
     else
      gLagx2 = Inf
      res_nonlin2 = Inf
     end

     if norm(res_nonlin1) <= norm(res_nonlin2)
      state.mu, state.lambda = l[1:n], l[n+1:n+ncon]
      state.lG, state.lH     = l[n+ncon+1:n+ncon+ncc], l[n+ncon+ncc+1:n+ncon+2*ncc]
      gLagx = gLagx1
      res_nonlin = res_nonlin1
     else
      gLagx = gLagx2
      res_nonlin = res_nonlin2
     end
    end

    res_bounds = min.(state.mu,0.0)

    if ncon > 0
     Ib = ∩(wG,wH)
     res_mpcc = min.(state.lG[Ib].*state.lH[Ib],min.(state.lG[Ib],0)+min.(state.lH[Ib],0))
     feas = vcat(max.(state.cx   - pb.meta.ucon,0),max.(- state.cx + pb.meta.lcon,0),max.(  state.x - pb.meta.uvar,0), max.(- state.x + pb.meta.lvar,0))
    else
     res_mpcc = 0.0
     feas = vcat(max.(  state.x - pb.meta.uvar,0), max.(- state.x + pb.meta.lvar,0))
    end

    if ncc > 0
     res_mpcc = 0.0
     feas_mpcc = vcat(max.(-state.Gc,0),max.(-state.Gc,0),max.(state.Gc.*state.Hc,0))
    else
     res_mpcc = 0.0
     feas_mpcc = 0.0
    end
@show gLagx, feas, feas_mpcc, res_bounds, res_nonlin, res_mpcc
    res = vcat(gLagx, feas, feas_mpcc, res_bounds, res_nonlin, res_mpcc)
    if norm(res_nonlin) > pr
     #Z = nullspace(Jct)
     #I need to take care of this...
    end
@show norm(res, pnorm)
    return norm(res, pnorm)
end


text:
#=
Condense : remove empty row and column within the input Assoc A and return the new condensed Assoc
=#
function condense(A::Assoc)#performance improvement needed
    nonZeroCol = findnz(sum(A.A,1))[2]
    nonZeroRow = findnz(sum(A.A,2))[1]
    Newrow = A.row[nonZeroRow]
    Newcol = A.col[nonZeroCol]
    NewA = A.A[nonZeroRow,nonZeroCol]

    return Assoc(Newrow,Newcol,A.val,NewA)
end

########################################################
# D4M: Dynamic Distributed Dimensional Data Model
# Architect: Dr. Jeremy Kepner (kepner@ll.mit.edu)
# Software Engineer: Alexander Chen (alexc89@mit.edu)
########################################################


max_stars_repo_name: jstrube/adventofcode

max_issues_repo_name: jstrube/adventofcode

max_forks_repo_name: jstrube/adventofcode


text:
function __init__()
    @require Expokit = "a1e7a1ef-7a5d-5822-a38c-be74e1bb89f4" load_expokit()
    @require Optim = "429524aa-4258-5aef-a3af-852621145aeb" load_optim()
    @require Polyhedra = "67491407-f73d-577b-9b50-8179a7c68029" load_polyhedra()
    @require Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" load_distributions()
end

function load_expokit()
    eval(load_expokit_sparsematrixexp())
    eval(load_expokit_exponentialmap())
    eval(load_expokit_exponentialprojectionmap())
end

function load_optim()
    eval(load_optim_intersection())
end

function load_polyhedra()
    eval(load_polyhedra_abstractpolytope())
    eval(load_polyhedra_hpolytope())
    eval(load_polyhedra_hpolyhedron())
    eval(load_polyhedra_vpolytope())
end

function load_distributions()
    eval(load_distributions_samples())
end

"""
    require(package::Symbol; fun_name::String="", explanation::String="")

Helper method to check for optional packages and printing an error message.

### Input

- `package`     -- symbol of the package name
- `fun_name`    -- (optional; default: `""`) name of the function that requires
                   the package
- `explanation` -- (optional; default: `""`) additional explanation in the error
                   message

### Output

If the package is loaded, this function has no effect.
Otherwise it prints an error message.

### Algorithm

This function uses `@assert` and hence loses its ability to print an error
message if assertions are deactivated.
"""
function require(package::Symbol; fun_name::String="", explanation::String="")
    @assert isdefined(@__MODULE__, package) "package '$package' not loaded" *
        (fun_name == "" ? "" :
            " (it is required for executing `$fun_name`" *
            (explanation == "" ? "" : " " * explanation) * ")")
end


text:
# Scripts assume that `code/` is used as working directory
# From project root, it can be set with
# cd("./code/")
# or in Atom: right-click code/ > Juno:Work in folder

# Activate project environment
import Pkg; Pkg.activate(".")

# Load required packages
@info "Loading required packages"
using DifferentialEquations
using Plots

# Load Hastings & Powell's model
@info "Loading model"
include("HPmodel.jl")

# Make the figures
for figfile in filter(f -> isfile(f) && startswith(f, "figure") && !endswith(f, "gif.jl"), readdir())
    @info "Running $figfile"
    include(figfile)
end


text:
# This file was generated, do not modify it. # hide
first(dfY1, 3)


text:
include("testGetData.jl")
include("testSensitivity.jl")
include("testInversion.jl")
include("testTimeDomain.jl")


text:
"""
    integrate(func, u, weights)

Map the function `func` to the coefficients `u` and integrate with respect to
the quadrature rule given by `weights`.
"""
function integrate(func, u, weights::AbstractVector)
    Pp1 = length(weights)
    @boundscheck begin
        @assert Pp1 == length(u)
    end

    res = zero(func(first(u)))
    @inbounds for n in 1:Pp1
        res += func(u[n]) * weights[n]
    end
    res
end

function integrate(func, u, basis::NodalBasis)
    integrate(func, u, basis.weights)
end

integrate(u, weights_or_basis) = integrate(identity, u, weights_or_basis)


text:
struct Mesh
    dim::Any
    nelements::Any
    widths
    x0
    elementsize
    cellmaps::Any
    nodalcoordinates::Any
    nodalconnectivity::Any
    cellconnectivity::Any
    ncells::Any
    nfmside::Any
    totalnodes::Any
    nodesperelement::Any
    isinteriorcell::Any
end

function Mesh(mesh, nf::Int)
    dim = dimension(mesh)
    cellmaps = cell_maps(mesh)
    x0 = reference_corner(mesh)
    w = widths(mesh)
    nelements = elements_per_mesh_side(mesh)
    elementsize = w ./ nelements
    nfeside = nodes_per_element_side(nf)
    nfmside = nodes_per_mesh_side(nelements, nfeside)
    totalnodes = prod(nfmside)

    nodalcoordinates = nodal_coordinates(x0, widths(mesh), nelements, nfmside)
    nodalconnectivity = nodal_connectivity(nfmside, nfeside, nf, nelements)
    cellconnectivity = cell_connectivity(mesh)
    isinteriorcell = is_interior_cell(cellconnectivity)
    ncells = number_of_elements(mesh)
    Mesh(
        dim,
        nelements,
        w,
        x0,
        elementsize,
        cellmaps,
        nodalcoordinates,
        nodalconnectivity,
        cellconnectivity,
        ncells,
        nfmside,
        totalnodes,
        nf,
        isinteriorcell,
    )
end

function Mesh(mesh, basis)
    nf = number_of_basis_functions(basis)
    return Mesh(mesh, nf)
end

function Mesh(x0, widths, nelements, nf::Int)
    mesh = UniformMesh(x0, widths, nelements)
    return Mesh(mesh, nf)
end

function Mesh(x0, widths, nelements, basis)
    nf = number_of_basis_functions(basis)
    return Mesh(x0, widths, nelements, nf)
end

function cell_id(mesh::Mesh, x)
    dim = dimension(mesh)
    @assert length(x) == dim == 2
    elementsize = element_size(mesh)
    nelements = elements_per_mesh_side(mesh)
    x0 = reference_corner(mesh)
    @assert all(x .>= x0)
    cartesiancellid = [ceil(Int,i) for i in (x-x0) ./ elementsize]
    cellid = (cartesiancellid[1]-1)*nelements[2] + cartesiancellid[2]
    return cellid
end

function Base.show(io::IO, mesh::Mesh)
    ncells = number_of_cells(mesh)
    numnodes = number_of_nodes(mesh)
    dim = dimension(mesh)
    nf = nodes_per_element(mesh)
    str = "Mesh\n\tDimension : $dim\n\tNum. Cells: $ncells\n\tNum. Nodes: $numnodes\n\tNodes/Cell: $nf"
    print(io, str)
end

function number_of_cells(mesh::Mesh)
    return mesh.ncells
end

function nodes_per_mesh_side(mesh::Mesh)
    return mesh.nfmside
end

function element_size(mesh::Mesh)
    return mesh.elementsize
end

function reference_corner(mesh::Mesh)
    return mesh.x0
end

function number_of_nodes(mesh::Mesh)
    return mesh.totalnodes
end

function nodes_per_element(mesh::Mesh)
    return mesh.nodesperelement
end

function reference_corner(mesh::UniformMesh)
    return mesh.x0
end

function widths(mesh::UniformMesh)
    return mesh.widths
end

function widths(mesh::Mesh)
    return mesh.widths
end

function elements_per_mesh_side(mesh)
    return mesh.nelements
end

function cell_maps(mesh)
    ncells = number_of_elements(mesh)
    return [CellMap(element(mesh, i)...) for i = 1:ncells]
end

function cell_maps(mesh::Mesh)
    return mesh.cellmaps
end

function cell_map(mesh::Mesh, i)
    return mesh.cellmaps[i]
end

function determinant_jacobian(mesh::Mesh)
    return determinant_jacobian(cell_map(mesh, 1))
end

function jacobian(mesh::Mesh)
    return jacobian(cell_map(mesh, 1))
end

function face_determinant_jacobian(mesh::Mesh)
    return face_determinant_jacobian(cell_map(mesh, 1))
end

function nodes_per_mesh_side(nelements, nfeside)
    return (nfeside - 1) * nelements .+ 1
end

function nodes_per_element_side(nodesperelement)
    nfeside = sqrt(nodesperelement)
    @assert isinteger(nfeside)
    return round(Int, nfeside)
end

function nodal_coordinates(x0, widths, nelements, nfmside)
    @assert length(x0) == length(widths) == length(nelements) == 2

    xrange = range(x0[1], stop = x0[1] + widths[1], length = nfmside[1])
    yrange = range(x0[2], stop = x0[2] + widths[2], length = nfmside[2])

    ycoords = repeat(yrange, outer = nfmside[1])
    xcoords = repeat(xrange, inner = nfmside[2])
    return vcat(xcoords', ycoords')
end

function nodal_coordinates(mesh::Mesh)
    return mesh.nodalcoordinates
end

function nodal_connectivity(mesh::Mesh)
    return mesh.nodalconnectivity
end

function nodal_connectivity(mesh::Mesh,cellid)
    return mesh.nodalconnectivity[:,cellid]
end

function dimension(mesh::Mesh)
    return mesh.dim
end

function dimension(mesh::UniformMesh)
    return CartesianMesh.dimension(mesh)
end

function faces_per_cell(mesh::UniformMesh)
    return CartesianMesh.faces_per_cell(mesh)
end

function number_of_elements(mesh::UniformMesh)
    return CartesianMesh.number_of_elements(mesh)
end

function nodal_connectivity(nfmside, nfeside, nodesperelement, nelements)
    numnodes = prod(nfmside)
    ncells = prod(nelements)

    nodeids = reshape(1:numnodes, reverse(nfmside)...)
    connectivity = zeros(Int, nodesperelement, ncells)
    colstart = 1
    colend = nfeside

    cellid = 1
    for col = 1:nelements[1]
        rowstart = 1
        rowend = nfeside
        for row = 1:nelements[2]
            connectivity[:, cellid] .= vec(nodeids[rowstart:rowend, colstart:colend])
            cellid += 1
            rowstart = rowend
            rowend += nfeside - 1
        end
        colstart = colend
        colend += nfeside - 1
    end
    return connectivity
end

function cell_connectivity(mesh)
    ncells = number_of_elements(mesh)
    nfaces = faces_per_cell(mesh)
    connectivity = zeros(Int, nfaces, ncells)
    for cellid = 1:ncells
        connectivity[:, cellid] .= neighbors(mesh, cellid)
    end
    return connectivity
end

function cell_connectivity(mesh::Mesh)
    return mesh.cellconnectivity
end

function bottom_boundary_node_ids(mesh)
    nfmside = nodes_per_mesh_side(mesh)
    return range(1, step = nfmside[2], length = nfmside[1])
end

function right_boundary_node_ids(mesh)
    nfmside = nodes_per_mesh_side(mesh)
    start = nfmside[2] * (nfmside[1] - 1) + 1
    stop = nfmside[1] * nfmside[2]
    return start:stop
end

function top_boundary_node_ids(mesh)
    nfmside = nodes_per_mesh_side(mesh)
    return range(nfmside[2], step = nfmside[2], length = nfmside[1])
end

function left_boundary_node_ids(mesh)
    nfmside = nodes_per_mesh_side(mesh)
    return 1:nfmside[2]
end

function number_of_degrees_of_freedom(mesh::Mesh)
    dim = dimension(mesh)
    numnodes = number_of_nodes(mesh)
    return numnodes * dim
end

function boundary_node_ids(mesh::Mesh)
    nodeids = vcat(
        bottom_boundary_node_ids(mesh),
        right_boundary_node_ids(mesh),
        top_boundary_node_ids(mesh),
        left_boundary_node_ids(mesh),
    )
    return unique!(sort!(nodeids))
end

function is_interior_cell(cellconnectivity)
    numcells = size(cellconnectivity)[2]
    isinteriorcell = [all(cellconnectivity[:, i] .!= 0) for i = 1:numcells]
    return isinteriorcell
end

function is_interior_cell(mesh::Mesh)
    return mesh.isinteriorcell
end

function is_boundary_cell(x)
    return .!is_interior_cell(x)
end


text:
struct GaussianProcess{T,B} <: DifferentiableObjects.DifferentiableObject{3}
    # Σdata::Vector{T}
    Σ::Symmetric{T,BandedMatrix{T,Array{T,2},Base.OneTo{Int}}}
    ∂Σ::Vector{ForwardDiff.Partials{4,T}}
    x::Vector{T}
    y::Vector{T}
    z::Vector{T}
    t::Vector{T}
    ∇::SizedSIMDArray{Tuple{4},T,1,4,4}
    # ∇::Base.RefValue{ForwardDiff.Partials{4,T}}
end

function GaussianProcess(N::Integer, T = Float64, ::Val{B} = Val{15}()) where B
    # L = N * B - (B*(B+1) >> 1)
    M = B + 1
    data = Matrix{T}(undef, M, N)
    # data = Vector{T}(undef, M * N)
    GaussianProcess{T,B}(
        # data,
        # Symmetric(BandedMatrices._BandedMatrix(reshape(data,(M,N)), Base.OneTo(N), 0, B)),
        Symmetric(BandedMatrices._BandedMatrix(data, Base.OneTo(N), 0, B)),
        # Symmetric(BandedMatrix{T}(undef, N, N, 0, B)),
        Vector{ForwardDiff.Partials{4,T}}(undef, (B+1) * N),
        Vector{T}(undef, N), # x
        Vector{T}(undef, N), # y
        Vector{T}(undef, N), # z
        Vector{T}(undef, N), # t
        # Ref(ForwardDiff.Partials{4,$T}((zero(T),zero(T),zero(T),zero(T))))
        SizedSIMDVector{4,T,4,4}(undef)
    )
end
function GaussianProcess(x::AbstractVector{T}, t::AbstractVector{T}, ::Val{B} = Val{15}()) where {B,T}
    N = length(x)
    # L = N * B - (B*(B+1) >> 1)
    M = B + 1
    data = Matrix{T}(undef, M, N)
    # data = Vector{T}(undef, M * N)
    GaussianProcess{T,B}(
        # data,
        # Symmetric(BandedMatrices._BandedMatrix(reshape(data,(M,N)), Base.OneTo(N), 0, B)),
        Symmetric(BandedMatrices._BandedMatrix(data, Base.OneTo(N), 0, B)),
        Vector{ForwardDiff.Partials{4,T}}(undef, M * N),
        x, # x
        Vector{T}(undef, N), # y
        Vector{T}(undef, N), # z
        t, # t
        # Ref(ForwardDiff.Partials{4,$T}((zero(T),zero(T),zero(T),zero(T))))
        SizedSIMDVector{4,T,4,4}(undef)
    )
end

function Base.resize!(gp::GaussianProcess{T,B}, N::Int) where {T,B}
    M = B + 1
    MN = M * N
    # gp.Σdata = Vector{T}(undef, MN)
    # resize!(gp.Σdata, MN)
    # gp.Σ.data.data = reshape(gp.Σdata, (M, N))
    gp.Σ.data.data = Matrix{T}(undef, (M, N))
    gp.Σ.data.raxis = Base.OneTo(N)
    resize!(gp.∂Σ, MN)
    resize!(gp.x,   N)
    resize!(gp.y,   N)
    resize!(gp.z,   N)
    resize!(gp.t,   N)
    gp
end

# logit(x) = log(x/(1-x))
# inv_logit(x) = 1/(1+exp(-x))
@inline function constrain(θ)
    λₑ = exp(θ[1])
    λᵣ = exp(θ[2])
    αᵣ = exp(θ[3])
    ρ  = inv_logit(θ[4])
    λₑ, λᵣ, αᵣ, ρ
end

function logdettest(θ::AbstractVector{T}, t, ::Val{B} = Val(15)) where {B,T}
    Σ = Symmetric(BandedMatrix{T}(undef, N, N, 0, B))
    data = Σ.data.data
    fill_Σ!(data, t, θ, Val(B))
    @show data[13,15]
    @show data[14,15]
    @show data[15,15]
    2chollogdet!(data, Val(B))
end

function (gp::GaussianProcess{T,B})(θ::AbstractVector{T}) where {T,B}
    Σ = gp.Σ.data.data
    fill_Σ!(gp, θ)
    tri_log_det = 2chollogdet!(Σ, Val(B))
    # @show tri_log_det

    copyto!(gp.y, gp.x)
    BandedMatrices.tbsv!('U', 'T', 'N', size(gp.Σ,1), B, Σ, gp.y)

    tri_log_det + (gp.y' * gp.y) + θ[1] + θ[2]
end
@inline DifferentiableObjects.f(gp::GaussianProcess, θ) = gp(θ)
function DifferentiableObjects.fdf(gp::GaussianProcess{T, B}, θ::AbstractVector{T}) where {T, B}
    λₑ = exp(θ[1])
    λᵣ = exp(θ[2])
    αᵣ = exp(θ[3])
    expnθ₃ = exp(-θ[4])
    ρ = 1 / (1 + expnθ₃)
    ∂ρ = ρ^2 * expnθ₃
    fill_Σ!(gp, λₑ, λᵣ, αᵣ, ρ, ∂ρ)

    # @show gp.∂Σ[13,15]
    # @show gp.∂Σ[14,15]
    # @show gp.∂Σ[15,15]
    # ∇fill_Σ!(gp, θ)

    Σ = gp.Σ.data.data
    tri_log_det = 2chollogdetjac!(Σ, gp.∂Σ, Val(B))
    # @show tri_log_det
    gp.∇ .= tri_log_det.partials
    # gp.∇ .= 0

    # BandedMatrices.p,.btrf!('U', size(gp.Σ,1), B, Σ) # Banded Cholesky
    copyto!(gp.y, gp.x)
    BandedMatrices.tbsv!('U', 'T', 'N', size(gp.Σ,1), B, Σ, gp.y)
    copyto!(gp.z, gp.y)
    BandedMatrices.tbsv!('U', 'N', 'N', size(gp.Σ,1), B, Σ, gp.z)

    calc_gradient!(gp)
    gp.∇[1] += 1
    gp.∇[2] += 1
    tri_log_det.value  + (gp.y' * gp.y) + θ[1] + θ[2]
end
function DifferentiableObjects.scale_fdf(gp::GaussianProcess{T}, θ::AbstractVector{T}, scale_target) where T
    fval = DifferentiableObjects.fdf(gp, θ)
    scale = min(one(T), scale_target / norm(gp.∇))
    SIMDArrays.scale!(gp.∇, scale)
    fval * scale, scale
end
function DifferentiableObjects.scaled_fdf(gp::GaussianProcess{T}, θ::AbstractVector{T}, scale) where T
    fval = DifferentiableObjects.fdf(gp, θ)
    SIMDArrays.scale!(gp.∇, scale)
    fval * scale
end

function calc_gradient!(gp::GaussianProcess{T,B}) where {T,B}
    M = B + 1
    ∇₁, ∇₂, ∇₃, ∇₄ = zero(T), zero(T), zero(T), zero(T)
    ∇ = ForwardDiff.Partials((zero(T),zero(T),zero(T),zero(T)))
    y = gp.y; z = gp.z; ∂Σ = gp.∂Σ
    @inbounds @fastmath for col ∈ 1:min(B,size(∂Σ,2))
        n2zᵢ = -2z[col]
        o = col - B - 1
        for row ∈ B+2-col:M
            Λ = n2zᵢ * y[row + o]
            ∂ = ∂Σ[row + (col-1) * M]
            ∇₁ += Λ * ∂[1]
            ∇₂ += Λ * ∂[2]
            ∇₃ += Λ * ∂[3]
            ∇₄ += Λ * ∂[4]
        end
    end
    @inbounds @fastmath for col ∈ B+1:size(∂Σ,2)
        n2zᵢ = -2z[col]
        o = col - B - 1
        for row ∈ 1:M
            Λ = n2zᵢ * y[row + o]
            ∂ = ∂Σ[row + (col-1) * M]
            ∇₁ += Λ * ∂[1]
            ∇₂ += Λ * ∂[2]
            ∇₃ += Λ * ∂[3]
            ∇₄ += Λ * ∂[4]
        end
    end
    @inbounds begin
        gp.∇[1] += ∇₁
        gp.∇[2] += ∇₂
        gp.∇[3] += ∇₃
        gp.∇[4] += ∇₄
    end
    nothing
end
DifferentiableObjects.gradient(gp::GaussianProcess) = gp.∇

function fill_Σ!(gp::GaussianProcess{T,B}, λₑ, λᵣ, αᵣ, ρ) where {B,T}
    Σ = gp.Σ; t = gp.t
    data = Σ.data.data
    Omρ = 1 - ρ
    @inbounds for col ∈ 1:min(B,size(Σ,2))
        o = col - B - 1
        for row ∈ B+2-col:B
            δ = t[col] - t[row + o] # always positive
            δ² = δ^2
            σₑ = exp(-δ  * λₑ)
            σᵣ = (1 + λᵣ * δ²/(2αᵣ))^(-αᵣ)
            data[row,col] = σₑ * ρ + σᵣ * Omρ
        end
        data[B+1,col] = 1
    end
    @inbounds for col ∈ B+1:size(Σ,2)
        o = col - B - 1
        for row ∈ 1:B
            δ = t[col] - t[row + o] # always positive
            δ² = δ^2
            σₑ = exp(-δ  * λₑ)
            σᵣ = (1 + λᵣ * δ²/(2αᵣ))^(-αᵣ)
            data[row,col] = σₑ * ρ + σᵣ * Omρ
        end
        data[B+1,col] = 1
    end
end
function fill_Σ!(gp::GaussianProcess{T,B}, θ) where {T,B}
    fill_Σ!(gp.Σ.data.data, gp.t, θ, Val(B))
    gp.Σ
end
function fill_Σ!(data, t, θ, ::Val{B}) where {T,B}
    λₑ, λᵣ, αᵣ, ρ = constrain(θ)
    Omρ = 1 - ρ
    @inbounds for col ∈ 1:min(B,size(data,2))
        for row ∈ B+2-col:B
            δ = t[col] - t[col + row - B - 1] # always positive
            δ² = δ^2
            σₑ = exp(-δ  * λₑ)
            σᵣ = (1 + λᵣ * δ²/(2αᵣ))^(-αᵣ)
            data[row,col] = σₑ * ρ + σᵣ * Omρ
        end
        data[B+1,col] = 1
    end
    @inbounds for col ∈ B+1:size(data,2)
        for row ∈ 1:B
            δ = t[col] - t[col + row - B - 1] # always positive
            δ² = δ^2
            σₑ = exp(-δ  * λₑ)
            σᵣ = (1 + λᵣ * δ²/(2αᵣ))^(-αᵣ)
            data[row,col] = σₑ * ρ + σᵣ * Omρ
        end
        data[B+1,col] = 1
    end
end

function fill_Σ!(gp::GaussianProcess{T,B}, λₑ, λᵣ, αᵣ, ρ, ∂ρ) where {B,T}
    M = B + 1
    Σ = gp.Σ; ∂Σ = gp.∂Σ; t = gp.t
    data = Σ.data.data
    Omρ = 1 - ρ
    @inbounds for col ∈ 1:min(B,size(Σ,2))
        for row ∈ B+2-col:B
            δ = t[col] - t[col + row - B - 1] # always positive
            δ² = δ^2
            σₑ = exp(-δ  * λₑ)
            α2 = 2αᵣ
            δ²λᵣ  =δ² * λᵣ
            denom = α2 + δ²λᵣ
            frac = α2 / denom
            σᵣ = frac^αᵣ
            data[row,col] = σₑ * ρ + σᵣ * Omρ
            ∂Σ[row + (col-1) * M] = ForwardDiff.Partials{4,T}((
                    σₑ * ρ * -δ * λₑ,
                    T(-0.5) * σᵣ * δ² * frac * λᵣ * Omρ,
                    σᵣ * (δ²λᵣ + denom * log(frac)) / denom * αᵣ * Omρ,
                    ( σₑ - σᵣ ) * ∂ρ
            ))
        end
        data[B+1,col] = 1
    end
    @inbounds for col ∈ M:size(Σ,2)
        for row ∈ 1:B
            δ = t[col] - t[col + row - B - 1] # always positive
            δ² = δ^2
            σₑ = exp(-δ  * λₑ)
            α2 = 2αᵣ
            δ²λᵣ  = δ² * λᵣ
            denom = α2 + δ²λᵣ
            frac = α2 / denom
            σᵣ = frac^αᵣ
            data[row,col] = σₑ * ρ + σᵣ * Omρ
            ∂Σ[row + (col-1) * M] = ForwardDiff.Partials{4,T}((
                    σₑ * ρ * -δ * λₑ,
                    T(-0.5) * σᵣ * δ² * frac * λᵣ * Omρ,
                    σᵣ * (δ²λᵣ + denom * log(frac)) / denom * αᵣ * Omρ,
                    ( σₑ - σᵣ ) * ∂ρ
            ))
        end
        data[B+1,col] = 1
    end
end

@generated function chol!(U::AbstractArray{T,2}, ::Val{P}) where {T,P}
    M = P+1
    q = quote @fastmath begin end end
    qa = q.args[2].args[3].args
    for p ∈ 1:P
        push!(qa, :(@inbounds Uᵢᵢ = U[$(M + (p-1)*M)]))
        for l ∈ 1:p-1
            j = l - p + M
            push!(qa, :( @inbounds Uⱼᵢ = U[$(l-p+M +  (p-1)*M)] ))
            for k ∈ 1:l-1
                push!(qa, :( @inbounds Uⱼᵢ -= U[$(k-p+M + (p-1)*M)] * U[$(k-l+M + (l-1)*M)] ) )
            end
            push!(qa, :(@inbounds Uⱼᵢ /= U[$(M + (l-1)*M)]))
            push!(qa, :(Uᵢᵢ -= Uⱼᵢ * Uⱼᵢ))
            push!(qa, :(@inbounds U[$(j + (p-1)*M)] = Uⱼᵢ))
        end
        push!(qa, :(@inbounds U[$(M + (p-1)*M)] = sqrt(Uᵢᵢ)))
    end
    loop_expr = quote end
    push!(loop_expr.args, :(Uᵢᵢ = U[$M + i*$M]))
    for p ∈ 1:P
        push!(loop_expr.args, :(l = i + $(p - M) ))
        push!(loop_expr.args, :(@inbounds Uⱼᵢ = U[$p + i * $M]))
        for k ∈ 1:p-1
            push!(loop_expr.args, :(@inbounds Uⱼᵢ -= U[$k + i*$M] * U[$(k-p+M) + l * $M]))
        end
        push!(loop_expr.args, :(@inbounds Uⱼᵢ /= U[$M + l * $M]))
        push!(loop_expr.args, :(Uᵢᵢ -= Uⱼᵢ * Uⱼᵢ))
        push!(loop_expr.args, :(@inbounds U[$p + i*$M] = Uⱼᵢ))
    end
    push!(loop_expr.args, :(@inbounds U[$M + i*$M] = sqrt(Uᵢᵢ)))

    push!(qa, quote
        for i ∈ $P:size(U,2)-1
            $loop_expr
        end
    end)
    q

end

@generated function chollogdet!(U::AbstractArray{T,2}, ::Val{P}) where {T,P}
    M = P+1
    fastmath = true
    if fastmath
        q = quote @fastmath begin logdet = zero($T) end end
        qa = q.args[2].args[3].args
    else
        q = quote logdet = zero($T) end
        qa = q.args
    end
    for p ∈ 1:P
        push!(qa, :(@inbounds Uᵢᵢ = U[$(M + (p-1)*M)]))
        for l ∈ 1:p-1
            j = l - p + M
            push!(qa, :( @inbounds Uⱼᵢ = U[$(l-p+M +  (p-1)*M)] ))
            # push!(qa, :( @show Uⱼᵢ ))
            for k ∈ 1:l-1
                push!(qa, :( @inbounds Uⱼᵢ -= U[$(k-p+M + (p-1)*M)] * U[$(k-l+M + (l-1)*M)] ) )
                # push!(qa, :(@show U[$(k-p+M + (p-1)*M)] ))
                # push!(qa, :(@show U[$(k-l+M + (l-1)*M)] ))
            end
            # push!(qa, :( @show Uⱼᵢ ))
            push!(qa, :(@inbounds Uⱼᵢ /= U[$(M + (l-1)*M)]))
            push!(qa, :(Uᵢᵢ -= Uⱼᵢ * Uⱼᵢ))
            push!(qa, :(@inbounds U[$(j + (p-1)*M)] = Uⱼᵢ))
        end
        push!(qa, :(Uᵢᵢ = sqrt(Uᵢᵢ)))
        push!(qa, :(@inbounds U[$(M + (p-1)*M)] = Uᵢᵢ))
        push!(qa, :(logdet += log(Uᵢᵢ)))
    end
    # push!(qa, :(@show logdet))
    loop_expr = quote end
    push!(loop_expr.args, :(Uᵢᵢ = U[$M + i*$M]))
    for p ∈ 1:P
        push!(loop_expr.args, :(l = i + $(p - M) ))
        push!(loop_expr.args, :(@inbounds Uⱼᵢ = U[$p + i * $M]))
        for k ∈ 1:p-1
            push!(loop_expr.args, :(@inbounds Uⱼᵢ -= U[$k + i*$M] * U[$(k-p+M) + l * $M]))
        end
        push!(loop_expr.args, :(@inbounds Uⱼᵢ /= U[$M + l * $M]))
        push!(loop_expr.args, :(Uᵢᵢ -= Uⱼᵢ * Uⱼᵢ))
        push!(loop_expr.args, :(@inbounds U[$p + i*$M] = Uⱼᵢ))
    end
    push!(loop_expr.args, :(Uᵢᵢ = sqrt(Uᵢᵢ)))
    push!(loop_expr.args, :(@inbounds U[$M + i*$M] = Uᵢᵢ))
    push!(loop_expr.args, :(logdet += log(Uᵢᵢ)))

    push!(qa, quote
        for i ∈ $P:size(U,2)-1
            $loop_expr
        end
        logdet
    end)
    q
end

@generated function chollogdetjac!(U::AbstractArray{T,2}, J::AbstractArray{ForwardDiff.Partials{4,T}}, ::Val{P}) where {T,P}
    M = P+1
    D = ForwardDiff.Dual{nothing,T,4}
    fastmath = true
    if fastmath
        q = quote @fastmath begin logdet = zero(ForwardDiff.Dual{nothing,$T,4}) end end
        qa = q.args[2].args[3].args
    else
        q = quote logdet = zero(ForwardDiff.Dual{nothing,$T,4}) end
        qa = q.args
    end
    for p ∈ 1:P
        push!(qa, :( @inbounds Uᵢᵢ = $D(U[$(M + (p-1)*M)]))) # first access
        for l ∈ 1:p-1
            j = l - p + M
            push!(qa, :( @inbounds Uⱼᵢ = $D(U[$(l-p+M +  (p-1)*M)], J[$(l-p+M +  (p-1)*M)] ) ))
            # push!(qa, :( @show Uⱼᵢ ))
            for k ∈ 1:l-1
                push!(qa, :( @inbounds Uⱼᵢ -= $D(U[$(k-p+M + (p-1)*M)], J[$(k-p+M + (p-1)*M)]) *
                                                $D(U[$(k-l+M + (l-1)*M)], J[$(k-l+M + (l-1)*M)]) ) )
                # push!(qa, :(@show $D(U[$(k-p+M + (p-1)*M)], J[$(k-p+M + (p-1)*P)]) ))
                # push!(qa, :(@show $D(U[$(k-l+M + (l-1)*M)], J[$(k-l+M + (l-1)*P)]) ))
            end
            # push!(qa, :( @show Uⱼᵢ ))
            push!(qa, :(@inbounds Uⱼᵢ /= $D(U[$(M + (l-1)*M)], J[$(M + (l-1)*M)])))
            push!(qa, :(Uᵢᵢ -= Uⱼᵢ * Uⱼᵢ))
            push!(qa, :(@inbounds U[$(j + (p-1)*M)] = Uⱼᵢ.value ))
            push!(qa, :(@inbounds J[$(j + (p-1)*M)] = Uⱼᵢ.partials ))
        end
        push!(qa, :(Uᵢᵢ = sqrt(Uᵢᵢ)))
        push!(qa, :(@inbounds U[$(M + (p-1)*M)] = Uᵢᵢ.value ))
        push!(qa, :(@inbounds J[$(M + (p-1)*M)] = Uᵢᵢ.partials ))
        push!(qa, :(logdet += log(Uᵢᵢ)))
    end
    # push!(qa, :(@show logdet))
    loop_expr = quote end
    push!(loop_expr.args, :(Uᵢᵢ = $D(U[$M + i*$M]))) # first access
    for p ∈ 1:P
        push!(loop_expr.args, :(l = i + $(p - M) ))
        push!(loop_expr.args, :(@inbounds Uⱼᵢ = $D(U[$p + i * $M], J[$p + i * $M])))
        for k ∈ 1:p-1
            push!(loop_expr.args, :(@inbounds Uⱼᵢ -= $D(U[$k + i*$M], J[$k + i*$M]) * $D(U[$(k-p+M) + l * $M], J[$(k-p+M) + l * $M])))
        end
        push!(loop_expr.args, :(@inbounds Uⱼᵢ /= $D(U[$M + l * $M], J[$M + l * $M])))
        push!(loop_expr.args, :(Uᵢᵢ -= Uⱼᵢ * Uⱼᵢ))
        push!(loop_expr.args, :(@inbounds U[$p + i*$M] = Uⱼᵢ.value))
        push!(loop_expr.args, :(@inbounds J[$p + i*$M] = Uⱼᵢ.partials))
    end
    push!(loop_expr.args, :(Uᵢᵢ = sqrt(Uᵢᵢ)))
    push!(loop_expr.args, :(@inbounds U[$M + i*$M] = Uᵢᵢ.value))
    push!(loop_expr.args, :(@inbounds J[$M + i*$M] = Uᵢᵢ.partials))
    push!(loop_expr.args, :(logdet += log(Uᵢᵢ)))

    push!(qa, quote
        for i ∈ $P:size(U,2)-1
            $loop_expr
        end
        logdet
    end)
    q
end

struct GPOpt{T,O}
    state::DifferentiableObjects.BFGSState2{4,T,4,16}
    initial_x::SizedSIMDArray{Tuple{4},T,1,4,4}
    ls::DifferentiableObjects.BackTracking2{O,T,Int}
end

function decorrelate_data!(X::AbstractMatrix{T}, gp::GaussianProcess{T}, gp_opt, t) where T
    N, M = size(X)
    resize!(gp, N)
    gp.t .= t;
    for m ∈ 1:M
        gp.x .= @view X[:,m]
        DifferentiableObjects.optimize_scale!(gp_opt.state, gp, gp_opt.initial_x, gp_opt.ls, T(10), 1e-3)
        X[:,m] .= gp.y
    end
end