text:
Base.@kwdef struct BlackBrane_xi1{T} <: InitialData
    a40           :: T   = 1.0
    # guess for the AH position
    AH_pos        :: T   = 1.0
    phi0          :: T   = 0.0
    xi_0          :: T   = 0.0
    xi_Ax         :: T   = 0.0
    xi_nx         :: Int = 1
    xi_Ay         :: T   = 0.0
    xi_ny         :: Int = 1
    xmax          :: T
    xmin          :: T
    ymax          :: T
    ymin          :: T
    ahf           :: AHF = AHF()
end

abstract type ID_ConstantAH  <: InitialData end

Base.@kwdef struct BlackBrane{T} <: ID_ConstantAH
    energy_dens   :: T   = 1.0
    AH_pos        :: T   = 1.0
    phi0          :: T   = 0.0
    ahf           :: AHF = AHF()
end

Base.@kwdef struct BlackBranePert{T} <: ID_ConstantAH
    energy_dens   :: T   = 1.0
    AH_pos        :: T   = 1.0
    phi0          :: T   = 0.0
    oophiM2       :: T   = 0.0
    B1_amp        :: T   = 0.0
    B1_nx         :: Int = 1
    B1_ny         :: Int = 2
    B2_amp        :: T   = 0.0
    B2_nx         :: Int = 1
    B2_ny         :: Int = 2
    G_amp         :: T   = 0.0
    G_nx          :: Int = 1
    G_ny          :: Int = 2
    phi2          :: T   = 0.0
    a4_ampx       :: T   = 0.0
    a4_ampy       :: T   = 0.0
    a4_kx         :: Int = 1
    a4_ky         :: Int = 1
    fx2_ampx      :: T   = 0.0
    fx2_ampy      :: T   = 0.0
    fx2_kx        :: Int = 1
    fx2_ky        :: Int = 1
    fy2_ampx      :: T   = 0.0
    fy2_ampy      :: T   = 0.0
    fy2_kx        :: Int = 1
    fy2_ky        :: Int = 1
    xi0           :: T   = 0.0
    xmax          :: T
    xmin          :: T
    ymax          :: T
    ymin          :: T
    ahf           :: AHF = AHF()
end

Base.@kwdef struct PhiGaussian_u{T} <: ID_ConstantAH
    energy_dens   :: T   = 1.0
    AH_pos        :: T   = 1.0
    phi0          :: T   = 0.0
    phi2          :: T   = 0.0
    oophiM2       :: T   = 0.0
    amp           :: T   = 0.0
    u0            :: T   = 0.0
    sigma         :: T   = 0.1
    ahf           :: AHF = AHF()
end

Base.@kwdef struct QNM_1D{T} <: InitialData
    energy_dens :: T   = 1.0
    phi0        :: T   = 0.0
    phi2        :: T   = 0.0
    oophiM2     :: T   = 0.0
    AH_pos      :: T   = 1.0
    ahf         :: AHF = AHF()
end

function (id::InitialData)(bulkconstrains, bulkevols, bulkderivs, boundary::Boundary,
                           gauge::Gauge, horizoncache::HorizonCache, systems::SystemPartition,
                           evoleq::EvolutionEquations)
    _, Nx, Ny = size(systems[end])
    AH_pos    = id.AH_pos
    xi        = getxi(gauge)

    # function to solve the nested system
    nested = Nested(systems, bulkconstrains)

    init_data!(boundary, systems[1],   id)

    init_data!(gauge,    systems[end], id)
    init_data!(bulkevols, gauge, systems, id)

    # solve nested system for the constrained variables
    nested(bulkevols, boundary, gauge, evoleq)

    # find the Apparent Horizon
    sigma = similar(gauge.xi)
    fill!(sigma, 1/AH_pos)  # initial guess
    find_AH!(sigma, bulkconstrains[end], bulkevols[end], bulkderivs[end], gauge,
             horizoncache, systems[end], id.ahf)

    nothing
end

function (id::ID_ConstantAH)(bulkconstrains, bulkevols, bulkderivs, boundary::Boundary,
                           gauge::Gauge, horizoncache::HorizonCache, systems::SystemPartition,
                           evoleq::EvolutionEquations)
    _, Nx, Ny = size(systems[end])
    AH_pos    = id.AH_pos
    xi        = getxi(gauge)

    # function to solve the nested system
    nested = Nested(systems, bulkconstrains)

    init_data!(boundary, systems[1],   id)

    init_data!(gauge,    systems[end], id)
    init_data!(bulkevols, gauge, systems, id)

    # solve nested system for the constrained variables
    nested(bulkevols, boundary, gauge, evoleq)

    # find the Apparent Horizon
    sigma = similar(gauge.xi)
    fill!(sigma, 1/AH_pos)  # initial guess
    find_AH!(sigma, bulkconstrains[end], bulkevols[end], bulkderivs[end], gauge,
             horizoncache, systems[end], id.ahf)

    # assuming that the AH has been found, we now update xi and the bulk variables
    for j in 1:Ny
        for i in 1:Nx
            xi[1,i,j] += -1 / AH_pos + sigma[1,i,j]
        end
    end

    init_data!(bulkevols, gauge, systems, id)

    # solve nested system for the constrained variables
    nested(bulkevols, boundary, gauge, evoleq)

    # AH should now be at u = AH_pos

    nothing
end

function init_data!(bulkevols, gauge::Gauge, systems::SystemPartition,
                    id::InitialData)
    # the Ref() makes its argument a scalar with respect to broadcast
    init_data!.(bulkevols, Ref(gauge), systems, Ref(id))
end

function init_data!(bulk::BulkEvolved, gauge::Gauge, sys::System{Inner},
                    id::InitialData)
    Nu, Nx, Ny = size(sys)
    xx = sys.xcoord
    yy = sys.ycoord
    uu = sys.ucoord

    B1  = getB1(bulk)
    B2  = getB2(bulk)
    G   = getG(bulk)
    phi = getphi(bulk)
    xi  = getxi(gauge)

    phi0 = id.phi0

    for j in 1:Ny
        for i in 1:Nx
            for a in 1:Nu
                u       = uu[a]
                x       = xx[i]
                y       = yy[j]
                xi_ij   = xi[1,i,j]
                aux     = 1 + xi_ij * u
                aux3    = aux * aux * aux
                aux4    = aux * aux3
                u_old   = u / aux
                B1_old  = analytic_B1(u_old, x, y, id)
                B2_old  = analytic_B2(u_old, x, y, id)
                G_old   = analytic_G(u_old, x, y, id)

                B1[a,i,j]  = B1_old / aux4
                B2[a,i,j]  = B2_old / aux4
                G[a,i,j]   = G_old  / aux4
            end
        end
    end

    # if phi0 = 0 set phi to zero
    if abs(phi0) < 1e-9
        fill!(phi, 0)
    else
        for j in 1:Ny
            for i in 1:Nx
                for a in 1:Nu
                    u       = uu[a]
                    x       = xx[i]
                    y       = yy[j]
                    xi_ij   = xi[1,i,j]
                    aux     = 1 + xi_ij * u
                    aux3    = aux * aux * aux
                    aux4    = aux * aux3
                    u_old   = u / aux
                    phi_old = analytic_phi(u_old, x, y, id)

                    phi[a,i,j] = xi_ij * xi_ij / (phi0 * phi0 * aux) +
                        phi_old / aux3
                end
            end
        end
    end

    bulk
end

function init_data!(bulk::BulkEvolved, gauge::Gauge, sys::System{Outer},
                    id::InitialData)
    Nu, Nx, Ny = size(sys)
    xx = sys.xcoord
    yy = sys.ycoord
    uu = sys.ucoord

    B1  = getB1(bulk)
    B2  = getB2(bulk)
    G   = getG(bulk)
    phi = getphi(bulk)
    xi  = getxi(gauge)

    phi0 = id.phi0

    for j in 1:Ny
        for i in 1:Nx
            for a in 1:Nu
                u         = uu[a]
                x         = xx[i]
                y         = yy[j]
                xi_ij     = xi[1,i,j]
                aux       = 1 + xi_ij * u
                aux3      = aux * aux * aux
                aux4      = aux * aux3
                u_old     = u / aux
                B1_old    = analytic_B1(u_old, x, y, id)
                B2_old    = analytic_B2(u_old, x, y, id)
                G_old     = analytic_G(u_old, x, y, id)
                B1_inner  = B1_old / aux4
                B2_inner  = B2_old / aux4
                G_inner   = G_old  / aux4

                B1[a,i,j]  = u^4 * B1_inner
                B2[a,i,j]  = u^4 * B2_inner
                G[a,i,j]   = u^4 * G_inner
            end
        end
    end

    # if phi0 = 0 set phi to zero
    if abs(phi0) < 1e-9
        fill!(phi, 0)
    else
        for j in 1:Ny
            for i in 1:Nx
                for a in 1:Nu
                    u         = uu[a]
                    x         = xx[i]
                    y         = yy[j]
                    xi_ij     = xi[1,i,j]
                    aux       = 1 + xi_ij * u
                    aux3      = aux * aux * aux
                    aux4      = aux * aux3
                    u_old     = u / aux
                    phi_old   = analytic_phi(u_old, x, y, id)
                    phi_inner = xi_ij * xi_ij / (phi0 * phi0 * aux) +
                        phi_old / aux3

                    phi[a,i,j] = u * phi0 - u^2 * phi0 * xi_ij + u^3 * phi0^3 * phi_inner
                end
            end
        end
    end

    bulk
end

# BlackBrane_xi1

analytic_B1(u, x, y, id::BlackBrane_xi1)  = 0
analytic_B2(u, x, y, id::BlackBrane_xi1)  = 0
analytic_G(u, x, y, id::BlackBrane_xi1)   = 0
analytic_phi(u, x, y, id::BlackBrane_xi1) = 0

function init_data!(ff::Boundary, sys::System, id::BlackBrane_xi1)
    a40 = id.a40

    a4  = geta4(ff)
    fx2 = getfx2(ff)
    fy2 = getfy2(ff)

    fill!(a4, a40)
    fill!(fx2, 0)
    fill!(fy2, 0)

    ff
end

function init_data!(ff::Gauge, sys::System, id::BlackBrane_xi1)
    _, Nx, Ny = size(sys)
    xx = sys.xcoord
    yy = sys.ycoord
    xi  = getxi(ff)

    xmax  = id.xmax
    xmin  = id.xmin
    ymax  = id.ymax
    ymin  = id.ymin

    for j in 1:Ny
        for i in 1:Nx
            x         = xx[i]
            y         = yy[j]

            xi[1,i,j] = id.xi_0 +
                id.xi_Ax * sin( 2 * π * id.xi_nx * (xmax-x)/(xmax-xmin) ) +
                id.xi_Ay * sin( 2 * π * id.xi_ny * (ymax-y)/(ymax-ymin) )
        end
    end

    ff
end

# BlackBrane initial data

analytic_B1(u, x, y, id::BlackBrane)  = 0
analytic_B2(u, x, y, id::BlackBrane)  = 0
analytic_G(u, x, y, id::BlackBrane)   = 0
analytic_phi(u, x, y, id::BlackBrane) = 0

function init_data!(ff::Boundary, sys::System, id::BlackBrane)
    a40 = -id.energy_dens/0.75

    a4  = geta4(ff)
    fx2 = getfx2(ff)
    fy2 = getfy2(ff)

    fill!(a4, a40)
    fill!(fx2, 0)
    fill!(fy2, 0)

    ff
end

function init_data!(ff::Gauge, sys::System, id::BlackBrane)
    a40     = -id.energy_dens/0.75
    AH_pos  = id.AH_pos
    xi0     = (-a40)^0.25 - 1/AH_pos

    xi  = getxi(ff)

    fill!(xi, xi0)

    ff
end

# BlackBranePert initial data

analytic_phi(u, x, y, id::BlackBranePert) = id.phi2 / id.phi0^3

function analytic_B1(u, x, y, id::BlackBranePert)
    # add the perturbation on B1
    pert_amp = id.B1_amp
    xmax     = id.xmax
    xmin     = id.xmin
    ymax     = id.ymax
    ymin     = id.ymin
    # number of maxima in each direction
    nx       = id.B1_nx
    ny       = id.B1_ny

    pert_amp * sin( 2 * π * nx * (xmax-x)/(xmax-xmin) ) *
        sin( -2 * π * ny * (ymax-y)/(ymax-ymin) )
end

function analytic_B2(u, x, y, id::BlackBranePert)
    # add the perturbation on B2
    pert_amp = id.B2_amp
    xmax     = id.xmax
    xmin     = id.xmin
    ymax     = id.ymax
    ymin     = id.ymin
    # number of maxima in each direction
    nx       = id.B2_nx
    ny       = id.B2_ny

    pert_amp * sin( 2 * π * nx * (xmax-x)/(xmax-xmin) ) *
        sin( -2 * π * ny * (ymax-y)/(ymax-ymin) )
end

function analytic_G(u, x, y, id::BlackBranePert)
    # add the perturbation on G
    pert_amp = id.G_amp
    xmax     = id.xmax
    xmin     = id.xmin
    ymax     = id.ymax
    ymin     = id.ymin
    # number of maxima in each direction
    nx       = id.G_nx
    ny       = id.G_ny

    pert_amp * sin( 2 * π * nx * (xmax-x)/(xmax-xmin) ) *
        sin( -2 * π * ny * (ymax-y)/(ymax-ymin) )
end

function init_data!(ff::Boundary, sys::System{Inner}, id::BlackBranePert)
    epsilon = id.energy_dens
    phi0    = id.phi0
    phi2    = id.phi2
    oophiM2 = id.oophiM2

    # a4 perturbation amplitude
    ampx     = id.a4_ampx
    ampy     = id.a4_ampy
    fx2_ampx = id.fx2_ampx
    fx2_ampy = id.fx2_ampy
    fy2_ampx = id.fy2_ampx
    fy2_ampy = id.fy2_ampy
    # number of maxima
    kx     = id.a4_kx
    ky     = id.a4_ky
    fx2_kx = id.fx2_kx
    fx2_ky = id.fx2_ky
    fy2_kx = id.fy2_kx
    fy2_ky = id.fy2_ky

    xmax = id.xmax
    xmin = id.xmin
    xmid = (xmax + xmin) / 2
    ymax = id.ymax
    ymin = id.ymin
    ymid = (ymax + ymin) / 2

    _, Nx, Ny = size(sys)
    xx = sys.xcoord
    yy = sys.ycoord

    phi04 = phi0 * phi0 * phi0 * phi0
    a40   = (-epsilon - phi0 * phi2 - phi04 * oophiM2 / 4 + 7 * phi04 / 36) / 0.75

    a4  = geta4(ff)
    fx2 = getfx2(ff)
    fy2 = getfy2(ff)

    fill!(a4, a40)
    fill!(fx2, 0)
    fill!(fy2, 0)

    for j in 1:Ny
        for i in 1:Nx
            x = xx[i]
            y = yy[j]
            a4[1,i,j]  += -a40 * ( ampx * cos(2 * π * kx * (x-xmid)/(xmax-xmin)) +
                                   ampy * cos(2 * π * ky * (y-ymid)/(ymax-ymin)) )

            fx2[1,i,j] += fx2_ampx * cos(2 * π * fx2_kx * (x-xmid)/(xmax-xmin)) +
                           fx2_ampy * cos(2 * π * fx2_ky * (y-ymid)/(ymax-ymin))

            fy2[1,i,j] += fy2_ampx * cos(2 * π * fy2_kx * (x-xmid)/(xmax-xmin)) +
                          fy2_ampy * cos(2 * π * fy2_ky * (y-ymid)/(ymax-ymin))
        end
    end

    ff
end

function init_data!(ff::Gauge, sys::System, id::BlackBranePert)
    a40     = -id.energy_dens/0.75
    AH_pos  = id.AH_pos

    # TODO: this guess works best for the conformal case. is there a better one?
    if id.xi0 == 0
        xi0 = (-a40)^0.25 - 1/AH_pos
    else
        xi0 = id.xi0
    end

    xi  = getxi(ff)

    fill!(xi, xi0)

    ff
end

# PhiGaussian_u initial data

function analytic_phi(u, x, y, id::PhiGaussian_u)
    phi0   = id.phi0
    phi2   = id.phi2
    amp    = id.amp
    sigma  = id.sigma
    u0     = id.u0

    phi03  = phi0 * phi0 * phi0
    sigma2 = sigma * sigma

    myfunc = amp * exp( -(u-u0)*(u-u0) / (2*sigma2) )

    (phi2 + u * myfunc) / phi03
end

analytic_B1(u, x, y, id::PhiGaussian_u) = 0
analytic_B2(u, x, y, id::PhiGaussian_u) = 0
analytic_G(u, x, y, id::PhiGaussian_u)  = 0

function init_data!(ff::Boundary, sys::System, id::PhiGaussian_u)
    a4  = geta4(ff)
    fx2 = getfx2(ff)
    fy2 = getfy2(ff)

    epsilon = id.energy_dens
    phi0    = id.phi0
    phi2    = id.phi2
    oophiM2 = id.oophiM2
    phi04   = phi0 * phi0 * phi0 * phi0

    a40 = (-epsilon - phi0 * phi2 - phi04 * oophiM2 / 4 + 7 * phi04 / 36) / 0.75

    fill!(a4, a40)
    fill!(fx2, 0)
    fill!(fy2, 0)

    ff
end

function init_data!(ff::Gauge, sys::System, id::PhiGaussian_u)
    epsilon = id.energy_dens
    phi0    = id.phi0
    phi2    = id.phi2
    AH_pos  = id.AH_pos
    oophiM2 = id.oophiM2
    phi04   = phi0 * phi0 * phi0 * phi0

    a40 = (-epsilon - phi0 * phi2 - phi04 * oophiM2 / 4 + 7 * phi04 / 36) / 0.75

    # TODO: this guess works best for the conformal case. is there a better one?
    xi0 = (-a40)^0.25 - 1/AH_pos

    xi  = getxi(ff)

    fill!(xi, xi0)

    ff
end

#QNM in 1D initial data
analytic_B1(u, x, y, id::QNM_1D)  = 3/2*0.1*u^8
analytic_B2(u, x, y, id::QNM_1D)  = 1/2*0.1*u^8
analytic_G(u, x, y, id::QNM_1D)   = 0
analytic_phi(u, x, y, id::QNM_1D) = id.phi2/id.phi0^3

function init_data!(ff::Boundary, sys::System, id::QNM_1D)
    a4  = geta4(ff)
    fx2 = getfx2(ff)
    fy2 = getfy2(ff)

    epsilon = id.energy_dens
    phi0    = id.phi0
    phi2    = id.phi2
    oophiM2 = id.oophiM2
    phi04   = phi0 * phi0 * phi0 * phi0

    a40 = (-epsilon - phi0 * phi2 - phi04 * oophiM2 / 4 + 7 * phi04 / 36) / 0.75

    fill!(a4, a40)
    fill!(fx2, 0)
    fill!(fy2, 0)

    ff
end

function init_data!(ff::Gauge, sys::System, id::QNM_1D)
    epsilon = id.energy_dens
    phi0    = id.phi0
    phi2    = id.phi2
    AH_pos  = id.AH_pos
    oophiM2 = id.oophiM2
    phi04   = phi0 * phi0 * phi0 * phi0

    a40 = (-epsilon - phi0 * phi2 - phi04 * oophiM2 / 4 + 7 * phi04 / 36) / 0.75

    xi0 = 0

    xi  = getxi(ff)

    fill!(xi, xi0)

    ff
end


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: appsync
using AWS.Compat
using AWS.UUIDs
"""
    CreateApiCache()

Creates a cache for the GraphQL API.

# Required Parameters
- `apiCachingBehavior`: Caching behavior.    FULL_REQUEST_CACHING: All requests are fully cached.    PER_RESOLVER_CACHING: Individual resolvers that you specify are cached.
- `apiId`: The GraphQL API Id.
- `ttl`: TTL in seconds for cache entries. Valid values are between 1 and 3600 seconds.
- `type`: The cache instance type. Valid values are     SMALL     MEDIUM     LARGE     XLARGE     LARGE_2X     LARGE_4X     LARGE_8X (not available in all regions)    LARGE_12X    Historically, instance types were identified by an EC2-style value. As of July 2020, this is deprecated, and the generic identifiers above should be used. The following legacy instance types are available, but their use is discouraged:    T2_SMALL: A t2.small instance type.    T2_MEDIUM: A t2.medium instance type.    R4_LARGE: A r4.large instance type.    R4_XLARGE: A r4.xlarge instance type.    R4_2XLARGE: A r4.2xlarge instance type.    R4_4XLARGE: A r4.4xlarge instance type.    R4_8XLARGE: A r4.8xlarge instance type.

# Optional Parameters
- `atRestEncryptionEnabled`: At rest encryption flag for cache. This setting cannot be updated after creation.
- `transitEncryptionEnabled`: Transit encryption flag when connecting to cache. This setting cannot be updated after creation.
"""

create_api_cache(apiCachingBehavior, apiId, ttl, type; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches", Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type); aws_config=aws_config)
create_api_cache(apiCachingBehavior, apiId, ttl, type, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type), args)); aws_config=aws_config)

"""
    CreateApiKey()

Creates a unique key that you can distribute to clients who are executing your API.

# Required Parameters
- `apiId`: The ID for your GraphQL API.

# Optional Parameters
- `description`: A description of the purpose of the API key.
- `expires`: The time from creation time after which the API key expires. The date is represented as seconds since the epoch, rounded down to the nearest hour. The default value for this parameter is 7 days from creation time. For more information, see .
"""

create_api_key(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys"; aws_config=aws_config)
create_api_key(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys", args; aws_config=aws_config)

"""
    CreateDataSource()

Creates a DataSource object.

# Required Parameters
- `apiId`: The API ID for the GraphQL API for the DataSource.
- `name`: A user-supplied name for the DataSource.
- `type`: The type of the DataSource.

# Optional Parameters
- `description`: A description of the DataSource.
- `dynamodbConfig`: Amazon DynamoDB settings.
- `elasticsearchConfig`: Amazon Elasticsearch Service settings.
- `httpConfig`: HTTP endpoint settings.
- `lambdaConfig`: AWS Lambda settings.
- `relationalDatabaseConfig`: Relational database settings.
- `serviceRoleArn`: The AWS IAM service role ARN for the data source. The system assumes this role when accessing the data source.
"""

create_data_source(apiId, name, type; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources", Dict{String, Any}("name"=>name, "type"=>type); aws_config=aws_config)
create_data_source(apiId, name, type, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name, "type"=>type), args)); aws_config=aws_config)

"""
    CreateFunction()

Creates a Function object. A function is a reusable entity. Multiple functions can be used to compose the resolver logic.

# Required Parameters
- `apiId`: The GraphQL API ID.
- `dataSourceName`: The Function DataSource name.
- `functionVersion`: The version of the request mapping template. Currently the supported value is 2018-05-29.
- `name`: The Function name. The function name does not have to be unique.

# Optional Parameters
- `description`: The Function description.
- `requestMappingTemplate`: The Function request mapping template. Functions support only the 2018-05-29 version of the request mapping template.
- `responseMappingTemplate`: The Function response mapping template.
"""

create_function(apiId, dataSourceName, functionVersion, name; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions", Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name); aws_config=aws_config)
create_function(apiId, dataSourceName, functionVersion, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name), args)); aws_config=aws_config)

"""
    CreateGraphqlApi()

Creates a GraphqlApi object.

# Required Parameters
- `authenticationType`: The authentication type: API key, AWS IAM, OIDC, or Amazon Cognito user pools.
- `name`: A user-supplied name for the GraphqlApi.

# Optional Parameters
- `additionalAuthenticationProviders`: A list of additional authentication providers for the GraphqlApi API.
- `logConfig`: The Amazon CloudWatch Logs configuration.
- `openIDConnectConfig`: The OpenID Connect configuration.
- `tags`: A TagMap object.
- `userPoolConfig`: The Amazon Cognito user pool configuration.
- `xrayEnabled`: A flag indicating whether to enable X-Ray tracing for the GraphqlApi.
"""

create_graphql_api(authenticationType, name; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis", Dict{String, Any}("authenticationType"=>authenticationType, "name"=>name); aws_config=aws_config)
create_graphql_api(authenticationType, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("authenticationType"=>authenticationType, "name"=>name), args)); aws_config=aws_config)

"""
    CreateResolver()

Creates a Resolver object. A resolver converts incoming requests into a format that a data source can understand and converts the data source's responses into GraphQL.

# Required Parameters
- `apiId`: The ID for the GraphQL API for which the resolver is being created.
- `fieldName`: The name of the field to attach the resolver to.
- `typeName`: The name of the Type.

# Optional Parameters
- `cachingConfig`: The caching configuration for the resolver.
- `dataSourceName`: The name of the data source for which the resolver is being created.
- `kind`: The resolver type.    UNIT: A UNIT resolver type. A UNIT resolver is the default resolver type. A UNIT resolver enables you to execute a GraphQL query against a single data source.    PIPELINE: A PIPELINE resolver type. A PIPELINE resolver enables you to execute a series of Function in a serial manner. You can use a pipeline resolver to execute a GraphQL query against multiple data sources.
- `pipelineConfig`: The PipelineConfig.
- `requestMappingTemplate`: The mapping template to be used for requests. A resolver uses a request mapping template to convert a GraphQL expression into a format that a data source can understand. Mapping templates are written in Apache Velocity Template Language (VTL). VTL request mapping templates are optional when using a Lambda data source. For all other data sources, VTL request and response mapping templates are required.
- `responseMappingTemplate`: The mapping template to be used for responses from the data source.
- `syncConfig`: The SyncConfig for a resolver attached to a versioned datasource.
"""

create_resolver(apiId, fieldName, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers", Dict{String, Any}("fieldName"=>fieldName); aws_config=aws_config)
create_resolver(apiId, fieldName, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("fieldName"=>fieldName), args)); aws_config=aws_config)

"""
    CreateType()

Creates a Type object.

# Required Parameters
- `apiId`: The API ID.
- `definition`: The type definition, in GraphQL Schema Definition Language (SDL) format. For more information, see the GraphQL SDL documentation.
- `format`: The type format: SDL or JSON.

"""

create_type(apiId, definition, format; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types", Dict{String, Any}("definition"=>definition, "format"=>format); aws_config=aws_config)
create_type(apiId, definition, format, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("definition"=>definition, "format"=>format), args)); aws_config=aws_config)

"""
    DeleteApiCache()

Deletes an ApiCache object.

# Required Parameters
- `apiId`: The API ID.

"""

delete_api_cache(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/ApiCaches"; aws_config=aws_config)
delete_api_cache(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/ApiCaches", args; aws_config=aws_config)

"""
    DeleteApiKey()

Deletes an API key.

# Required Parameters
- `apiId`: The API ID.
- `id`: The ID for the API key.

"""

delete_api_key(apiId, id; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/apikeys/$(id)"; aws_config=aws_config)
delete_api_key(apiId, id, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/apikeys/$(id)", args; aws_config=aws_config)

"""
    DeleteDataSource()

Deletes a DataSource object.

# Required Parameters
- `apiId`: The API ID.
- `name`: The name of the data source.

"""

delete_data_source(apiId, name; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/datasources/$(name)"; aws_config=aws_config)
delete_data_source(apiId, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/datasources/$(name)", args; aws_config=aws_config)

"""
    DeleteFunction()

Deletes a Function.

# Required Parameters
- `apiId`: The GraphQL API ID.
- `functionId`: The Function ID.

"""

delete_function(apiId, functionId; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/functions/$(functionId)"; aws_config=aws_config)
delete_function(apiId, functionId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/functions/$(functionId)", args; aws_config=aws_config)

"""
    DeleteGraphqlApi()

Deletes a GraphqlApi object.

# Required Parameters
- `apiId`: The API ID.

"""

delete_graphql_api(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)"; aws_config=aws_config)
delete_graphql_api(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)", args; aws_config=aws_config)

"""
    DeleteResolver()

Deletes a Resolver object.

# Required Parameters
- `apiId`: The API ID.
- `fieldName`: The resolver field name.
- `typeName`: The name of the resolver type.

"""

delete_resolver(apiId, fieldName, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)"; aws_config=aws_config)
delete_resolver(apiId, fieldName, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)", args; aws_config=aws_config)

"""
    DeleteType()

Deletes a Type object.

# Required Parameters
- `apiId`: The API ID.
- `typeName`: The type name.

"""

delete_type(apiId, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)"; aws_config=aws_config)
delete_type(apiId, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)", args; aws_config=aws_config)

"""
    FlushApiCache()

Flushes an ApiCache object.

# Required Parameters
- `apiId`: The API ID.

"""

flush_api_cache(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/FlushCache"; aws_config=aws_config)
flush_api_cache(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/FlushCache", args; aws_config=aws_config)

"""
    GetApiCache()

Retrieves an ApiCache object.

# Required Parameters
- `apiId`: The API ID.

"""

get_api_cache(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/ApiCaches"; aws_config=aws_config)
get_api_cache(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/ApiCaches", args; aws_config=aws_config)

"""
    GetDataSource()

Retrieves a DataSource object.

# Required Parameters
- `apiId`: The API ID.
- `name`: The name of the data source.

"""

get_data_source(apiId, name; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources/$(name)"; aws_config=aws_config)
get_data_source(apiId, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources/$(name)", args; aws_config=aws_config)

"""
    GetFunction()

Get a Function.

# Required Parameters
- `apiId`: The GraphQL API ID.
- `functionId`: The Function ID.

"""

get_function(apiId, functionId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)"; aws_config=aws_config)
get_function(apiId, functionId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)", args; aws_config=aws_config)

"""
    GetGraphqlApi()

Retrieves a GraphqlApi object.

# Required Parameters
- `apiId`: The API ID for the GraphQL API.

"""

get_graphql_api(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)"; aws_config=aws_config)
get_graphql_api(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)", args; aws_config=aws_config)

"""
    GetIntrospectionSchema()

Retrieves the introspection schema for a GraphQL API.

# Required Parameters
- `apiId`: The API ID.
- `format`: The schema format: SDL or JSON.

# Optional Parameters
- `includeDirectives`: A flag that specifies whether the schema introspection should contain directives.
"""

get_introspection_schema(apiId, format; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schema", Dict{String, Any}("format"=>format); aws_config=aws_config)
get_introspection_schema(apiId, format, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schema", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), args)); aws_config=aws_config)

"""
    GetResolver()

Retrieves a Resolver object.

# Required Parameters
- `apiId`: The API ID.
- `fieldName`: The resolver field name.
- `typeName`: The resolver type name.

"""

get_resolver(apiId, fieldName, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)"; aws_config=aws_config)
get_resolver(apiId, fieldName, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)", args; aws_config=aws_config)

"""
    GetSchemaCreationStatus()

Retrieves the current status of a schema creation operation.

# Required Parameters
- `apiId`: The API ID.

"""

get_schema_creation_status(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schemacreation"; aws_config=aws_config)
get_schema_creation_status(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schemacreation", args; aws_config=aws_config)

"""
    GetType()

Retrieves a Type object.

# Required Parameters
- `apiId`: The API ID.
- `format`: The type format: SDL or JSON.
- `typeName`: The type name.

"""

get_type(apiId, format, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}("format"=>format); aws_config=aws_config)
get_type(apiId, format, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), args)); aws_config=aws_config)

"""
    ListApiKeys()

Lists the API keys for a given API.  API keys are deleted automatically 60 days after they expire. However, they may still be included in the response until they have actually been deleted. You can safely call DeleteApiKey to manually delete a key before it's automatically deleted.

# Required Parameters
- `apiId`: The API ID.

# Optional Parameters
- `maxResults`: The maximum number of results you want the request to return.
- `nextToken`: An identifier that was returned from the previous call to this operation, which can be used to return the next set of items in the list.
"""

list_api_keys(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/apikeys"; aws_config=aws_config)
list_api_keys(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/apikeys", args; aws_config=aws_config)

"""
    ListDataSources()

Lists the data sources for a given API.

# Required Parameters
- `apiId`: The API ID.

# Optional Parameters
- `maxResults`: The maximum number of results you want the request to return.
- `nextToken`: An identifier that was returned from the previous call to this operation, which can be used to return the next set of items in the list.
"""

list_data_sources(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources"; aws_config=aws_config)
list_data_sources(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources", args; aws_config=aws_config)

"""
    ListFunctions()

List multiple functions.

# Required Parameters
- `apiId`: The GraphQL API ID.

# Optional Parameters
- `maxResults`: The maximum number of results you want the request to return.
- `nextToken`: An identifier that was returned from the previous call to this operation, which can be used to return the next set of items in the list.
"""

list_functions(apiId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions"; aws_config=aws_config)
list_functions(apiId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions", args; aws_config=aws_config)

"""
    ListGraphqlApis()

Lists your GraphQL APIs.

# Optional Parameters
- `maxResults`: The maximum number of results you want the request to return.
- `nextToken`: An identifier that was returned from the previous call to this operation, which can be used to return the next set of items in the list.
"""

list_graphql_apis(; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis"; aws_config=aws_config)
list_graphql_apis(args::AbstractDict{String, Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis", args; aws_config=aws_config)

"""
    ListResolvers()

Lists the resolvers for a given API and type.

# Required Parameters
- `apiId`: The API ID.
- `typeName`: The type name.

# Optional Parameters
- `maxResults`: The maximum number of results you want the request to return.
- `nextToken`: An identifier that was returned from the previous call to this operation, which can be used to return the next set of items in the list.
"""

list_resolvers(apiId, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers"; aws_config=aws_config)
list_resolvers(apiId, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers", args; aws_config=aws_config)

"""
    ListResolversByFunction()

List the resolvers that are associated with a specific function.

# Required Parameters
- `apiId`: The API ID.
- `functionId`: The Function ID.

# Optional Parameters
- `maxResults`: The maximum number of results you want the request to return.
- `nextToken`: An identifier that was returned from the previous call to this operation, which you can use to return the next set of items in the list.
"""

list_resolvers_by_function(apiId, functionId; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)/resolvers"; aws_config=aws_config)
list_resolvers_by_function(apiId, functionId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)/resolvers", args; aws_config=aws_config)

"""
    ListTagsForResource()

Lists the tags for a resource.

# Required Parameters
- `resourceArn`: The GraphqlApi ARN.

"""

list_tags_for_resource(resourceArn; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/tags/$(resourceArn)"; aws_config=aws_config)
list_tags_for_resource(resourceArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/tags/$(resourceArn)", args; aws_config=aws_config)

"""
    ListTypes()

Lists the types for a given API.

# Required Parameters
- `apiId`: The API ID.
- `format`: The type format: SDL or JSON.

# Optional Parameters
- `maxResults`: The maximum number of results you want the request to return.
- `nextToken`: An identifier that was returned from the previous call to this operation, which can be used to return the next set of items in the list.
"""

list_types(apiId, format; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types", Dict{String, Any}("format"=>format); aws_config=aws_config)
list_types(apiId, format, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), args)); aws_config=aws_config)

"""
    StartSchemaCreation()

Adds a new schema to your GraphQL API. This operation is asynchronous. Use to determine when it has completed.

# Required Parameters
- `apiId`: The API ID.
- `definition`: The schema definition, in GraphQL schema language format.

"""

start_schema_creation(apiId, definition; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/schemacreation", Dict{String, Any}("definition"=>definition); aws_config=aws_config)
start_schema_creation(apiId, definition, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/schemacreation", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("definition"=>definition), args)); aws_config=aws_config)

"""
    TagResource()

Tags a resource with user-supplied tags.

# Required Parameters
- `resourceArn`: The GraphqlApi ARN.
- `tags`: A TagMap object.

"""

tag_resource(resourceArn, tags; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/tags/$(resourceArn)", Dict{String, Any}("tags"=>tags); aws_config=aws_config)
tag_resource(resourceArn, tags, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/tags/$(resourceArn)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("tags"=>tags), args)); aws_config=aws_config)

"""
    UntagResource()

Untags a resource.

# Required Parameters
- `resourceArn`: The GraphqlApi ARN.
- `tagKeys`: A list of TagKey objects.

"""

untag_resource(resourceArn, tagKeys; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/tags/$(resourceArn)", Dict{String, Any}("tagKeys"=>tagKeys); aws_config=aws_config)
untag_resource(resourceArn, tagKeys, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("DELETE", "/v1/tags/$(resourceArn)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("tagKeys"=>tagKeys), args)); aws_config=aws_config)

"""
    UpdateApiCache()

Updates the cache for the GraphQL API.

# Required Parameters
- `apiCachingBehavior`: Caching behavior.    FULL_REQUEST_CACHING: All requests are fully cached.    PER_RESOLVER_CACHING: Individual resolvers that you specify are cached.
- `apiId`: The GraphQL API Id.
- `ttl`: TTL in seconds for cache entries. Valid values are between 1 and 3600 seconds.
- `type`: The cache instance type. Valid values are     SMALL     MEDIUM     LARGE     XLARGE     LARGE_2X     LARGE_4X     LARGE_8X (not available in all regions)    LARGE_12X    Historically, instance types were identified by an EC2-style value. As of July 2020, this is deprecated, and the generic identifiers above should be used. The following legacy instance types are available, but their use is discouraged:    T2_SMALL: A t2.small instance type.    T2_MEDIUM: A t2.medium instance type.    R4_LARGE: A r4.large instance type.    R4_XLARGE: A r4.xlarge instance type.    R4_2XLARGE: A r4.2xlarge instance type.    R4_4XLARGE: A r4.4xlarge instance type.    R4_8XLARGE: A r4.8xlarge instance type.

"""

update_api_cache(apiCachingBehavior, apiId, ttl, type; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches/update", Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type); aws_config=aws_config)
update_api_cache(apiCachingBehavior, apiId, ttl, type, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches/update", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type), args)); aws_config=aws_config)

"""
    UpdateApiKey()

Updates an API key. The key can be updated while it is not deleted.

# Required Parameters
- `apiId`: The ID for the GraphQL API.
- `id`: The API key ID.

# Optional Parameters
- `description`: A description of the purpose of the API key.
- `expires`: The time from update time after which the API key expires. The date is represented as seconds since the epoch. For more information, see .
"""

update_api_key(apiId, id; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys/$(id)"; aws_config=aws_config)
update_api_key(apiId, id, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys/$(id)", args; aws_config=aws_config)

"""
    UpdateDataSource()

Updates a DataSource object.

# Required Parameters
- `apiId`: The API ID.
- `name`: The new name for the data source.
- `type`: The new data source type.

# Optional Parameters
- `description`: The new description for the data source.
- `dynamodbConfig`: The new Amazon DynamoDB configuration.
- `elasticsearchConfig`: The new Elasticsearch Service configuration.
- `httpConfig`: The new HTTP endpoint configuration.
- `lambdaConfig`: The new AWS Lambda configuration.
- `relationalDatabaseConfig`: The new relational database configuration.
- `serviceRoleArn`: The new service role ARN for the data source.
"""

update_data_source(apiId, name, type; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources/$(name)", Dict{String, Any}("type"=>type); aws_config=aws_config)
update_data_source(apiId, name, type, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources/$(name)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("type"=>type), args)); aws_config=aws_config)

"""
    UpdateFunction()

Updates a Function object.

# Required Parameters
- `apiId`: The GraphQL API ID.
- `dataSourceName`: The Function DataSource name.
- `functionId`: The function ID.
- `functionVersion`: The version of the request mapping template. Currently the supported value is 2018-05-29.
- `name`: The Function name.

# Optional Parameters
- `description`: The Function description.
- `requestMappingTemplate`: The Function request mapping template. Functions support only the 2018-05-29 version of the request mapping template.
- `responseMappingTemplate`: The Function request mapping template.
"""

update_function(apiId, dataSourceName, functionId, functionVersion, name; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions/$(functionId)", Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name); aws_config=aws_config)
update_function(apiId, dataSourceName, functionId, functionVersion, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions/$(functionId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name), args)); aws_config=aws_config)

"""
    UpdateGraphqlApi()

Updates a GraphqlApi object.

# Required Parameters
- `apiId`: The API ID.
- `name`: The new name for the GraphqlApi object.

# Optional Parameters
- `additionalAuthenticationProviders`: A list of additional authentication providers for the GraphqlApi API.
- `authenticationType`: The new authentication type for the GraphqlApi object.
- `logConfig`: The Amazon CloudWatch Logs configuration for the GraphqlApi object.
- `openIDConnectConfig`: The OpenID Connect configuration for the GraphqlApi object.
- `userPoolConfig`: The new Amazon Cognito user pool configuration for the GraphqlApi object.
- `xrayEnabled`: A flag indicating whether to enable X-Ray tracing for the GraphqlApi.
"""

update_graphql_api(apiId, name; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)", Dict{String, Any}("name"=>name); aws_config=aws_config)
update_graphql_api(apiId, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), args)); aws_config=aws_config)

"""
    UpdateResolver()

Updates a Resolver object.

# Required Parameters
- `apiId`: The API ID.
- `fieldName`: The new field name.
- `typeName`: The new type name.

# Optional Parameters
- `cachingConfig`: The caching configuration for the resolver.
- `dataSourceName`: The new data source name.
- `kind`: The resolver type.    UNIT: A UNIT resolver type. A UNIT resolver is the default resolver type. A UNIT resolver enables you to execute a GraphQL query against a single data source.    PIPELINE: A PIPELINE resolver type. A PIPELINE resolver enables you to execute a series of Function in a serial manner. You can use a pipeline resolver to execute a GraphQL query against multiple data sources.
- `pipelineConfig`: The PipelineConfig.
- `requestMappingTemplate`: The new request mapping template. A resolver uses a request mapping template to convert a GraphQL expression into a format that a data source can understand. Mapping templates are written in Apache Velocity Template Language (VTL). VTL request mapping templates are optional when using a Lambda data source. For all other data sources, VTL request and response mapping templates are required.
- `responseMappingTemplate`: The new response mapping template.
- `syncConfig`: The SyncConfig for a resolver attached to a versioned datasource.
"""

update_resolver(apiId, fieldName, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)"; aws_config=aws_config)
update_resolver(apiId, fieldName, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)", args; aws_config=aws_config)

"""
    UpdateType()

Updates a Type object.

# Required Parameters
- `apiId`: The API ID.
- `format`: The new type format: SDL or JSON.
- `typeName`: The new type name.

# Optional Parameters
- `definition`: The new definition.
"""

update_type(apiId, format, typeName; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}("format"=>format); aws_config=aws_config)
update_type(apiId, format, typeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), args)); aws_config=aws_config)

ext: jl


text:
using Flux, DiffEqFlux, StochasticDiffEq, Plots

function lotka_volterra(du,u,p,t)
  x, y = u
  α, β, δ, γ = p
  du[1] = dx = α*x - β*x*y
  du[2] = dy = -δ*y + γ*x*y
end
function lotka_volterra_noise(du,u,p,t)
  du[1] = 0.1u[1]
  du[2] = 0.1u[2]
end
prob = SDEProblem(lotka_volterra,lotka_volterra_noise,[1.0,1.0],(0.0,10.0))
p = param([2.2, 1.0, 2.0, 0.4])
function predict_fd_sde()
  diffeq_fd(p,sol->sol[1,:],101,prob,SOSRI(),saveat=0.1)
end
loss_fd_sde() = sum(abs2,x-1 for x in predict_fd_sde())
loss_fd_sde()
Flux.back!(loss_fd_sde())

function predict_rd_sde()
  Array(diffeq_rd(p,prob,SOSRI(),saveat=0.1))
end
loss_rd_sde() = sum(abs2,x-1 for x in predict_rd_sde())
loss_rd_sde()
@test_broken Flux.back!(loss_rd_sde())


text:
using NCDatasets

using ArgParse, JSON
function parse_commandline()

    s = ArgParseSettings()

    @add_arg_table s begin

        "--config-file"
            help = "Casename"
            arg_type = String
            required = true

        "--project-code"
            help = "Project code for PBS -A option"
            arg_type = String
            default = ""

        "--ncpu"
            help = "MPI cpus used"
            arg_type = Int64
            default = 36

        "--walltime"
            help = "Walltime for PBS -l walltime option"
            arg_type = String
            default = "06:00:00"

    end

    return parse_args(s)
end

parsed = parse_commandline()

JSON.print(parsed,4)

using TOML
config = TOML.parsefile(parsed["config-file"])

caseroot = config["DRIVER"]["caseroot"]

runfile = joinpath(caseroot, "run.$(config["DRIVER"]["casename"]).sh")
open(runfile, "w") do io
    write(io, """
#!/bin/bash
#PBS -A $(parsed["project-code"])
#PBS -N $(config["DRIVER"]["casename"])
#PBS -q economy
#PBS -l select=1:ncpus=36:mpiprocs=36:ompthreads=1
#PBS -l walltime=$(parsed["walltime"])
#PBS -j oe
#PBS -S /bin/bash

mpiexec -n $(parsed["ncpu"]) julia --project   \\
    $(@__DIR__)/main.jl          \\
        --stop-n=2               \\
        --time-unit=year         \\
        --config-file=$(caseroot)/config.toml \\
        --atm-forcing-file=$(@__DIR__)/data/POP2PROFILE.g16.nc

    """)
end

chmod(runfile, 0o750)

max_stars_repo_name: meteorologytoday/IOM

max_issues_repo_name: meteorologytoday/IOM

max_forks_repo_name: meteorologytoday/IOM


text:
function aqueous_diffusivity(molecular_weight::Array{Float64,1})
    # Perry and Hilton 1973
    D_S = @. 4.36e-9*molecular_weight^(-0.386)
end

max_stars_repo_name: giannamars/DEBMicroTrait

max_issues_repo_name: giannamars/DEBMicroTrait

max_forks_repo_name: giannamars/DEBMicroTrait


text:
# Test.get_test_result generates code that uses the following so we must import them
using Test: Returned, Threw, eval_test

"A cunning hack to carry extra message along with the original expression in a test"
struct ExprAndMsg
    ex
    msg
end

"""
    @test_msg msg condion kws...

This is per `Test.@test condion kws...` except that if it fails it also prints the `msg`.
If `msg==""` then this is just like `@test`, nothing is printed

### Examles
```julia
julia> @test_msg "It is required that the total is under 10" sum(1:1000) < 10;
Test Failed at REPL[1]:1
  Expression: sum(1:1000) < 10
  Problem: It is required that the total is under 10
   Evaluated: 500500 < 10
ERROR: There was an error during testing

julia> @test_msg "It is required that the total is under 10" error("not working at all");
Error During Test at REPL[2]:1
  Test threw exception
  Expression: error("not working at all")
  Problem: It is required that the total is under 10
  "not working at all"
  Stacktrace:

julia> a = "";

julia> @test_msg a sum(1:1000) < 10;
  Test Failed at REPL[153]:1
    Expression: sum(1:1000) < 10
     Evaluated: 500500 < 10
  ERROR: There was an error during testing
```
"""
macro test_msg(msg, ex, kws...)
    # This code is basically a evil hack that accesses the internals of the Test stdlib.
    # Code below is based on the `@test` macro definition as it was in Julia 1.6.
    # https://github.com/JuliaLang/julia/blob/v1.6.1/stdlib/Test/src/Test.jl#L371-L376
    Test.test_expr!("@test_msg msg", ex, kws...)

    result = Test.get_test_result(ex, __source__)
    return :(Test.do_test($result, $ExprAndMsg($(string(ex)), $(esc(msg)))))
end

function Base.print(io::IO, x::ExprAndMsg)
    print(io, x.ex)
    !isempty(x.msg) && print(io, "\n  Problem: ", x.msg)
end

### helpers for printing in log messages etc
_string_typeof(x) = string(typeof(x))
_string_typeof(xs::Tuple) = join(_string_typeof.(xs), ",")
_string_typeof(x::PrimalAndTangent) = _string_typeof(primal(x))  # only show primal


text:
function show(io::IO, x::DoubleFloat{T}) where {T<:IEEEFloat}
    compact = get(io, :compact, true)
    if compact
        str = string(x.hi)
    else
        str = string(x)
    end
    print(io, str)
end

function show(io::IO, x::Complex{DoubleFloat{T}}) where {T<:IEEEFloat}
    compact = get(io, :compact, true)
    if compact
        str = string(x.re.hi, (signbit(x.im.hi) ? " - " : " + "), abs(x.im.hi), "im")
    else
        str = string(x.re, (signbit(x.im.hi) ? " - " : " + "), abs(x.im), "im")
    end
    print(io, str)
end

for (T,D) in ((:Float64, :"Double64"), (:Float32, :"Double32"), (:Float16, :"Double16"))
  @eval begin
    function show(io::IO, ::MIME"text/plain", x::Vector{DoubleFloat{$T}})
        println(io, string(length(x),"-element ","Array{",$D,",1}:"))
        for a in x
            spc = signbit(a.hi) ? "" : " "
            println(io, string(spc,a))
        end
        return nothing
    end
    function show(io::IOContext, x::Vector{DoubleFloat{$T}})
        iostream = io.io
        println(iostream, string(length(x),"-element ","Array{",$D,",1}:"))
        for a in x
            spc = signbit(a.hi) ? "" : " "
            println(io, spc, a)
        end
        return nothing
    end
  end
end

show(x::DoubleFloat{T}) where {T<:IEEEFloat} = show(Base.stdout, x)

show(x::Complex{DoubleFloat{T}}) where {T<:IEEEFloat} = show(Base.stdout, x)

function showtyped(io::IO, x::DoubleFloat{T}) where {T<:IEEEFloat}
    str = stringtyped(x)
    print(io, str)
end

showtyped(io::IO, ::MIME"text/plain", x::DoubleFloat{T}) where {T<:IEEEFloat} = showtyped(io, x)

showtyped(io::IO, ::MIME"text/plain", x::Complex{DoubleFloat{T}}) where {T<:IEEEFloat} = showtyped(io, x)

showtyped(x::DoubleFloat{T}) where {T<:IEEEFloat} = showtyped(Base.stdout, x)

showtyped(x::Complex{DoubleFloat{T}}) where {T<:IEEEFloat} = showtyped(Base.stdout, x)


text:
@testset "Sparse" begin
    A = AFArray(rand(10,10));
    @test !issparse(A)

    # build an identity matrix
    n = 10;

    Ie = AFArray(Matrix{Float32}(I,10,10))
    Aid = sparse(Ie)

    @test issparse(Aid)

    Ie2 = full(Aid)

    @test !issparse(Ie2)

    @test all(Ie2 == Ie)

    e = sprand(10, 20, 0.2)
    c = randn(20)
    a1 = AFArray(e)
    c1 = AFArray(c)
    @test issparse(a1)

    e2 = SparseMatrixCSC(a1)
    @test e2 == e

    @test sum(e * c) ≈ sum(a1 * c1)
end


text:
using DataFrames, CSV, FFTW, LinearAlgebra, ToeplitzMatrices, Plots

us = [] # flows
push!(us, CSV.read("stergiopulos1999_data/aflow.csv", DataFrame, header=false,types=[Float64, Float64]).Column2)
push!(us, CSV.read("invivo_data/Ao_baseline1_AoQ1.csv", DataFrame, comment="#",header=true,types=[Time, Float64], normalizenames=true).vb_va)
push!(us, CSV.read("exvivo_data/Ao_baseline1_AoQ1.csv", DataFrame, comment="#",header=true,types=[Time, Float64], normalizenames=true).vb_va)

S = [] # normalized singular values
for u in us
    N = length(u)
    D = fft(Matrix{Float64}(I,N,N),1)
    r = 1/N*conj(D)*(abs.(D*u).^2)
    Φ = Array(Toeplitz(r,r))
    Snorm = svd(Φ).S./maximum(svd(Φ).S)
    display(plot(Snorm, xlims=(1,20), lw=2, marker=:circle, grid=true))
    push!(S,Snorm)
end

# export data for pgfplots
comment = *("# The largest 20 singular values (normalized) of the autocorrelation matrix of flow data from the following sources\n",
"# S1999: parsed at 200Hz (n=166) from stergiopulos1999total doi = {10.1152/ajpheart.1999.276.1.H81}, Figure 4A type A beat using https://automeris.io/WebPlotDigitizer\n",
"# Sinvivo: measured in vivo Ao_baseline1 20201201\n",
"# Sexvivo: measured ex vivo Ao_baseline1 20201202\n")
filename = "spectrum.csv"
open(filename, "w") do f
    write(f, comment)
end
CSV.write(filename, DataFrame(x = collect(1:20), S1999 = S[1][1:20], Sinvivo = S[2][1:20], Sexvivo = S[3][1:20]), header=true, append=true)
# CSV.write("flow1999.csv", DataFrame(u1999 = u[1]))
# CSV.write("flowinvivo.csv", DataFrame(uinvivo = u[2]))
# CSV.write("flowexvivo.csv", DataFrame(uexvivo = u[3]))

max_stars_repo_name: hpigot/windkessel-id

max_issues_repo_name: hpigot/windkessel-id

max_forks_repo_name: hpigot/windkessel-id


text:
### A Pluto.jl notebook ###
# v0.14.1

using Markdown
using InteractiveUtils

# ╔═╡ d3435ffa-6910-11eb-1169-5f99095f1fdf
begin
	using PlutoUI
	using Test
	using Printf
end

# ╔═╡ 57e617da-6910-11eb-0e3f-33b08ab72b7a
md"""
### Structs and Functions

* From Chapter 16. Structs and Functions - Think Julia, by Ben Lauwens*
* From Chapter 17. Multiple Dispatch  - Think Julia, by Ben Lauwens*

Resources:
- https://github.com/BenLauwens/ThinkJulia.jl
"""

# ╔═╡ b8800646-8364-4cd9-8ab5-c010c666fb65
PlutoUI.TableOfContents(indent=true, depth=4, aside=true)

# ╔═╡ 7d6fa0de-6910-11eb-00df-39e0c9733dd2
"""
Represents the time of day.
fields: hour, minute, second
"""
struct YaTime
    hour::Int64
    minute::Int64
    second::Int64

    # inner constructor, to enforce invariants:
    function YaTime(hour::Int64=0, minute::Int64=0, second::Int64=0)
        @assert(0 ≤ minute < 60, "Minute is not between 0 and 60.")
        @assert(0 ≤ second < 60, "Second is not between 0 and 60.")

        new(hour, minute, second)
    end
end

# ╔═╡ a5a13cf2-6910-11eb-1db3-392525cb52dc
md"""
The `struct YaTime` now has four inner constructor methods:
- `YaTime()`
- `YaTime(hour::Int64)`
- `YaTime(hour::Int64, minute::Int64)`
- `YaTime(hour::Int64, minute::Int64, second::Int64)`

An inner constructor method is always defined inside the block of a type declaration, and it has access to a special function called `new` that creates objects of the newly declared type.
"""

# ╔═╡ b5c2de12-6910-11eb-3ade-73ae4245aaf9
begin
	@test_throws AssertionError YaTime(23, 89, 10)
	@test_throws AssertionError YaTime(23, 89)
end

# ╔═╡ 0e1ecf32-6912-11eb-3eff-4bbfc6d00980
md"""
**Exercise**

Write a function called print_time that takes a YaTime object and prints it in the form `hour:minute:second`.
The @printf macro of the standard library module Printf prints an integer with the format sequence `"%02d"` using at least two digits, including a leading zero if necessary.

"""

# ╔═╡ 030e96a8-6911-11eb-3c5f-b103f63ecb8f
function print_time(t::YaTime)
    @printf("%02d:%02d:%02d\n", t.hour, t.minute, t.second)
end

# ╔═╡ 5777439a-6911-11eb-3cd0-cdd3a66c15a6
with_terminal() do
	t = YaTime(10, 11, 24) # using default (implicit) constructor
	print_time(t)
end

# ╔═╡ 6f3db41e-6911-11eb-016d-11a7e82f072d
## we can also define Base.show

Base.show(io::IO, t::YaTime) = print(io, @sprintf("%02d:%02d:%02d\n", t.hour, t.minute, t.second))

# ╔═╡ d522cea2-6911-11eb-026f-4be6aec6f3de
t₁ = YaTime(19, 58, 24)

# ╔═╡ 22d86fa0-6912-11eb-13f6-1125998a1df7
md"""
**Exercise**

Write a Boolean function called `is_after` that takes two YaTime objects, t1 and t2, and returns true if t1 follows t2 chronologically and false otherwise.

*Challenge: don’t use an if statement.*
"""

# ╔═╡ 37c16a0c-6912-11eb-07c3-733e4066b898
is_after(t₁::YaTime, t₂::YaTime) = t₁.hour > t₂.hour || t₁.minute > t₂.minute || t₁.second > t₂.second

# ╔═╡ 91dcec8c-6912-11eb-1c04-f781c60db1ae
begin
	tₓ, tₜ = (YaTime(11, 11, 54), YaTime(10, 11, 54))
	@test is_after(tₓ, tₜ)

	(t₃, t₄) = (YaTime(11, 11, 56), YaTime(11, 11, 55))
	@test is_after(t₃, t₄)

	t₅ = YaTime(11, 10, 54)
	@test is_after(t₃, t₅)

	t₆= YaTime(12, 11, 54)
	@test !is_after(tₓ, t₆)    ## negation
end

# ╔═╡ a64a66e4-6913-11eb-29cb-85ce1f785caa
md"""
#### Pure Function
"""

# ╔═╡ 50166aec-6914-11eb-2bda-cde28024c50f
begin

import Base: +, ==, isless

function +(t₁::YaTime, t₂::YaTime)::YaTime
    """
    Creates a new YaTime Struct, initializes its fields, and returns a reference to it
    """
    sec  = t₁.second + t₂.second
    min  = t₁.minute + t₂.minute
    hour = t₁.hour + t₂.hour

    sec, min  = add_hlpr(sec, min)
    min, hour = add_hlpr(min, hour)

    YaTime(hour, min, sec)
end

function +(t::YaTime, sec::Int64)::YaTime
  	tsec = time_to_int(t) + sec
  	int_to_time(tsec)
end

+(sec::Int64, t::YaTime) = :+(t, sec)

function ==(t₁::YaTime, t₂::YaTime)::Bool
	t₁.hour == t₂.hour && t₁.minute == t₂.minute && t₁.second == t₂.second
end

function isless(t₁::YaTime, t₂::YaTime)::Bool
    (t₁.hour, t₁.minute, t₁.second) < (t₂.hour, t₂.minute, t₂.second)
end

function time_to_int(t::YaTime)::Int64
  t.second + t.minute * 60 + t.hour * 3600
end

function int_to_time(val::Int64)::YaTime
  (h, val) = divrem(val, 3600)
  (m, s) = divrem(val, 60)
  YaTime(h, m, s)
end

function add_hlpr(u₁::Integer, u₂::Integer, mod::Integer=60)
    if u₁ > mod
        u₁ -= 60
        u₂ += 1
    end
    (u₁, u₂)
end

end

# ╔═╡ eff6c928-6917-11eb-2720-918204039f0e
with_terminal() do
	println(methods(+))
end

# ╔═╡ de8be752-6914-11eb-2061-21ec29439e96
begin
	(tₐ, tₒ) = (YaTime(12, 11, 54), YaTime(11, 11, 54))
	nt = tₐ + tₒ
end

# ╔═╡ 1ced8ab4-6915-11eb-1de5-3de099efa35c
@test YaTime(10, 30, 54) + YaTime(9, 11, 44) == YaTime(19, 42, 38)

# ╔═╡ e4bc1df8-6915-11eb-130f-e1b1bdd1e940
md"""
#### Using Conversions

When we wrote `+`, we were effectively doing addition in base 60, which is why we had to carry from one column to the next.

This observation suggests another approach to the whole problem — we can convert YaTime objects to integers and take advantage of the fact that the computer knows how to do integer arithmetic.

cf. implementation above...
"""

# ╔═╡ 6526d230-6916-11eb-07f2-63fe39f294c7
begin
	ts = YaTime(1, 10, 10)
	@test time_to_int(ts) == 4210

	nts = YaTime(2, 31, 10)
	@test time_to_int(nts) == 9070  # "3h31m10s is 9070s"

	nts₂ = YaTime(24, 0, 0)
	@test time_to_int(nts₂) == 86_400 # "24h is 86400s"

	nts₃ = YaTime(24, 0, 0) + 11
	@test time_to_int(nts₃) == 86_411 # "24h and 11s is 86411s"
end

# ╔═╡ d2836738-c72c-4348-aede-7db694123f70
html"""
<style>
  main {
        max-width: calc(800px + 25px + 6px);
  }
  .plutoui-toc.aside {
    background: linen;
  }
  h3, h4 {
        background: wheat;
  }
</style>
"""

# ╔═╡ Cell order:
# ╟─57e617da-6910-11eb-0e3f-33b08ab72b7a
# ╠═d3435ffa-6910-11eb-1169-5f99095f1fdf
# ╟─b8800646-8364-4cd9-8ab5-c010c666fb65
# ╠═7d6fa0de-6910-11eb-00df-39e0c9733dd2
# ╟─a5a13cf2-6910-11eb-1db3-392525cb52dc
# ╠═b5c2de12-6910-11eb-3ade-73ae4245aaf9
# ╟─0e1ecf32-6912-11eb-3eff-4bbfc6d00980
# ╠═030e96a8-6911-11eb-3c5f-b103f63ecb8f
# ╠═5777439a-6911-11eb-3cd0-cdd3a66c15a6
# ╠═6f3db41e-6911-11eb-016d-11a7e82f072d
# ╠═d522cea2-6911-11eb-026f-4be6aec6f3de
# ╟─22d86fa0-6912-11eb-13f6-1125998a1df7
# ╠═37c16a0c-6912-11eb-07c3-733e4066b898
# ╠═91dcec8c-6912-11eb-1c04-f781c60db1ae
# ╟─a64a66e4-6913-11eb-29cb-85ce1f785caa
# ╠═50166aec-6914-11eb-2bda-cde28024c50f
# ╠═eff6c928-6917-11eb-2720-918204039f0e
# ╠═de8be752-6914-11eb-2061-21ec29439e96
# ╠═1ced8ab4-6915-11eb-1de5-3de099efa35c
# ╟─e4bc1df8-6915-11eb-130f-e1b1bdd1e940
# ╠═6526d230-6916-11eb-07f2-63fe39f294c7
# ╟─d2836738-c72c-4348-aede-7db694123f70

max_stars_repo_name: pascal-p/julia-notebooks

max_issues_repo_name: pascal-p/julia-notebooks

max_forks_repo_name: pascal-p/julia-notebooks


text:
"""
`BufferedVector` is a wrapper around `Vector` that avoid shrinking the inner `Vector`

This is done by keeping a `size` in itself that represets the number of usable elements in
the underlying `Vector`.

Note: if an element is added to this `Vector`, it might not get garbage collected, as a
      pointer to it might remain in the underlying `Vector`. Thus, storing huge objects in
      `BufferedVector` is not encouraged.
"""
mutable struct BufferedVector{T} <: AbstractVector{T}
    buff::Vector{T}
    size::SizeType

    BufferedVector{T}() where {T} = new{T}(Vector{T}(), 0)
    BufferedVector(buff::Vector{T}) where {T} = new{T}(buff, 0)
end
function Base.iterate(vec::BufferedVector{T}, state::Int=1) where {T}
    state > vec.size ? nothing : (vec.buff[state], state+1)
end
function Base.resize!(vec::BufferedVector{T}, new_size::SizeType) where {T}
    if length(vec.buff) < new_size
        resize!(vec.buff, new_size)
    end
end
function Base.setindex!(vec::BufferedVector{T}, val, key) where {T}
    # `setindex!` is supposed to be called in a sequence
    @assert key == vec.size + 1
    vec.buff[key] = val
    vec.size += 1
    nothing
end

Base.getindex(vec::BufferedVector{T}, key) where {T} = getindex(vec.buff, key)
Base.length(vec::BufferedVector{T}) where {T} = vec.size
Base.isempty(vec::BufferedVector{T}) where {T} = vec.size == 0
Base.empty!(vec::BufferedVector{T}) where {T} = (vec.size = 0; nothing)
capacity(vec::BufferedVector{T}) where {T} = SizeType(length(vec.buff))

Base.IndexStyle(::Type{<:BufferedVector}) = IndexLinear()
Base.IndexStyle(::BufferedVector) = IndexLinear()
Base.size(vec::BufferedVector) = (vec.size,)
Base.eltype(::Type{BufferedVector{T}}) where {T} = T


text:
mutable struct KktCache{T}
    K::SparseMatrixCSC{T, Int64}
    Kt::SparseMatrixCSC{T, Int64}
    ldl_fact::QDLDLFactorisation{T, Int64}
    equil::Vector{T}
    reg::T
    x1::Vector{T}
    y1::Vector{T}
    z1::Vector{T}
    n::Int64
    m::Int64
    p::Int64
    q::Int64
end

function KktCache(prob::Problem{T}, settings::Settings{T}, scaling::CompositeConeScaling{T}) where T
    n, m, p = get_prob_sizes(prob)
    P = SparseMatrixCSC(Diagonal(fill(settings.prim_reg, n)))
    S = SparseMatrixCSC(Diagonal(fill(settings.dual_reg, m)))
    R = settings.init_scaling_param*speye(p)
    q = get_num_quad_cones(prob.C)
    sz(dims...) = spzeros(T, dims...)
    K = [         P   prob.A'   prob.G'  sz(n, 2q)
             prob.A        -S  sz(m, p)  sz(m, 2q)
             prob.G  sz(p, m)        -R  sz(p, 2q)
          sz(2q, n) sz(2q, m) sz(2q, p) sz(2q, 2q) ]
    K[n+m+1:end, n+m+1:end] -= get_lower_kkt_block(scaling, identity=true)

    x1 = fill(NaN, n)
    y1 = fill(NaN, m)
    z1 = fill(NaN, p)
    n, m, p = get_prob_sizes(prob)

    perm = amd(K)
    Kt, equil, _, = equilibrate(K, max_iters=settings.kkt_equil_iters)
    reg = settings.init_reg
    ldl_fact = qdldl(Kt, perm=perm, reg=reg)
    kkt = KktCache{T}(K, Kt, ldl_fact, equil, reg, x1, y1, z1, n, m, p, q)
    return kkt
end

function factorize!(kkt::KktCache)
    kkt.ldl_fact = qdldl(kkt.Kt, perm=kkt.ldl_fact.perm, reg=kkt.reg)
end

function update!(kkt::KktCache, iter::Iterate, prob::Problem, W::CompositeConeScaling, settings::Settings)
    μ_hat = (iter.s' * iter.z + iter.κ * iter.τ) / (degree(prob.C) + 1)
    n, m, p = get_prob_sizes(prob)

    reg_x = min.(settings.prim_reg .+ settings.trust_reg_scaling * μ_hat ./ iter.x.^2, settings.max_trust_reg)
    reg_y = min.(settings.prim_reg .+ settings.trust_reg_scaling * μ_hat ./ iter.y.^2, settings.max_trust_reg)
    P = SparseMatrixCSC(Diagonal(reg_x))
    S = SparseMatrixCSC(Diagonal(reg_y))
    R = SparseMatrixCSC(Diagonal(fill(settings.dual_reg, p)))
    kkt.K[1:n, 1:n] = P
    kkt.K[n+1:n+m, n+1:n+m] = -S
    kkt.K[n+m+1:n+m+p, n+m+1:n+m+p] = -R
    kkt.K[n+m+1:end, n+m+1:end] -= get_lower_kkt_block(W)
    kkt.Kt, kkt.equil, _, = equilibrate(kkt.K, max_iters=5)
    kkt.equil = kkt.equil
    factorize!(kkt)
end

function cache_first_solve!(kkt::KktCache{T}, prob::Problem{T}, settings::Settings{T},
                            stats::Stats{T}) where T
    rhs = [-prob.c, prob.b, prob.h, zeros(2*kkt.q)]
    (kkt.x1, kkt.y1, kkt.z1, _), best_ref_ratio, last_ref_ratio, num_iters, corr_ratio =
                solve_and_refine(kkt, rhs, max_iters=settings.max_iters_ir)
    register_cache_stats!(stats, num_iters, kkt.reg)

    kkt.reg = get_next_reg(best_ref_ratio, last_ref_ratio, corr_ratio, kkt.reg, settings)
end

function get_next_reg(best_ref_ratio::T, last_ref_ratio::T, corr_ratio::T,
                      last_reg::T, settings::Settings{T}) where T <: AbstractFloat
    if last_ref_ratio > settings.great_ref_ratio
        next_reg = max(last_reg/settings.reg_decrease_param, settings.min_reg)
    elseif (last_ref_ratio < settings.min_ref_ratio_ir) || (corr_ratio < settings.min_corr_ratio_ir)
        next_reg = min(settings.reg_increase_param*last_reg, settings.max_reg)
    else
        next_reg = max(last_reg/settings.reg_decrease_param, settings.min_reg)
    end
    return next_reg
end

function mult_by_vector(kkt::KktCache{T}, prob::Problem{T}, scaling::CompositeConeScaling{T},
                        x::Vector{T}, y::Vector{T}, z::Vector{T}) where T <: AbstractFloat
    W = convert(Vector{T}, scaling.W)
    Ax = prob.A' * y + prob.G' * z
    Ay = prob.A * x
    Az = -prob.G * x + W'*W*z1
    return Ax, Ay, Az
end

function solve(kkt::KktCache, rhs::Vector{T}) where T <: AbstractFloat
    n_orig = length(rhs)
    n_extra = length(kkt.equil) - n_orig
    rhs = [rhs; zeros(n_extra)]

    rhs_e = kkt.equil .* rhs
    sol_e = kkt.ldl_fact \ rhs_e
    sol = sol_e .* kkt.equil
    return sol[1:n_orig]
end

function split(y::Vector{T}, lens::Vector{Int64}) where T <: AbstractFloat
    cum_lens = [0; cumsum(lens)]
    y_split = [y[cum_lens[i]+1:cum_lens[i+1]] for i in 1:length(lens)]
    return y_split
end

# TODO change to "get_error"
function multiply(kkt::KktCache, x::Vector{T}) where T <: AbstractFloat
    n_orig = length(x)
    n_extra = length(kkt.equil) - n_orig
    x = [x; zeros(n_extra)]
    E = Diagonal(kkt.ldl_fact.workspace.E[kkt.ldl_fact.iperm])

    x_e = x ./ kkt.equil
    y_e = kkt.Kt * x_e
    y_e_corr = y_e + E * x_e
    y = y_e ./ kkt.equil
    y_corr = y_e_corr ./ kkt.equil
    return y[1:n_orig], y_corr[1:n_orig]
end

function solve_and_refine(kkt::KktCache, rhs::Vector{T}; max_iters=5, tol=1e-13,
                          non_improv_tol=2.) where T <: AbstractFloat

    num_iters = 0
    x = solve(kkt, rhs)
    x_prec = x_best = convert(Vector{T}, x)
    (max_iters == 0) && return x_prec, 1., num_iters, 1.  # If we don't do iterative refinement, just return.

    # Compute error:
    Kx, Kx_plus_Ex = multiply(kkt, x_prec)
    err = rhs - Kx
    corr_err = norm(rhs - Kx_plus_Ex, Inf)
    first_err = last_err = best_err = norm(err, Inf)
    corr_err_ratio = first_err / corr_err

    while num_iters < max_iters
        # Iterative refinement:
        corr = solve(kkt, err)
        x_prec += corr

        # Compute forward error:
        err = rhs - multiply(kkt, x_prec)[1]
        norm_err = norm(err, Inf)

        # First termination condition:
        (last_err < norm_err) && break
        if norm_err < best_err
            x_best = copy(x_prec)
            best_err = norm_err
        end

        # Update:
        x_last = copy(x_prec)
        num_iters += 1

        # Second termination condition:
        (last_err / norm_err < non_improv_tol) && break
        last_err = norm_err
        (norm_err < tol) && break
    end
    return x_prec, first_err/best_err, first_err/last_err, num_iters, corr_err_ratio
end

function solve(kkt::KktCache, x::Vector{Vector{T}}) where T <: AbstractFloat
    rhs = vcat(x...)
    sol = solve(kkt, rhs)
    return split(sol, map(length, x))
end

function solve_and_refine(kkt::KktCache, x::Vector{Vector{T}}; kwargs...) where T <: AbstractFloat
    rhs = vcat(x...)
    sol, best_ref_ratio, last_ref_ratio, num_iters, corr_err_ratio = solve_and_refine(kkt, rhs; kwargs...)
    return split(sol, map(length, x)), best_ref_ratio, last_ref_ratio, num_iters, corr_err_ratio
end


text:
"""
    struct MonomialBasis{D,T} <: Field

Type representing a basis of multivariate scalar-valued, vector-valued, or
tensor-valued, iso- or aniso-tropic monomials. The fields
of this `struct` are not public
This type fully implements the [`Field`](@ref) interface, with up to second order
derivatives.
"""
struct MonomialBasis{D,T} <: Field
  orders::NTuple{D,Int}
  terms::Vector{CartesianIndex{D}}
  function MonomialBasis{D}(
    ::Type{T}, orders::NTuple{D,Int}, terms::Vector{CartesianIndex{D}}) where {D,T}
    new{D,T}(orders,terms)
  end
end

"""
    MonomialBasis{D}(::Type{T}, orders::Tuple [, filter::Function]) where {D,T}

This version of the constructor allows to pass a tuple `orders` containing the
polynomial order to be used in each of the `D` dimensions in order to  construct
and anisotropic tensor-product space.
"""
function MonomialBasis{D}(
  ::Type{T}, orders::NTuple{D,Int}, filter::Function=_q_filter) where {D,T}

  terms = _define_terms(filter, orders)
  MonomialBasis{D}(T,orders,terms)
end

"""
    MonomialBasis{D}(::Type{T}, order::Int [, filter::Function]) where {D,T}

Returns an instance of `MonomialBasis` representing a multivariate polynomial basis
in `D` dimensions, of polynomial degree `order`, whose value is represented by the type `T`.
The type `T` is typically `<:Number`, e.g., `Float64` for scalar-valued functions and `VectorValue{D,Float64}`
for vector-valued ones.

# Filter function

The `filter` function is used to select which terms of the tensor product space
of order `order` in `D` dimensions are to be used. If the filter is not provided, the full tensor-product
space is used by default leading to a multivariate polynomial space of type Q.
The signature of the filter function is

    (e,order) -> Bool

where `e` is a tuple of `D` integers containing the exponents of a multivariate monomial. The following filters
are used to select well known polynomial spaces

- Q space: `(e,order) -> true`
- P space: `(e,order) -> sum(e) <= order`
- "Serendipity" space: `(e,order) -> sum( [ i for i in e if i>1 ] ) <= order`

"""
function MonomialBasis{D}(
  ::Type{T}, order::Int, filter::Function=_q_filter) where {D,T}

  orders = tfill(order,Val{D}())
  MonomialBasis{D}(T,orders,filter)
end

# API

"""
    get_exponents(b::MonomialBasis)

Get a vector of tuples with the exponents of all the terms in the
monomial basis.

# Examples

```jldoctest
using Gridap.Polynomials

b = MonomialBasis{2}(Float64,2)

exponents = get_exponents(b)

println(exponents)

# output
Tuple{Int64,Int64}[(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)]
```
"""
function get_exponents(b::MonomialBasis)
  indexbase = 1
  [Tuple(t) .- indexbase for t in b.terms]
end

"""
    get_order(b::MonomialBasis)
"""
function get_order(b::MonomialBasis)
  maximum(b.orders)
end

"""
    get_orders(b::MonomialBasis)
"""
function get_orders(b::MonomialBasis)
  b.orders
end

"""
"""
get_value_type(::MonomialBasis{D,T}) where {D,T} = T

get_value_type(::Type{MonomialBasis{D,T}}) where {D,T} = T

# Field implementation

function field_cache(f::MonomialBasis{D,T},x) where {D,T}
  @assert D == length(eltype(x)) "Incorrect number of point components"
  np = length(x)
  ndof = length(f.terms)*num_components(T)
  n = 1 + _maximum(f.orders)
  r = CachedArray(zeros(T,(np,ndof)))
  v = CachedArray(zeros(T,(ndof,)))
  c = CachedArray(zeros(eltype(T),(D,n)))
  (r, v, c)
end

function evaluate_field!(cache,f::MonomialBasis{D,T},x) where {D,T}
  r, v, c = cache
  np = length(x)
  ndof = length(f.terms)*num_components(T)
  n = 1 + _maximum(f.orders)
  setsize!(r,(np,ndof))
  setsize!(v,(ndof,))
  setsize!(c,(D,n))
  for i in 1:np
    @inbounds xi = x[i]
    _evaluate_nd!(v,xi,f.orders,f.terms,c)
    for j in 1:ndof
      @inbounds r[i,j] = v[j]
    end
  end
  r.array
end

function gradient_cache(f::MonomialBasis{D,V},x) where {D,V}
  @assert D == length(eltype(x)) "Incorrect number of point components"
  np = length(x)
  ndof = length(f.terms)*num_components(V)
  xi = testitem(x)
  T = gradient_type(V,xi)
  n = 1 + _maximum(f.orders)
  r = CachedArray(zeros(T,(np,ndof)))
  v = CachedArray(zeros(T,(ndof,)))
  c = CachedArray(zeros(eltype(T),(D,n)))
  g = CachedArray(zeros(eltype(T),(D,n)))
  (r, v, c, g)
end

function evaluate_gradient!(cache,f::MonomialBasis{D,T},x) where {D,T}
  r, v, c, g = cache
  np = length(x)
  ndof = length(f.terms) * num_components(T)
  n = 1 + _maximum(f.orders)
  setsize!(r,(np,ndof))
  setsize!(v,(ndof,))
  setsize!(c,(D,n))
  setsize!(g,(D,n))
  for i in 1:np
    @inbounds xi = x[i]
    _gradient_nd!(v,xi,f.orders,f.terms,c,g,T)
    for j in 1:ndof
      @inbounds r[i,j] = v[j]
    end
  end
  r.array
end

function hessian_cache(f::MonomialBasis{D,V},x) where {D,V}
  @assert D == length(eltype(x)) "Incorrect number of point components"
  np = length(x)
  ndof = length(f.terms)*num_components(V)
  xi = testitem(x)
  T = gradient_type(gradient_type(V,xi),xi)
  n = 1 + _maximum(f.orders)
  r = CachedArray(zeros(T,(np,ndof)))
  v = CachedArray(zeros(T,(ndof,)))
  c = CachedArray(zeros(eltype(T),(D,n)))
  g = CachedArray(zeros(eltype(T),(D,n)))
  h = CachedArray(zeros(eltype(T),(D,n)))
  (r, v, c, g, h)
end

function evaluate_hessian!(cache,f::MonomialBasis{D,T},x) where {D,T}
  r, v, c, g, h = cache
  np = length(x)
  ndof = length(f.terms) * num_components(T)
  n = 1 + _maximum(f.orders)
  setsize!(r,(np,ndof))
  setsize!(v,(ndof,))
  setsize!(c,(D,n))
  setsize!(g,(D,n))
  setsize!(h,(D,n))
  for i in 1:np
    @inbounds xi = x[i]
    _hessian_nd!(v,xi,f.orders,f.terms,c,g,h,T)
    for j in 1:ndof
      @inbounds r[i,j] = v[j]
    end
  end
  r.array
end

# Helpers

_q_filter(e,o) = true

function _define_terms(filter,orders)
  t = orders .+ 1
  g = (0 .* orders) .+ 1
  cis = CartesianIndices(t)
  co = CartesianIndex(g)
  maxorder = _maximum(orders)
  [ ci for ci in cis if filter(Int[Tuple(ci-co)...],maxorder) ]
end

function _evaluate_1d!(v::AbstractMatrix{T},x,order,d) where T
  n = order + 1
  z = one(T)
  @inbounds v[d,1] = z
  for i in 2:n
    @inbounds v[d,i] = x[d]^(i-1)
  end
end

function _gradient_1d!(v::AbstractMatrix{T},x,order,d) where T
  n = order + 1
  z = zero(T)
  @inbounds v[d,1] = z
  for i in 2:n
    @inbounds v[d,i] = (i-1)*x[d]^(i-2)
  end
end

function _hessian_1d!(v::AbstractMatrix{T},x,order,d) where T
  n = order + 1
  z = zero(T)
  @inbounds v[d,1] = z
  if n>1
    @inbounds v[d,2] = z
  end
  for i in 3:n
    @inbounds v[d,i] = (i-1)*(i-2)*x[d]^(i-3)
  end
end

function _evaluate_nd!(
  v::AbstractVector{V},
  x,
  orders,
  terms::AbstractVector{CartesianIndex{D}},
  c::AbstractMatrix{T}) where {V,T,D}

  dim = D
  for d in 1:dim
    _evaluate_1d!(c,x,orders[d],d)
  end

  o = one(T)
  k = 1

  for ci in terms

    s = o
    for d in 1:dim
      @inbounds s *= c[d,ci[d]]
    end

    k = _set_value!(v,s,k)

  end

end

@inline function _set_value!(v::AbstractVector{V},s::T,k) where {V,T}
  m = zero(mutable(V))
  z = zero(T)
  js = eachindex(m)
  for j in js
    for i in js
      @inbounds m[i] = z
    end
    m[j] = s
    v[k] = m
    k += 1
  end
  k
end

@inline function _set_value!(v::AbstractVector{<:Real},s,k)
    @inbounds v[k] = s
    k+1
end

function _gradient_nd!(
  v::AbstractVector{G},
  x,
  orders,
  terms::AbstractVector{CartesianIndex{D}},
  c::AbstractMatrix{T},
  g::AbstractMatrix{T},
  ::Type{V}) where {G,T,D,V}

  dim = D
  for d in 1:dim
    _evaluate_1d!(c,x,orders[d],d)
    _gradient_1d!(g,x,orders[d],d)
  end

  z = zero(mutable(VectorValue{D,T}))
  o = one(T)
  k = 1

  for ci in terms

    s = z
    for i in eachindex(s)
      @inbounds s[i] = o
    end
    for q in 1:dim
      for d in 1:dim
        if d != q
          @inbounds s[q] *= c[d,ci[d]]
        else
          @inbounds s[q] *= g[d,ci[d]]
        end
      end
    end

    k = _set_gradient!(v,s,k,V)

  end

end

@inline function _set_gradient!(
  v::AbstractVector{G},s,k,::Type{<:Real}) where G

  @inbounds v[k] = s
  k+1
end

@inline function _set_gradient!(
  v::AbstractVector{G},s,k,::Type{V}) where {V,G}

  T = eltype(s)
  m = zero(mutable(G))
  w = zero(V)
  z = zero(T)
  for j in CartesianIndices(w)
    for i in CartesianIndices(m)
     @inbounds m[i] = z
    end
    for i in CartesianIndices(s)
      @inbounds m[i,j] = s[i]
    end
    @inbounds v[k] = m
    k += 1
  end
  k
end

function _hessian_nd!(
  v::AbstractVector{G},
  x,
  orders,
  terms::AbstractVector{CartesianIndex{D}},
  c::AbstractMatrix{T},
  g::AbstractMatrix{T},
  h::AbstractMatrix{T},
  ::Type{V}) where {G,T,D,V}

  dim = D
  for d in 1:dim
    _evaluate_1d!(c,x,orders[d],d)
    _gradient_1d!(g,x,orders[d],d)
    _hessian_1d!(h,x,orders[d],d)
  end

  z = zero(mutable(TensorValue{D,D,T}))
  o = one(T)
  k = 1

  for ci in terms

    s = z
    for i in eachindex(s)
      @inbounds s[i] = o
    end
    for r in 1:dim
      for q in 1:dim
        for d in 1:dim
          if d != q && d != r
            @inbounds s[r,q] *= c[d,ci[d]]
          elseif d == q && d ==r
            @inbounds s[r,q] *= h[d,ci[d]]
          else
            @inbounds s[r,q] *= g[d,ci[d]]
          end
        end
      end
    end

    k = _set_gradient!(v,s,k,V)

  end

end

_maximum(orders::Tuple{}) = 0
_maximum(orders) = maximum(orders)


text:
isdefined(Base, :__precompile__) && __precompile__()
module UnicodePlots

using Base.Dates
import StatsBase: Histogram, fit

export

    GraphicsArea,
        Canvas,
            BrailleCanvas,
            DensityCanvas,
            BlockCanvas,
            AsciiCanvas,
            DotCanvas,
        BarplotGraphics,

    pixel_width,
    pixel_height,
    pixel_size,
    width,
    height,
    origin_x,
    origin_y,
    origin,
    printrow,
    nrows,
    ncols,

    pixel!,
    points!,
    lines!,
    addrow!,

    Plot,
    title, title!,
    xlabel, xlabel!,
    ylabel, ylabel!,
    annotate!,

    barplot, barplot!,
    lineplot, lineplot!,
    scatterplot, scatterplot!,
    stairs, stairs!,
    histogram,
    densityplot, densityplot!,
    spy

include("common.jl")
include("canvas.jl")
include("graphics/lookupcanvas.jl")
include("graphics/braillecanvas.jl")
include("graphics/densitycanvas.jl")
include("graphics/blockcanvas.jl")
include("graphics/asciicanvas.jl")
include("graphics/dotcanvas.jl")
include("graphics/bargraphics.jl")
include("plot.jl")
include("interface/barplot.jl")
include("interface/histogram.jl")
include("interface/scatterplot.jl")
include("interface/lineplot.jl")
include("interface/stairs.jl")
include("interface/densityplot.jl")
include("interface/spy.jl")
include("deprecated.jl")

end


text:
""" Sign preserving 1D distance between nodes and a data sample x. """
function distance(nodes::Array{Float64,1},x::Float64)
    return x .- nodes
end

function αexp(s::Int,r::Float64=0.05)
    return exp(-r*s)
end

function αlin(s::Int,smax::Int)
    return 1-(s-1)/smax
end

function maxspread(data::AbstractArray)
    return maximum(data)-minimum(data)
end

function crenel(x::Real, Δ::Real)
    if x > -Δ && x < Δ
        return one(x)
    else
        return zero(x)
    end
end

function average_rounding_error(data::Array{Float64,1},nodes::Array{Float64,1})
    n = length(data)
    S = 0.0
    for i = 1:n
        S += minimum(abs.(distance(nodes,data[i])))/n
    end
    return S
end


text:
module NDTensors

using Random
using LinearAlgebra
using StaticArrays
using HDF5

#####################################
# DenseTensor and DiagTensor
#
include("tupletools.jl")
include("dims.jl")
include("tensorstorage.jl")
include("tensor.jl")
include("contraction_logic.jl")
include("dense.jl")
include("symmetric.jl")
include("linearalgebra.jl")
include("diag.jl")
include("combiner.jl")
include("truncate.jl")
include("svd.jl")

#####################################
# BlockSparseTensor
#
include("blocksparse/blockdims.jl")
include("blocksparse/blockoffsets.jl")
include("blocksparse/blocksparse.jl")
include("blocksparse/blocksparsetensor.jl")
include("blocksparse/diagblocksparse.jl")
include("blocksparse/combiner.jl")
include("blocksparse/linearalgebra.jl")

end # module NDTensors


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

mutable struct IoK8sApiCoordinationV1beta1LeaseSpec <: SwaggerModel
    acquireTime::Any # spec type: Union{ Nothing, IoK8sApimachineryPkgApisMetaV1MicroTime } # spec name: acquireTime
    holderIdentity::Any # spec type: Union{ Nothing, String } # spec name: holderIdentity
    leaseDurationSeconds::Any # spec type: Union{ Nothing, Int32 } # spec name: leaseDurationSeconds
    leaseTransitions::Any # spec type: Union{ Nothing, Int32 } # spec name: leaseTransitions
    renewTime::Any # spec type: Union{ Nothing, IoK8sApimachineryPkgApisMetaV1MicroTime } # spec name: renewTime

    function IoK8sApiCoordinationV1beta1LeaseSpec(;acquireTime=nothing, holderIdentity=nothing, leaseDurationSeconds=nothing, leaseTransitions=nothing, renewTime=nothing)
        o = new()
        validate_property(IoK8sApiCoordinationV1beta1LeaseSpec, Symbol("acquireTime"), acquireTime)
        setfield!(o, Symbol("acquireTime"), acquireTime)
        validate_property(IoK8sApiCoordinationV1beta1LeaseSpec, Symbol("holderIdentity"), holderIdentity)
        setfield!(o, Symbol("holderIdentity"), holderIdentity)
        validate_property(IoK8sApiCoordinationV1beta1LeaseSpec, Symbol("leaseDurationSeconds"), leaseDurationSeconds)
        setfield!(o, Symbol("leaseDurationSeconds"), leaseDurationSeconds)
        validate_property(IoK8sApiCoordinationV1beta1LeaseSpec, Symbol("leaseTransitions"), leaseTransitions)
        setfield!(o, Symbol("leaseTransitions"), leaseTransitions)
        validate_property(IoK8sApiCoordinationV1beta1LeaseSpec, Symbol("renewTime"), renewTime)
        setfield!(o, Symbol("renewTime"), renewTime)
        o
    end
end # type IoK8sApiCoordinationV1beta1LeaseSpec

const _property_map_IoK8sApiCoordinationV1beta1LeaseSpec = Dict{Symbol,Symbol}(Symbol("acquireTime")=>Symbol("acquireTime"), Symbol("holderIdentity")=>Symbol("holderIdentity"), Symbol("leaseDurationSeconds")=>Symbol("leaseDurationSeconds"), Symbol("leaseTransitions")=>Symbol("leaseTransitions"), Symbol("renewTime")=>Symbol("renewTime"))
const _property_types_IoK8sApiCoordinationV1beta1LeaseSpec = Dict{Symbol,String}(Symbol("acquireTime")=>"IoK8sApimachineryPkgApisMetaV1MicroTime", Symbol("holderIdentity")=>"String", Symbol("leaseDurationSeconds")=>"Int32", Symbol("leaseTransitions")=>"Int32", Symbol("renewTime")=>"IoK8sApimachineryPkgApisMetaV1MicroTime")
Base.propertynames(::Type{ IoK8sApiCoordinationV1beta1LeaseSpec }) = collect(keys(_property_map_IoK8sApiCoordinationV1beta1LeaseSpec))
Swagger.property_type(::Type{ IoK8sApiCoordinationV1beta1LeaseSpec }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_IoK8sApiCoordinationV1beta1LeaseSpec[name]))}
Swagger.field_name(::Type{ IoK8sApiCoordinationV1beta1LeaseSpec }, property_name::Symbol) =  _property_map_IoK8sApiCoordinationV1beta1LeaseSpec[property_name]

function check_required(o::IoK8sApiCoordinationV1beta1LeaseSpec)
    true
end

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


text:
using OpenCL, Transpiler

import Transpiler: cli
using Transpiler: GlobalPointer
import GPUArrays: GPUArray, unsafe_reinterpret, LocalMemory, gpu_sub2ind
using Sugar: to_tuple

import Base: pointer, similar, size, copy!, convert
using Base: RefValue

mutable struct CLArray{T, N} <: GPUArray{T, N}
    size::NTuple{N, Cuint}
    ptr::OwnedPtr{T}
end

# arguments are swapped to not override default constructor
function (::Type{CLArray{T, N}})(ptr::OwnedPtr{T}, size::NTuple{N, Integer}) where {T, N}
    arr = CLArray{T, N}(size, ptr)
    finalizer(arr, unsafe_free!)
    arr
end
size(x::CLArray) = Int.(x.size)
pointer(x::CLArray) = x.ptr
context(p::CLArray) = context(pointer(p))

# Avoid conflict with OpenCL.cl
module Shorthands
    using ..CLArrays: CLArray
    import Adapt: adapt, adapt_

    adapt_(::Type{<:CLArray}, xs::AbstractArray) = isbits(xs) ? xs : convert(CLArray, xs)

    cl(x) = adapt(CLArray{Float32}, x)

    export cl
end

function (::Type{CLArray{T, N}})(size::NTuple{N, Integer}, ctx::cl.Context = global_context()) where {T, N}
    # element type has different padding from cl type in julia
    # for fixedsize arrays we use vload/vstore, so we can use it packed
    clT = T #!Transpiler.is_fixedsize_array(T) ? cl.packed_convert(T) : T
    elems = prod(size)
    elems = elems == 0 ? 1 : elems # OpenCL can't allocate 0 sized buffers
    ptr = Mem.alloc(clT, elems, ctx)
    CLArray{clT, N}(ptr, size)
end

raw_print(msg::AbstractString...) =
    ccall(:write, Cssize_t, (Cint, Cstring, Csize_t), 1, join(msg), length(join(msg)))

similar(::Type{<: CLArray}, ::Type{T}, size::Base.Dims{N}) where {T, N} = CLArray{T, N}(size)

function unsafe_free!(a::CLArray)
    ptr = pointer(a)
    ctxid = context(ptr).id
    err = Mem.free(ptr)
    if err == cl.CL_SUCCESS
        Mem.current_allocated_mem[] -= sizeof(eltype(a)) * length(a)
    elseif err == cl.CL_INVALID_CONTEXT
        # ignore (log it!)
    else
        cl.@check err
    end
end

function unsafe_reinterpret(::Type{T}, A::CLArray{ET}, size::NTuple{N, Integer}) where {T, ET, N}
    ptr = pointer(A)
    Mem.retain(ptr) # we now have 2 finalizers for ptr, so it needs to be retained/increase refcount
    ptrt = OwnedPtr{T}(ptr)
    CLArray{T, N}(size, ptrt)
end

function copy!{T}(
        dest::Array{T}, d_offset::Integer,
        source::CLArray{T}, s_offset::Integer, amount::Integer
    )
    amount == 0 && return dest
    s_offset = (s_offset - 1) * sizeof(T)
    q = global_queue(source)
    # TODO unpack elements if they were converted
    unsafe_copy!(q, Ref(dest, d_offset), s_offset, pointer(source), amount * sizeof(T))
    dest
end

function copy!{T}(
        dest::CLArray{T}, d_offset::Integer,
        source::Array{T}, s_offset::Integer, amount::Integer
    )
    amount == 0 && return dest
    q = global_queue(dest)
    d_offset = (d_offset - 1) * sizeof(T)
    buff = pointer(dest)
    clT = eltype(buff)
    # element type has different padding from cl type in julia
    # for fixedsize arrays we use vload/vstore, so we can use it packed
    if sizeof(clT) != sizeof(T) && !Transpiler.is_fixedsize_array(T)
        # TODO only convert the range in the offset, or maybe convert elements and directly upload?
        # depends a bit on the overhead of cl_writebuffer
        source = map(cl.packed_convert, source)
    end
    unsafe_copy!(q, buff, d_offset, Ref(source, s_offset), amount * sizeof(clT))
    dest
end

function copy!{T}(
        dest::CLArray{T}, d_offset::Integer,
        src::CLArray{T}, s_offset::Integer, amount::Integer
    )
    amount == 0 && return dest
    q = global_queue(src)
    d_offset = (d_offset - 1) * sizeof(T)
    s_offset = (s_offset - 1) * sizeof(T)

    n_evts  = UInt(0)
    evt_ids = C_NULL
    ret_evt = Ref{cl.CL_event}()
    cl.@check cl.api.clEnqueueCopyBuffer(
        q.id, pointer(src), pointer(dest),
        s_offset, d_offset, amount * sizeof(T),
        n_evts, evt_ids, ret_evt
    )
    dest
end


text:
# Autogenerated wrapper script for librtlsdr_jll for x86_64-apple-darwin
export librtlsdr

using libusb_jll
JLLWrappers.@generate_wrapper_header("librtlsdr")
JLLWrappers.@declare_library_product(librtlsdr, "@rpath/librtlsdr.0.dylib")
function __init__()
    JLLWrappers.@generate_init_header(libusb_jll)
    JLLWrappers.@init_library_product(
        librtlsdr,
        "lib/librtlsdr.0.6.0.dylib",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md

using JuliaFEM
using JuliaFEM.Testing
using JuliaFEM.Preprocess

@testset "test projection" begin
    C = [
        2.0  1.0  0.0  0.0   0.0   0.0  0.0  0.0
        1.0  2.0  0.0  0.0   0.0   0.0  0.0  0.0
        0.0  0.0  2.0  1.0  -1.0  -2.0  0.0  0.0
        0.0  0.0  1.0  2.0  -2.0  -1.0  0.0  0.0
        0.0  0.0  0.0  0.0   0.0   0.0  0.0  0.0
        0.0  0.0  0.0  0.0   0.0   0.0  0.0  0.0
        0.0  0.0  0.0  0.0   0.0   0.0  0.0  0.0
        0.0  0.0  0.0  0.0   0.0   0.0  0.0  0.0]
    g = [3.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
    P, h = create_projection(sparse(C), g)
    P_expected = [
        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
        0.0  0.0  0.0  0.0  0.0  1.0  0.0  0.0
        0.0  0.0  0.0  0.0  1.0  0.0  0.0  0.0
        0.0  0.0  0.0  0.0  1.0  0.0  0.0  0.0
        0.0  0.0  0.0  0.0  0.0  1.0  0.0  0.0
        0.0  0.0  0.0  0.0  0.0  0.0  1.0  0.0
        0.0  0.0  0.0  0.0  0.0  0.0  0.0  1.0]
    h_expected = [1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
    @test isapprox(full(P), P_expected)
    @test isapprox(full(h), h_expected)
    nz = [5, 6, 7, 8]
    info("is P'P positive definite? ", isposdef(P[:,nz]'P[:,nz]))
    @test isposdef(P[:,nz]'P[:,nz])
end

@testset "test creating projection matrix from invertible problem" begin
    # simple 3 element poisson problem
    k = [1.0 -1.0; -1.0 1.0]
    K = zeros(4, 4)
    K[1:2,1:2] += k
    K[2:3,2:3] += k
    K[3:4,3:4] += k
    # first dof homogeneous bc, last dof u₄ = 1
    C = zeros(4, 4)
    C[1,1] = 1.0
    C[4,4] = 1.0
    g = zeros(4)
    g[1] = 0.0
    g[4] = 1.0
    P, h = create_projection(sparse(C), g, Val{:invertible})
    info("P = ")
    dump(full(P))
    P_expected = zeros(4, 4)
    P_expected[2,2] = P_expected[3,3] = 1.0
    @test isapprox(full(P), P_expected)
    #h_expected = [0.5, 1.0]
    #@test isapprox(h, h_expected)
end

@testset "projection between surfaces" begin
    # FIXME: creating mortar projection takes very long time.
    meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/joint.med"
    isfile(meshfile) || return
    mesh = aster_read_mesh(meshfile, "JOINT")

    # top
    bc1 = Problem(Dirichlet, "fixed1", 3, "displacement")
    bc1.elements = create_elements(mesh, "FIXED1")
    update!(bc1.elements, "displacement 1", 0.0)
    update!(bc1.elements, "displacement 2", 0.0)
    update!(bc1.elements, "displacement 3", 0.0)

    # bottom
    bc2 = Problem(Dirichlet, "fixed2", 3, "displacement")
    bc2.elements = create_elements(mesh, "FIXED2")
    update!(bc2.elements, "displacement 1", 0.0)
    update!(bc2.elements, "displacement 2", 0.0)
    update!(bc2.elements, "displacement 3", 0.0)

    # joint
    contact = Problem(Mortar, "joint", 3, "displacement")
    master_elements = create_elements(mesh, "BODY1_TO_BODY2")
    slave_elements = create_elements(mesh, "BODY2_TO_BODY1")
    update!(slave_elements, "master elements", master_elements)
    contact.elements = [master_elements; slave_elements]

    solver = Solver(Modal)
    push!(solver, bc1, bc2, contact)
    assemble!(solver)
    Kb, C1, C2, D, fb, g = get_boundary_assembly(solver)
    P, h = create_projection(C1, g)
end


text:
module LESbrary

using Statistics
using Printf

using OffsetArrays
using Glob
using JLD2

using Oceananigans.AbstractOperations
using Oceananigans.BoundaryConditions
using Oceananigans.TurbulenceClosures
using Oceananigans.Diagnostics
using Oceananigans.Fields
using Oceananigans.Operators
using Oceananigans.Grids
using Oceananigans.Utils

using Oceananigans: Face, Center
using Oceananigans.BuoyancyModels: g_Earth
using Oceananigans.Fields: xnodes, ynodes, znodes

include("Utils/Utils.jl")
include("FileManagement.jl")
include("TurbulenceStatistics/TurbulenceStatistics.jl")
include("NearSurfaceTurbulenceModels.jl")

end # module