text:
# Julia wrapper for header: gswteos-10.h
# Automatically generated using Clang.jl

function gsw_add_barrier(input_data, lon, lat, long_grid, lat_grid, dlong_grid, dlat_grid, output_data)
    ccall((:gsw_add_barrier, libgswteos), Cvoid, (Ptr{Cdouble}, Cdouble, Cdouble, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cdouble}), input_data, lon, lat, long_grid, lat_grid, dlong_grid, dlat_grid, output_data)
end

function gsw_add_mean(data_in, data_out)
    ccall((:gsw_add_mean, libgswteos), Cvoid, (Ptr{Cdouble}, Ptr{Cdouble}), data_in, data_out)
end

function gsw_adiabatic_lapse_rate_from_ct(sa, ct, p)
    ccall((:gsw_adiabatic_lapse_rate_from_ct, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_adiabatic_lapse_rate_ice(t, p)
    ccall((:gsw_adiabatic_lapse_rate_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_alpha(sa, ct, p)
    ccall((:gsw_alpha, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_alpha_on_beta(sa, ct, p)
    ccall((:gsw_alpha_on_beta, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_alpha_wrt_t_exact(sa, t, p)
    ccall((:gsw_alpha_wrt_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_alpha_wrt_t_ice(t, p)
    ccall((:gsw_alpha_wrt_t_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_beta_const_t_exact(sa, t, p)
    ccall((:gsw_beta_const_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_beta(sa, ct, p)
    ccall((:gsw_beta, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_cabbeling(sa, ct, p)
    ccall((:gsw_cabbeling, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_c_from_sp(sp, t, p)
    ccall((:gsw_c_from_sp, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sp, t, p)
end

function gsw_chem_potential_water_ice(t, p)
    ccall((:gsw_chem_potential_water_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_chem_potential_water_t_exact(sa, t, p)
    ccall((:gsw_chem_potential_water_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_cp_ice(t, p)
    ccall((:gsw_cp_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_cp_t_exact(sa, t, p)
    ccall((:gsw_cp_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_ct_first_derivatives(sa, pt, ct_sa, ct_pt)
    ccall((:gsw_ct_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, pt, ct_sa, ct_pt)
end

function gsw_ct_first_derivatives_wrt_t_exact(sa, t, p, ct_sa_wrt_t, ct_t_wrt_t, ct_p_wrt_t)
    ccall((:gsw_ct_first_derivatives_wrt_t_exact, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, t, p, ct_sa_wrt_t, ct_t_wrt_t, ct_p_wrt_t)
end

function gsw_ct_freezing(sa, p, saturation_fraction)
    ccall((:gsw_ct_freezing, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, p, saturation_fraction)
end

function gsw_ct_freezing_first_derivatives(sa, p, saturation_fraction, ctfreezing_sa, ctfreezing_p)
    ccall((:gsw_ct_freezing_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, saturation_fraction, ctfreezing_sa, ctfreezing_p)
end

function gsw_ct_freezing_first_derivatives_poly(sa, p, saturation_fraction, ctfreezing_sa, ctfreezing_p)
    ccall((:gsw_ct_freezing_first_derivatives_poly, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, saturation_fraction, ctfreezing_sa, ctfreezing_p)
end

function gsw_ct_freezing_poly(sa, p, saturation_fraction)
    ccall((:gsw_ct_freezing_poly, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, p, saturation_fraction)
end

function gsw_ct_from_enthalpy(sa, h, p)
    ccall((:gsw_ct_from_enthalpy, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, h, p)
end

function gsw_ct_from_enthalpy_exact(sa, h, p)
    ccall((:gsw_ct_from_enthalpy_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, h, p)
end

function gsw_ct_from_entropy(sa, entropy)
    ccall((:gsw_ct_from_entropy, libgswteos), Cdouble, (Cdouble, Cdouble), sa, entropy)
end

function gsw_ct_from_pt(sa, pt)
    ccall((:gsw_ct_from_pt, libgswteos), Cdouble, (Cdouble, Cdouble), sa, pt)
end

function gsw_ct_from_rho(rho, sa, p, ct, ct_multiple)
    ccall((:gsw_ct_from_rho, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), rho, sa, p, ct, ct_multiple)
end

function gsw_ct_from_t(sa, t, p)
    ccall((:gsw_ct_from_t, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_ct_maxdensity(sa, p)
    ccall((:gsw_ct_maxdensity, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_ct_second_derivatives(sa, pt, ct_sa_sa, ct_sa_pt, ct_pt_pt)
    ccall((:gsw_ct_second_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, pt, ct_sa_sa, ct_sa_pt, ct_pt_pt)
end

function gsw_deltasa_atlas(p, lon, lat)
    ccall((:gsw_deltasa_atlas, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), p, lon, lat)
end

function gsw_deltasa_from_sp(sp, p, lon, lat)
    ccall((:gsw_deltasa_from_sp, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sp, p, lon, lat)
end

function gsw_dilution_coefficient_t_exact(sa, t, p)
    ccall((:gsw_dilution_coefficient_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_dynamic_enthalpy(sa, ct, p)
    ccall((:gsw_dynamic_enthalpy, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_enthalpy_ct_exact(sa, ct, p)
    ccall((:gsw_enthalpy_ct_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_enthalpy_diff(sa, ct, p_shallow, p_deep)
    ccall((:gsw_enthalpy_diff, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sa, ct, p_shallow, p_deep)
end

function gsw_enthalpy(sa, ct, p)
    ccall((:gsw_enthalpy, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_enthalpy_first_derivatives_ct_exact(sa, ct, p, h_sa, h_ct)
    ccall((:gsw_enthalpy_first_derivatives_ct_exact, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, h_sa, h_ct)
end

function gsw_enthalpy_first_derivatives(sa, ct, p, h_sa, h_ct)
    ccall((:gsw_enthalpy_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, h_sa, h_ct)
end

function gsw_enthalpy_ice(t, p)
    ccall((:gsw_enthalpy_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_enthalpy_second_derivatives_ct_exact(sa, ct, p, h_sa_sa, h_sa_ct, h_ct_ct)
    ccall((:gsw_enthalpy_second_derivatives_ct_exact, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, h_sa_sa, h_sa_ct, h_ct_ct)
end

function gsw_enthalpy_second_derivatives(sa, ct, p, h_sa_sa, h_sa_ct, h_ct_ct)
    ccall((:gsw_enthalpy_second_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, h_sa_sa, h_sa_ct, h_ct_ct)
end

function gsw_enthalpy_sso_0(p)
    ccall((:gsw_enthalpy_sso_0, libgswteos), Cdouble, (Cdouble,), p)
end

function gsw_enthalpy_t_exact(sa, t, p)
    ccall((:gsw_enthalpy_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_entropy_first_derivatives(sa, ct, eta_sa, eta_ct)
    ccall((:gsw_entropy_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, eta_sa, eta_ct)
end

function gsw_entropy_from_ct(sa, ct)
    ccall((:gsw_entropy_from_ct, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_entropy_from_pt(sa, pt)
    ccall((:gsw_entropy_from_pt, libgswteos), Cdouble, (Cdouble, Cdouble), sa, pt)
end

function gsw_entropy_from_t(sa, t, p)
    ccall((:gsw_entropy_from_t, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_entropy_ice(t, p)
    ccall((:gsw_entropy_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_entropy_part(sa, t, p)
    ccall((:gsw_entropy_part, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_entropy_part_zerop(sa, pt0)
    ccall((:gsw_entropy_part_zerop, libgswteos), Cdouble, (Cdouble, Cdouble), sa, pt0)
end

function gsw_entropy_second_derivatives(sa, ct, eta_sa_sa, eta_sa_ct, eta_ct_ct)
    ccall((:gsw_entropy_second_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, eta_sa_sa, eta_sa_ct, eta_ct_ct)
end

function gsw_fdelta(p, lon, lat)
    ccall((:gsw_fdelta, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), p, lon, lat)
end

function gsw_frazil_properties(sa_bulk, h_bulk, p, sa_final, ct_final, w_ih_final)
    ccall((:gsw_frazil_properties, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa_bulk, h_bulk, p, sa_final, ct_final, w_ih_final)
end

function gsw_frazil_properties_potential(sa_bulk, h_pot_bulk, p, sa_final, ct_final, w_ih_final)
    ccall((:gsw_frazil_properties_potential, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa_bulk, h_pot_bulk, p, sa_final, ct_final, w_ih_final)
end

function gsw_frazil_properties_potential_poly(sa_bulk, h_pot_bulk, p, sa_final, ct_final, w_ih_final)
    ccall((:gsw_frazil_properties_potential_poly, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa_bulk, h_pot_bulk, p, sa_final, ct_final, w_ih_final)
end

function gsw_frazil_ratios_adiabatic(sa, p, w_ih, dsa_dct_frazil, dsa_dp_frazil, dct_dp_frazil)
    ccall((:gsw_frazil_ratios_adiabatic, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, w_ih, dsa_dct_frazil, dsa_dp_frazil, dct_dp_frazil)
end

function gsw_frazil_ratios_adiabatic_poly(sa, p, w_ih, dsa_dct_frazil, dsa_dp_frazil, dct_dp_frazil)
    ccall((:gsw_frazil_ratios_adiabatic_poly, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, w_ih, dsa_dct_frazil, dsa_dp_frazil, dct_dp_frazil)
end

function gsw_geo_strf_dyn_height(sa, ct, p, p_ref, n_levels, dyn_height)
    ccall((:gsw_geo_strf_dyn_height, libgswteos), Ptr{Cdouble}, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cdouble, Cint, Ptr{Cdouble}), sa, ct, p, p_ref, n_levels, dyn_height)
end

function gsw_geo_strf_dyn_height_1(sa, ct, p, p_ref, n_levels, dyn_height, max_dp_i, interp_method)
    ccall((:gsw_geo_strf_dyn_height_1, libgswteos), Cint, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cdouble, Cint, Ptr{Cdouble}, Cdouble, Cint), sa, ct, p, p_ref, n_levels, dyn_height, max_dp_i, interp_method)
end

function gsw_geo_strf_dyn_height_pc(sa, ct, delta_p, n_levels, geo_strf_dyn_height_pc, p_mid)
    ccall((:gsw_geo_strf_dyn_height_pc, libgswteos), Ptr{Cdouble}, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, delta_p, n_levels, geo_strf_dyn_height_pc, p_mid)
end

function gsw_gibbs_ice(nt, np, t, p)
    ccall((:gsw_gibbs_ice, libgswteos), Cdouble, (Cint, Cint, Cdouble, Cdouble), nt, np, t, p)
end

function gsw_gibbs_ice_part_t(t, p)
    ccall((:gsw_gibbs_ice_part_t, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_gibbs_ice_pt0(pt0)
    ccall((:gsw_gibbs_ice_pt0, libgswteos), Cdouble, (Cdouble,), pt0)
end

function gsw_gibbs_ice_pt0_pt0(pt0)
    ccall((:gsw_gibbs_ice_pt0_pt0, libgswteos), Cdouble, (Cdouble,), pt0)
end

function gsw_gibbs(ns, nt, np, sa, t, p)
    ccall((:gsw_gibbs, libgswteos), Cdouble, (Cint, Cint, Cint, Cdouble, Cdouble, Cdouble), ns, nt, np, sa, t, p)
end

function gsw_gibbs_pt0_pt0(sa, pt0)
    ccall((:gsw_gibbs_pt0_pt0, libgswteos), Cdouble, (Cdouble, Cdouble), sa, pt0)
end

function gsw_grav(lat, p)
    ccall((:gsw_grav, libgswteos), Cdouble, (Cdouble, Cdouble), lat, p)
end

function gsw_helmholtz_energy_ice(t, p)
    ccall((:gsw_helmholtz_energy_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_hill_ratio_at_sp2(t)
    ccall((:gsw_hill_ratio_at_sp2, libgswteos), Cdouble, (Cdouble,), t)
end

function gsw_ice_fraction_to_freeze_seawater(sa, ct, p, t_ih, sa_freeze, ct_freeze, w_ih)
    ccall((:gsw_ice_fraction_to_freeze_seawater, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, t_ih, sa_freeze, ct_freeze, w_ih)
end

function gsw_internal_energy(sa, ct, p)
    ccall((:gsw_internal_energy, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_internal_energy_ice(t, p)
    ccall((:gsw_internal_energy_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_ipv_vs_fnsquared_ratio(sa, ct, p, p_ref, nz, ipv_vs_fnsquared_ratio, p_mid)
    ccall((:gsw_ipv_vs_fnsquared_ratio, libgswteos), Cvoid, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cdouble, Cint, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, p_ref, nz, ipv_vs_fnsquared_ratio, p_mid)
end

function gsw_kappa_const_t_ice(t, p)
    ccall((:gsw_kappa_const_t_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_kappa(sa, ct, p)
    ccall((:gsw_kappa, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_kappa_ice(t, p)
    ccall((:gsw_kappa_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_kappa_t_exact(sa, t, p)
    ccall((:gsw_kappa_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_latentheat_evap_ct(sa, ct)
    ccall((:gsw_latentheat_evap_ct, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_latentheat_evap_t(sa, t)
    ccall((:gsw_latentheat_evap_t, libgswteos), Cdouble, (Cdouble, Cdouble), sa, t)
end

function gsw_latentheat_melting(sa, p)
    ccall((:gsw_latentheat_melting, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_linear_interp_sa_ct(sa, ct, p, np, p_i, npi, sa_i, ct_i)
    ccall((:gsw_linear_interp_sa_ct, libgswteos), Cvoid, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, np, p_i, npi, sa_i, ct_i)
end

function gsw_melting_ice_equilibrium_sa_ct_ratio(sa, p)
    ccall((:gsw_melting_ice_equilibrium_sa_ct_ratio, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_melting_ice_equilibrium_sa_ct_ratio_poly(sa, p)
    ccall((:gsw_melting_ice_equilibrium_sa_ct_ratio_poly, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_melting_ice_into_seawater(sa, ct, p, w_ih, t_ih, sa_final, ct_final, w_ih_final)
    ccall((:gsw_melting_ice_into_seawater, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, w_ih, t_ih, sa_final, ct_final, w_ih_final)
end

function gsw_melting_ice_sa_ct_ratio(sa, ct, p, t_ih)
    ccall((:gsw_melting_ice_sa_ct_ratio, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sa, ct, p, t_ih)
end

function gsw_melting_ice_sa_ct_ratio_poly(sa, ct, p, t_ih)
    ccall((:gsw_melting_ice_sa_ct_ratio_poly, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sa, ct, p, t_ih)
end

function gsw_melting_seaice_equilibrium_sa_ct_ratio(sa, p)
    ccall((:gsw_melting_seaice_equilibrium_sa_ct_ratio, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_melting_seaice_equilibrium_sa_ct_ratio_poly(sa, p)
    ccall((:gsw_melting_seaice_equilibrium_sa_ct_ratio_poly, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_melting_seaice_into_seawater(sa, ct, p, w_seaice, sa_seaice, t_seaice, sa_final, ct_final)
    ccall((:gsw_melting_seaice_into_seawater, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, w_seaice, sa_seaice, t_seaice, sa_final, ct_final)
end

function gsw_melting_seaice_sa_ct_ratio(sa, ct, p, sa_seaice, t_seaice)
    ccall((:gsw_melting_seaice_sa_ct_ratio, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble, Cdouble), sa, ct, p, sa_seaice, t_seaice)
end

function gsw_melting_seaice_sa_ct_ratio_poly(sa, ct, p, sa_seaice, t_seaice)
    ccall((:gsw_melting_seaice_sa_ct_ratio_poly, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble, Cdouble), sa, ct, p, sa_seaice, t_seaice)
end

function gsw_nsquared(sa, ct, p, lat, nz, n2, p_mid)
    ccall((:gsw_nsquared, libgswteos), Cvoid, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, lat, nz, n2, p_mid)
end

function gsw_o2sol(sa, ct, p, lon, lat)
    ccall((:gsw_o2sol, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble, Cdouble), sa, ct, p, lon, lat)
end

function gsw_o2sol_sp_pt(sp, pt)
    ccall((:gsw_o2sol_sp_pt, libgswteos), Cdouble, (Cdouble, Cdouble), sp, pt)
end

function gsw_pot_enthalpy_from_pt_ice(pt0_ice)
    ccall((:gsw_pot_enthalpy_from_pt_ice, libgswteos), Cdouble, (Cdouble,), pt0_ice)
end

function gsw_pot_enthalpy_from_pt_ice_poly(pt0_ice)
    ccall((:gsw_pot_enthalpy_from_pt_ice_poly, libgswteos), Cdouble, (Cdouble,), pt0_ice)
end

function gsw_pot_enthalpy_ice_freezing(sa, p)
    ccall((:gsw_pot_enthalpy_ice_freezing, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_pot_enthalpy_ice_freezing_first_derivatives(sa, p, pot_enthalpy_ice_freezing_sa, pot_enthalpy_ice_freezing_p)
    ccall((:gsw_pot_enthalpy_ice_freezing_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, pot_enthalpy_ice_freezing_sa, pot_enthalpy_ice_freezing_p)
end

function gsw_pot_enthalpy_ice_freezing_first_derivatives_poly(sa, p, pot_enthalpy_ice_freezing_sa, pot_enthalpy_ice_freezing_p)
    ccall((:gsw_pot_enthalpy_ice_freezing_first_derivatives_poly, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, pot_enthalpy_ice_freezing_sa, pot_enthalpy_ice_freezing_p)
end

function gsw_pot_enthalpy_ice_freezing_poly(sa, p)
    ccall((:gsw_pot_enthalpy_ice_freezing_poly, libgswteos), Cdouble, (Cdouble, Cdouble), sa, p)
end

function gsw_pot_rho_t_exact(sa, t, p, p_ref)
    ccall((:gsw_pot_rho_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sa, t, p, p_ref)
end

function gsw_pressure_coefficient_ice(t, p)
    ccall((:gsw_pressure_coefficient_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_pressure_freezing_ct(sa, ct, saturation_fraction)
    ccall((:gsw_pressure_freezing_ct, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, saturation_fraction)
end

function gsw_pt0_cold_ice_poly(pot_enthalpy_ice)
    ccall((:gsw_pt0_cold_ice_poly, libgswteos), Cdouble, (Cdouble,), pot_enthalpy_ice)
end

function gsw_pt0_from_t(sa, t, p)
    ccall((:gsw_pt0_from_t, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_pt0_from_t_ice(t, p)
    ccall((:gsw_pt0_from_t_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_pt_first_derivatives(sa, ct, pt_sa, pt_ct)
    ccall((:gsw_pt_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, pt_sa, pt_ct)
end

function gsw_pt_from_ct(sa, ct)
    ccall((:gsw_pt_from_ct, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_pt_from_entropy(sa, entropy)
    ccall((:gsw_pt_from_entropy, libgswteos), Cdouble, (Cdouble, Cdouble), sa, entropy)
end

function gsw_pt_from_pot_enthalpy_ice(pot_enthalpy_ice)
    ccall((:gsw_pt_from_pot_enthalpy_ice, libgswteos), Cdouble, (Cdouble,), pot_enthalpy_ice)
end

function gsw_pt_from_pot_enthalpy_ice_poly_dh(pot_enthalpy_ice)
    ccall((:gsw_pt_from_pot_enthalpy_ice_poly_dh, libgswteos), Cdouble, (Cdouble,), pot_enthalpy_ice)
end

function gsw_pt_from_pot_enthalpy_ice_poly(pot_enthalpy_ice)
    ccall((:gsw_pt_from_pot_enthalpy_ice_poly, libgswteos), Cdouble, (Cdouble,), pot_enthalpy_ice)
end

function gsw_pt_from_t(sa, t, p, p_ref)
    ccall((:gsw_pt_from_t, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sa, t, p, p_ref)
end

function gsw_pt_from_t_ice(t, p, p_ref)
    ccall((:gsw_pt_from_t_ice, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), t, p, p_ref)
end

function gsw_pt_second_derivatives(sa, ct, pt_sa_sa, pt_sa_ct, pt_ct_ct)
    ccall((:gsw_pt_second_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, pt_sa_sa, pt_sa_ct, pt_ct_ct)
end

function gsw_rho_alpha_beta(sa, ct, p, rho, alpha, beta)
    ccall((:gsw_rho_alpha_beta, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, rho, alpha, beta)
end

function gsw_rho(sa, ct, p)
    ccall((:gsw_rho, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_rho_first_derivatives(sa, ct, p, drho_dsa, drho_dct, drho_dp)
    ccall((:gsw_rho_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, drho_dsa, drho_dct, drho_dp)
end

function gsw_rho_first_derivatives_wrt_enthalpy(sa, ct, p, rho_sa, rho_h)
    ccall((:gsw_rho_first_derivatives_wrt_enthalpy, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, rho_sa, rho_h)
end

function gsw_rho_ice(t, p)
    ccall((:gsw_rho_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_rho_second_derivatives(sa, ct, p, rho_sa_sa, rho_sa_ct, rho_ct_ct, rho_sa_p, rho_ct_p)
    ccall((:gsw_rho_second_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, rho_sa_sa, rho_sa_ct, rho_ct_ct, rho_sa_p, rho_ct_p)
end

function gsw_rho_second_derivatives_wrt_enthalpy(sa, ct, p, rho_sa_sa, rho_sa_h, rho_h_h)
    ccall((:gsw_rho_second_derivatives_wrt_enthalpy, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, rho_sa_sa, rho_sa_h, rho_h_h)
end

function gsw_rho_t_exact(sa, t, p)
    ccall((:gsw_rho_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_rr68_interp_sa_ct(sa, ct, p, mp, p_i, mp_i, sa_i, ct_i)
    ccall((:gsw_rr68_interp_sa_ct, libgswteos), Cvoid, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, mp, p_i, mp_i, sa_i, ct_i)
end

function gsw_saar(p, lon, lat)
    ccall((:gsw_saar, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), p, lon, lat)
end

function gsw_sa_freezing_estimate(p, saturation_fraction, ct, t)
    ccall((:gsw_sa_freezing_estimate, libgswteos), Cdouble, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), p, saturation_fraction, ct, t)
end

function gsw_sa_freezing_from_ct(ct, p, saturation_fraction)
    ccall((:gsw_sa_freezing_from_ct, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), ct, p, saturation_fraction)
end

function gsw_sa_freezing_from_ct_poly(ct, p, saturation_fraction)
    ccall((:gsw_sa_freezing_from_ct_poly, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), ct, p, saturation_fraction)
end

function gsw_sa_freezing_from_t(t, p, saturation_fraction)
    ccall((:gsw_sa_freezing_from_t, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), t, p, saturation_fraction)
end

function gsw_sa_freezing_from_t_poly(t, p, saturation_fraction)
    ccall((:gsw_sa_freezing_from_t_poly, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), t, p, saturation_fraction)
end

function gsw_sa_from_rho(rho, ct, p)
    ccall((:gsw_sa_from_rho, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), rho, ct, p)
end

function gsw_sa_from_sp_baltic(sp, lon, lat)
    ccall((:gsw_sa_from_sp_baltic, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sp, lon, lat)
end

function gsw_sa_from_sp(sp, p, lon, lat)
    ccall((:gsw_sa_from_sp, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sp, p, lon, lat)
end

function gsw_sa_from_sstar(sstar, p, lon, lat)
    ccall((:gsw_sa_from_sstar, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sstar, p, lon, lat)
end

function gsw_sa_p_inrange(sa, p)
    ccall((:gsw_sa_p_inrange, libgswteos), Cint, (Cdouble, Cdouble), sa, p)
end

function gsw_seaice_fraction_to_freeze_seawater(sa, ct, p, sa_seaice, t_seaice, sa_freeze, ct_freeze, w_seaice)
    ccall((:gsw_seaice_fraction_to_freeze_seawater, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, sa_seaice, t_seaice, sa_freeze, ct_freeze, w_seaice)
end

function gsw_sigma0(sa, ct)
    ccall((:gsw_sigma0, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_sigma1(sa, ct)
    ccall((:gsw_sigma1, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_sigma2(sa, ct)
    ccall((:gsw_sigma2, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_sigma3(sa, ct)
    ccall((:gsw_sigma3, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_sigma4(sa, ct)
    ccall((:gsw_sigma4, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_sound_speed(sa, ct, p)
    ccall((:gsw_sound_speed, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_sound_speed_ice(t, p)
    ccall((:gsw_sound_speed_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_sound_speed_t_exact(sa, t, p)
    ccall((:gsw_sound_speed_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_specvol_alpha_beta(sa, ct, p, specvol, alpha, beta)
    ccall((:gsw_specvol_alpha_beta, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, specvol, alpha, beta)
end

function gsw_specvol_anom_standard(sa, ct, p)
    ccall((:gsw_specvol_anom_standard, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_specvol(sa, ct, p)
    ccall((:gsw_specvol, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_specvol_first_derivatives(sa, ct, p, v_sa, v_ct, v_p)
    ccall((:gsw_specvol_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, v_sa, v_ct, v_p)
end

function gsw_specvol_first_derivatives_wrt_enthalpy(sa, ct, p, v_sa, v_h)
    ccall((:gsw_specvol_first_derivatives_wrt_enthalpy, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, v_sa, v_h)
end

function gsw_specvol_ice(t, p)
    ccall((:gsw_specvol_ice, libgswteos), Cdouble, (Cdouble, Cdouble), t, p)
end

function gsw_specvol_second_derivatives(sa, ct, p, v_sa_sa, v_sa_ct, v_ct_ct, v_sa_p, v_ct_p)
    ccall((:gsw_specvol_second_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, v_sa_sa, v_sa_ct, v_ct_ct, v_sa_p, v_ct_p)
end

function gsw_specvol_second_derivatives_wrt_enthalpy(sa, ct, p, v_sa_sa, v_sa_h, v_h_h)
    ccall((:gsw_specvol_second_derivatives_wrt_enthalpy, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, v_sa_sa, v_sa_h, v_h_h)
end

function gsw_specvol_sso_0(p)
    ccall((:gsw_specvol_sso_0, libgswteos), Cdouble, (Cdouble,), p)
end

function gsw_specvol_t_exact(sa, t, p)
    ccall((:gsw_specvol_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_sp_from_c(c, t, p)
    ccall((:gsw_sp_from_c, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), c, t, p)
end

function gsw_sp_from_sa_baltic(sa, lon, lat)
    ccall((:gsw_sp_from_sa_baltic, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, lon, lat)
end

function gsw_sp_from_sa(sa, p, lon, lat)
    ccall((:gsw_sp_from_sa, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sa, p, lon, lat)
end

function gsw_sp_from_sk(sk)
    ccall((:gsw_sp_from_sk, libgswteos), Cdouble, (Cdouble,), sk)
end

function gsw_sp_from_sr(sr)
    ccall((:gsw_sp_from_sr, libgswteos), Cdouble, (Cdouble,), sr)
end

function gsw_sp_from_sstar(sstar, p, lon, lat)
    ccall((:gsw_sp_from_sstar, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sstar, p, lon, lat)
end

function gsw_sp_salinometer(rt, t)
    ccall((:gsw_sp_salinometer, libgswteos), Cdouble, (Cdouble, Cdouble), rt, t)
end

function gsw_spiciness0(sa, ct)
    ccall((:gsw_spiciness0, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_spiciness1(sa, ct)
    ccall((:gsw_spiciness1, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_spiciness2(sa, ct)
    ccall((:gsw_spiciness2, libgswteos), Cdouble, (Cdouble, Cdouble), sa, ct)
end

function gsw_sr_from_sp(sp)
    ccall((:gsw_sr_from_sp, libgswteos), Cdouble, (Cdouble,), sp)
end

function gsw_sstar_from_sa(sa, p, lon, lat)
    ccall((:gsw_sstar_from_sa, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sa, p, lon, lat)
end

function gsw_sstar_from_sp(sp, p, lon, lat)
    ccall((:gsw_sstar_from_sp, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), sp, p, lon, lat)
end

function gsw_t_deriv_chem_potential_water_t_exact(sa, t, p)
    ccall((:gsw_t_deriv_chem_potential_water_t_exact, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, t, p)
end

function gsw_t_freezing(sa, p, saturation_fraction)
    ccall((:gsw_t_freezing, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, p, saturation_fraction)
end

function gsw_t_freezing_first_derivatives_poly(sa, p, saturation_fraction, tfreezing_sa, tfreezing_p)
    ccall((:gsw_t_freezing_first_derivatives_poly, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, saturation_fraction, tfreezing_sa, tfreezing_p)
end

function gsw_t_freezing_first_derivatives(sa, p, saturation_fraction, tfreezing_sa, tfreezing_p)
    ccall((:gsw_t_freezing_first_derivatives, libgswteos), Cvoid, (Cdouble, Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), sa, p, saturation_fraction, tfreezing_sa, tfreezing_p)
end

function gsw_t_freezing_poly(sa, p, saturation_fraction)
    ccall((:gsw_t_freezing_poly, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, p, saturation_fraction)
end

function gsw_t_from_ct(sa, ct, p)
    ccall((:gsw_t_from_ct, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_t_from_pt0_ice(pt0_ice, p)
    ccall((:gsw_t_from_pt0_ice, libgswteos), Cdouble, (Cdouble, Cdouble), pt0_ice, p)
end

function gsw_thermobaric(sa, ct, p)
    ccall((:gsw_thermobaric, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble), sa, ct, p)
end

function gsw_turner_rsubrho(sa, ct, p, nz, tu, rsubrho, p_mid)
    ccall((:gsw_turner_rsubrho, libgswteos), Cvoid, (Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), sa, ct, p, nz, tu, rsubrho, p_mid)
end

function gsw_util_indx(x, n, z)
    ccall((:gsw_util_indx, libgswteos), Cint, (Ptr{Cdouble}, Cint, Cdouble), x, n, z)
end

function gsw_util_interp1q_int(nx, x, iy, nxi, x_i, y_i)
    ccall((:gsw_util_interp1q_int, libgswteos), Ptr{Cdouble}, (Cint, Ptr{Cdouble}, Ptr{Cint}, Cint, Ptr{Cdouble}, Ptr{Cdouble}), nx, x, iy, nxi, x_i, y_i)
end

function gsw_util_linear_interp(nx, x, ny, y, nxi, x_i, y_i)
    ccall((:gsw_util_linear_interp, libgswteos), Ptr{Cdouble}, (Cint, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Ptr{Cdouble}), nx, x, ny, y, nxi, x_i, y_i)
end

function gsw_util_sort_real(rarray, nx, iarray)
    ccall((:gsw_util_sort_real, libgswteos), Cvoid, (Ptr{Cdouble}, Cint, Ptr{Cint}), rarray, nx, iarray)
end

function gsw_util_xinterp1(x, y, n, x0)
    ccall((:gsw_util_xinterp1, libgswteos), Cdouble, (Ptr{Cdouble}, Ptr{Cdouble}, Cint, Cdouble), x, y, n, x0)
end

function gsw_util_pchip_interp(x, y, n, xi, yi, ni)
    ccall((:gsw_util_pchip_interp, libgswteos), Cint, (Ptr{Cdouble}, Ptr{Cdouble}, Cint, Ptr{Cdouble}, Ptr{Cdouble}, Cint), x, y, n, xi, yi, ni)
end

function gsw_z_from_p(p, lat, geo_strf_dyn_height, sea_surface_geopotential)
    ccall((:gsw_z_from_p, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), p, lat, geo_strf_dyn_height, sea_surface_geopotential)
end

function gsw_p_from_z(z, lat, geo_strf_dyn_height, sea_surface_geopotential)
    ccall((:gsw_p_from_z, libgswteos), Cdouble, (Cdouble, Cdouble, Cdouble, Cdouble), z, lat, geo_strf_dyn_height, sea_surface_geopotential)
end


text:
# Abstract supertype for DG-type solvers
# `POLYDEG` corresponds to `N` in the school of Kopriva
abstract type AbstractDg{NDIMS, POLYDEG, MeshType} <: AbstractSolver{NDIMS} end

@inline Base.ndims(dg::AbstractDg) = ndims(equations(dg))

# Return polynomial degree for a DG solver
@inline polydeg(::AbstractDg{NDIMS, POLYDEG}) where {NDIMS, POLYDEG} = POLYDEG

# Return number of nodes in one direction
@inline nnodes(::AbstractDg{NDIMS, POLYDEG}) where {NDIMS, POLYDEG} = POLYDEG + 1

# Return system of equations instance for a DG solver
@inline equations(dg::AbstractDg) = dg.equations

# Return number of variables for the system of equations in use
@inline nvariables(dg::AbstractDg) = nvariables(equations(dg))

# Return number of degrees of freedom
@inline ndofs(dg::AbstractDg) = dg.n_elements * nnodes(dg)^ndims(dg)

@inline uses_mpi(::AbstractDg{NDIMS, POLYDEG, TreeMesh{ParallelTree{NDIMS}}}) where {NDIMS, POLYDEG}= Val(true)
@inline uses_mpi(::AbstractDg{NDIMS, POLYDEG, TreeMesh{SerialTree{NDIMS}}}) where {NDIMS, POLYDEG} = Val(false)

"""
    get_node_coords(x, dg::AbstractDg, indices...)

Return an `ndims(dg)`-dimensional `SVector` for the DG node specified via the `i, j, k, element_id` indices (3D) or `i, j, element_id` indices (2D).
"""
@inline get_node_coords(x, dg::AbstractDg, indices...) = SVector(ntuple(idx -> x[idx, indices...], ndims(dg)))

"""
    get_node_vars(u, dg::AbstractDg, indices...)

Return an `nvariables(dg)`-dimensional `SVector` of the conservative variables for the DG node specified via the `i, j, k, element_id` indices (3D) or `i, j, element_id` indices (2D).
"""
@inline get_node_vars(u, dg::AbstractDg, indices...) = SVector(ntuple(v -> u[v, indices...], nvariables(dg)))

@inline function get_surface_node_vars(u, dg::AbstractDg, indices...)
  u_ll = SVector(ntuple(v -> u[1, v, indices...], nvariables(dg)))
  u_rr = SVector(ntuple(v -> u[2, v, indices...], nvariables(dg)))
  return u_ll, u_rr
end

@inline function set_node_vars!(u, u_node, ::AbstractDg, indices...)
  for v in eachindex(u_node)
    u[v, indices...] = u_node[v]
  end
  return nothing
end

@inline function add_to_node_vars!(u, u_node, ::AbstractDg, indices...)
  for v in eachindex(u_node)
    u[v, indices...] += u_node[v]
  end
  return nothing
end

# Include utilities
include("interpolation.jl")
include("l2projection.jl")

# Include 1D implementation
include("1d/containers.jl")
include("1d/dg.jl")
include("1d/amr.jl")

# Include 2D implementation
include("2d/containers.jl")
include("2d/dg.jl")
include("2d/amr.jl")
include("2d/parallel.jl")

# Include 3D implementation
include("3d/containers.jl")
include("3d/dg.jl")
include("3d/amr.jl")

ext: jl


text:
using UnicodePlots
using Markdown
import Markdown: MD, Paragraph, plain

function main()
  docs_url = "https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs"
  ver = "2.x"

  exs = (
    lineplot1 = ("Basic Canvas", """
      using UnicodePlots
      plt = lineplot([-1, 2, 3, 7], [-1, 2, 9, 4],
                     title="Example Plot", name="my line", xlabel="x", ylabel="y", border=:dotted)
      """),
    lineplot2 = ("Basic Canvas", """
      lineplot([-1, 2, 3, 7], [-1, 2, 9, 4],
               title="Example Plot", name="my line",
               xlabel="x", ylabel="y", canvas=DotCanvas, border=:ascii)
      """),
    lineplot3 = ("Basic Canvas", """lineplot!(plt, [0, 4, 8], [10, 1, 10], color=:blue, name="other line")"""),
    scatterplot1 = ("Scatterplot", """scatterplot(randn(50), randn(50), title="My Scatterplot", border=:dotted)"""),
    scatterplot2 = ("Scatterplot", "scatterplot(1:10, 1:10, xscale=:log10, yscale=:ln, border=:dotted)"),
    scatterplot3 = ("Scatterplot", "scatterplot(1:10, 1:10, xscale=:log10, yscale=:ln, border=:dotted, unicode_exponent=false)"),
    scatterplot4 = ("Scatterplot", """
      scatterplot([1, 2, 3], [3, 4, 1],
                  marker=[:circle, '😀', "∫"], color=[:red, nothing, :yellow], border=:dotted)
      """),
    lineplot4 = ("Lineplot", """lineplot([1, 2, 7], [9, -6, 8], title="My Lineplot", border=:dotted)"""),
    lineplot5 = ("Lineplot", "plt = lineplot([cos, sin], -π/2, 2π, border=:dotted)"),
    lineplot6 = ("Lineplot", """lineplot!(plt, -.5, .2, name="line")"""),
    stairs1 = ("Staircase", """
      # supported style are :pre and :post
      stairs([1, 2, 4, 7, 8], [1, 3, 4, 2, 7],
             color=:red, style=:post, title="My Staircase Plot", border=:dotted)
      """),
    barplot1 = ("Barplot", """
      barplot(["Paris", "New York", "Moskau", "Madrid"],
              [2.244, 8.406, 11.92, 3.165],
              title="Population")
      """),
    histogram1 = ("Histogram", "histogram(randn(1000) .* .1, nbins=15, closed=:left)"),
    histogram2 = ("Histogram", "histogram(randn(1000) .* .1, nbins=15, closed=:right, xscale=:log10)"),
    boxplot1 = ("Boxplot", "boxplot([1, 3, 3, 4, 6, 10])"),
    boxplot2 = ("Boxplot", """
      boxplot(["one", "two"],
              [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7, 8, 9]],
              title="Grouped Boxplot", xlabel="x")
      """),
    spy1 = ("Spy", "using SparseArrays\nspy(sprandn(50, 120, .05), border=:dotted)"),
    spy2 = ("Spy", "using SparseArrays\nspy(sprandn(50, 120, .9), show_zeros=true, border=:dotted)"),
    densityplot1 = ("Densityplot", """
      plt = densityplot(randn(1000), randn(1000))
      densityplot!(plt, randn(1000) .+ 2, randn(1000) .+ 2)
      """),
    contourplot1 = ("Contourplot", "contourplot(-3:.01:3, -7:.01:3, (x, y) -> exp(-(x / 2)^2 - ((y + 2) / 4)^2), border=:dotted)"),
    heatmap1 = ("Heatmap", """heatmap(repeat(collect(0:10)', outer=(11, 1)), zlabel="z")"""),
    heatmap2 = ("Heatmap", "heatmap(collect(0:30) * collect(0:30)', xfact=.1, yfact=.1, xoffset=-1.5, colormap=:inferno)"),
    width = ("Width", "lineplot(sin, 1:.5:20, width=60, border=:dotted)"),
    height = ("Height", "lineplot(sin, 1:.5:20, height=18, border=:dotted)"),
    labels = ("Labels", "lineplot(sin, 1:.5:20, labels=false, border=:dotted)"),
    border_bold = ("Border", "lineplot([-1., 2, 3, 7], [1.,2, 9, 4], canvas=DotCanvas, border=:bold)"),
    border_dashed = ("Border", "lineplot([-1., 2, 3, 7], [1.,2, 9, 4], canvas=DotCanvas, border=:dashed)"),
    border_dotted = ("Border", "lineplot([-1., 2, 3, 7], [1.,2, 9, 4], border=:dotted)"),
    border_none = ("Border", "lineplot([-1., 2, 3, 7], [1.,2, 9, 4], border=:none)"),
    decorate = ("Decorate", """
      x = y = collect(1:10)
      plt = lineplot(x, y, canvas=DotCanvas, width=30, height=10)
      lineplot!(plt, x, reverse(y))
      title!(plt, "Plot Title")
      for loc in (:tl, :t, :tr, :bl, :b, :br)
        label!(plt, loc, string(':', loc))
      end
      label!(plt, :l, ":l")
      label!(plt, :r, ":r")
      for i in 1:10
        label!(plt, :l, i, string(i))
        label!(plt, :r, i, string(i))
      end
      plt
      """),
    canvas = ("Canvas", """
      canvas = BrailleCanvas(40, 15,                    # number of columns and rows (characters)
                             origin_x=0., origin_y=0.,  # position in virtual space
                             width=1., height=1.)       # size of the virtual space
      lines!(canvas, 0., 0., 1., 1., :blue)             # virtual space
      points!(canvas, rand(50), rand(50), :red)         # virtual space
      lines!(canvas, 0., 1., .5, 0., :yellow)           # virtual space
      pixel!(canvas, 5, 8, :red)                        # pixel space
      Plot(canvas, border=:dotted)
      """),
    blending = ("Blending", """
      canvas = BrailleCanvas(40, 15, origin_x=0., origin_y=0., width=1., height=1.)
      lines!(canvas, 0., 0., 1., 1., :blue)
      lines!(canvas, .25, 1., .5, 0., :yellow)
      lines!(canvas, .2, .8, 1., 0., :red)
      Plot(canvas, border=:dotted)
      """),
  )

  examples = NamedTuple{keys(exs)}((
      MD(Paragraph(
        "```julia\n$(rstrip(e[2]))\n```\n![$(e[1])]($docs_url/doc/imgs/$ver/$k.png)"
      )) for (k, e) in pairs(exs)
    )
  )

  tab = ' '^2

  indent(x, n) = repeat(tab, n) * join(split(x isa MD ? plain(x) : x, '\n'), '\n' * repeat(tab, n))
  desc_ex(k, d, n=2) = (
    if k == :border
      join((
        d,
        indent(examples.border_bold, n),
        indent(examples.border_dashed, n),
        indent(examples.border_dotted, n),
        indent(examples.border_none, n),
      ), '\n')
    elseif k in (:width, :height, :labels)
      join((d, indent(getindex(examples, k), n)), '\n')
    else
      d
    end
  )
  description = join(
    (
      "$tab- `$(UnicodePlots.default_with_type(k))`: $(desc_ex(k, d * '.'))"
      for (k, d) in pairs(UnicodePlots.DESCRIPTION) if k in keys(UnicodePlots.KEYWORDS)
    ), '\n'
  )

  readme = md"""
# UnicodePlots

[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md)
[![PkgEval](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/U/UnicodePlots.named.svg)](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/U/UnicodePlots.html)
[![CI](https://github.com/JuliaPlots/UnicodePlots.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/JuliaPlots/UnicodePlots.jl/actions/workflows/ci.yml)
[![Coverage Status](https://codecov.io/gh/JuliaPlots/UnicodePlots.jl/branch/master/graphs/badge.svg?branch=master)](https://app.codecov.io/gh/JuliaPlots/UnicodePlots.jl)
[![UnicodePlots Downloads](https://shields.io/endpoint?url=https://pkgs.genieframework.com/api/v1/badge/UnicodePlots)](https://pkgs.genieframework.com?packages=UnicodePlots)

Advanced [`Unicode`](https://en.wikipedia.org/wiki/Unicode) plotting library designed for use in `Julia`'s `REPL`.

`UnicodePlots` is integrated in [`Plots`](https://github.com/JuliaPlots/Plots.jl) as a backend, with support for [layouts](https://docs.juliaplots.org/stable/generated/unicodeplots/#unicodeplots-ref17).

## High-level Interface

There are a couple of ways to generate typical plots without much verbosity.

Here is a list of the main high-level functions for common scenarios:

  - [`scatterplot`](https://github.com/JuliaPlots/UnicodePlots.jl#scatterplot) (Scatter Plot)
  - [`lineplot`](https://github.com/JuliaPlots/UnicodePlots.jl#lineplot) (Line Plot)
  - [`stairs`](https://github.com/JuliaPlots/UnicodePlots.jl#staircase-plot) (Staircase Plot)
  - [`barplot`](https://github.com/JuliaPlots/UnicodePlots.jl#barplot) (Bar Plot - horizontal)
  - [`histogram`](https://github.com/JuliaPlots/UnicodePlots.jl#histogram) (Histogram - horizontal)
  - [`boxplot`](https://github.com/JuliaPlots/UnicodePlots.jl#boxplot) (Box Plot - horizontal)
  - [`spy`](https://github.com/JuliaPlots/UnicodePlots.jl#sparsity-pattern) (Sparsity Pattern)
  - [`densityplot`](https://github.com/JuliaPlots/UnicodePlots.jl#density-plot) (Density Plot)
  - [`contourplot`](https://github.com/JuliaPlots/UnicodePlots.jl#contour-plot) (Contour Plot)
  - [`heatmap`](https://github.com/JuliaPlots/UnicodePlots.jl#heatmap-plot) (Heatmap Plot)

Here is a quick hello world example of a typical use-case:

$(examples.lineplot1)

There are other types of `Canvas` available (see section [Low-level Interface](https://github.com/JuliaPlots/UnicodePlots.jl#low-level-interface)).

In some situations, such as printing to a file, using `AsciiCanvas`, `DotCanvas` or `BlockCanvas` might lead to better results:

$(examples.lineplot2)

Some plot methods have a mutating variant that ends with a exclamation mark:

$(examples.lineplot3)

#### Scatterplot

$(examples.scatterplot1)

Axis scaling (`xscale` and/or `yscale`) is supported: choose from (`:identity`, `:ln`, `:log2`, `:log10`) or use an arbitrary scale function:

$(examples.scatterplot2)

For the axis scale exponent, one can revert to using `ASCII` characters instead of `Unicode` ones using the keyword `unicode_exponent=false`:

$(examples.scatterplot3)

Using a `marker` is supported, choose a `Char`, a unit length `String` or a symbol name such as `:circle` (more from `keys(UnicodePlots.MARKERS)`).
One can also provide a vector of `marker`s and/or `color`s as in the following example:

$(examples.scatterplot4)

#### Lineplot

$(examples.lineplot4)

It's also possible to specify a function and a range:

$(examples.lineplot5)

You can also plot lines by specifying an intercept and slope:

$(examples.lineplot6)

#### Staircase plot

$(examples.stairs1)

#### Barplot

$(examples.barplot1)

_Note_: You can use the keyword argument `symbols` to specify the characters that should be used to plot the bars (e.g. `symbols=['#']`).

#### Histogram

$(examples.histogram1)

The `histogram` function also supports axis scaling using the parameter `xscale`:

$(examples.histogram2)

#### Boxplot

$(examples.boxplot1)

$(examples.boxplot2)

#### Sparsity Pattern

$(examples.spy1)

Plotting the zeros pattern is also possible using `show_zeros=true`:

$(examples.spy2)

#### Density Plot

$(examples.densityplot1)

#### Contour Plot

$(examples.contourplot1)

The keyword `levels` controls the number of contour levels. One can also choose a `colormap` as with `heatmap`, and disable the colorbar using `colorbar=false`.

#### Heatmap Plot

$(examples.heatmap1)

The `heatmap` function also supports axis scaling using the parameters `xfact`, `yfact` and axis offsets after scaling using `xoffset` and `yoffset`.

The `colormap` parameter may be used to specify a named or custom colormap. See the `heatmap` function documentation for more details.

In addition, the `colorbar` and `colorbar_border` options may be used to toggle the colorbar and configure its border.

The `zlabel` option and `zlabel!` method may be used to set the `z` axis (colorbar) label.

$(examples.heatmap2)

### Options

All plots support the set (or a subset) of the following named parameters:

  $description

_Note_: If you want to print the plot into a file but have monospace issues with your font, you should probably try setting `border=:ascii` and `canvas=AsciiCanvas` (or `canvas=DotCanvas` for scatterplots).

### Methods

  - `title!(plot::Plot, title::String)`

    - `title` the string to write in the top center of the plot window. If the title is empty the whole line of the title will not be drawn

  - `xlabel!(plot::Plot, xlabel::String)`

    - `xlabel` the string to display on the bottom of the plot window. If the title is empty the whole line of the label will not be drawn

  - `ylabel!(plot::Plot, xlabel::String)`

    - `ylabel` the string to display on the far left of the plot window.

The method `label!` is responsible for the setting all the textual decorations of a plot. It has two functions:

  - `label!(plot::Plot, where::Symbol, value::String)`

    - `where` can be any of: `:tl` (top-left), `:t` (top-center), `:tr` (top-right), `:bl` (bottom-left), `:b` (bottom-center), `:br` (bottom-right), `:l` (left), `:r` (right)

  - `label!(plot::Plot, where::Symbol, row::Int, value::String)`

    - `where` can be any of: `:l` (left), `:r` (right)

    - `row` can be between 1 and the number of character rows of the canvas
$(MD(Paragraph(indent(examples.decorate, 2))))

  - `annotate!(plot::Plot, x::Number, y::Number, text::AbstractString; kw...)`
    - `text` arbitrary annotation at position (x, y)

## Know Issues

Using a non `true monospace font` can lead to visual problems on a `BrailleCanvas` (border versus canvas).

Either change the font to e.g. [JuliaMono](https://juliamono.netlify.app/) or use `border=:dotted` keyword argument in the plots.

For a `Jupyter` notebook with the `IJulia` kernel see [here](https://juliamono.netlify.app/faq/#can_i_use_this_font_in_a_jupyter_notebook_and_how_do_i_do_it).

(Experimental) Terminals seem to respect a standard aspect ratio of `4:3`, hence a square matrix does not often look square in the terminal.

You can pass `fix_ar=true` to `spy` or `heatmap` in order to recover a unit aspect ratio (this keyword is experimental and might be unnecessary in future versions).

## Low-level Interface

The primary structures that do all the heavy lifting behind the curtain are subtypes of `Canvas`. A canvas is a graphics object for rasterized plotting. Basically it uses Unicode characters to represent pixel.

Here is a simple example:

$(examples.canvas)

You can access the height and width of the canvas (in characters) with `nrows(canvas)` and `ncols(canvas)` respectively. You can use those functions in combination with `printrow` to embed the canvas anywhere you wish. For example, `printrow(STDOUT, canvas, 3)` writes the third character row of the canvas to the standard output.

As you can see, one issue that arises when multiple pixel are represented by one character is that it is hard to assign color. That is because each of the "pixel" of a character could belong to a different color group (each character can only have a single color). This package deals with this using a color-blend for the whole group. You can disable canvas color blending / mixing by passing `blend=false` to any function.

$(examples.blending)

The following types of `Canvas` are implemented:

  - **BrailleCanvas**:
    This type of canvas is probably the one with the highest resolution for `Unicode` plotting. It essentially uses the Unicode characters of the [Braille](https://en.wikipedia.org/wiki/Braille) symbols as pixels. This effectively turns every character into eight pixels that can individually be manipulated using binary operations.

  - **BlockCanvas**:
    This canvas is also `Unicode` based. It has half the resolution of the BrailleCanvas. In contrast to `BrailleCanvas`, the pixels don't have visible spacing between them. This canvas effectively turns every character into four pixels that can individually be manipulated using binary operations.

  - **HeatmapCanvas**:
    This canvas is also `Unicode` based. It has half the resolution of the `BlockCanvas`. This canvas effectively turns every character into two color pixels, using the foreground and background terminal colors. As such, the number of rows of the canvas is half the number of `y` coordinates being displayed.

  - **AsciiCanvas** and **DotCanvas**:
    These two canvas utilizes only standard `ASCII` character for drawing. Naturally, it doesn't look quite as nice as the Unicode-based ones. However, in some situations it might yield better results. Printing plots to a file is one of those situations.

  - **DensityCanvas**:
    Unlike the `BrailleCanvas`, the density canvas does not simply mark a "pixel" as set. Instead it increments a counter per character that keeps track of the frequency of pixels drawn in that character. Together with a variable that keeps track of the maximum frequency, the canvas can thus draw the density of datapoints.

  - **BarplotGraphics**:
    This graphics area is special in that it does not support any pixel manipulation. It is essentially the barplot without decorations but the numbers. It does only support one method `addrow!` which allows the user to add additional bars to the graphics object.

## Installation

To install UnicodePlots, start up `Julia` and type the following code snippet into the `REPL` (makes use of the native `Julia` package manager `Pkg`):

```julia
using Pkg
Pkg.add("UnicodePlots")
```

## Documentation update

The following snippet:
```bash
cd docs
julia generate_docs.jl
(cd imgs; bash gen_imgs.sh)
```
will regenerate `README.md` and the example images with root (prefix) url $(docs_url).

## License

This code is free to use under the terms of the MIT license.

## Acknowledgement

Inspired by [TextPlots.jl](https://github.com/sunetos/TextPlots.jl), which in turn was inspired by [Drawille](https://github.com/asciimoo/drawille)
"""

  mkpath("imgs/$ver")
  open("imgs/gen_imgs.jl", "w") do io
    println(io, """
      using UnicodePlots, StableRNGs, SparseArrays
      include(joinpath(dirname(pathof(UnicodePlots)), "..", "test", "fixes.jl"))

      RNG = StableRNG(1337)

      save(p, nm) = savefig(p, "$ver/\$(nm).txt"; color=true)
      """
    )
    for (i, (k, e)) in enumerate(pairs(exs))
      println(io, "# $k")
      code = filter(x -> length(x) != 0 && !startswith(lstrip(x), r"using|import"), [lstrip(c) for c in split(e[2], '\n')])
      code = [replace(c, r"\bsprandn\b\(" => "_stable_sprand(RNG, ", r"\brandn\b\(" => "randn(RNG, ", r"\brand\b\(" => "rand(RNG, ") for c in code]
      println(io, "_ex_$i() = begin\n$(indent(join(code, '\n'), 1))\nend")
      println(io, "plt = _ex_$i(); save(plt, \"$k\")")
    end
  end

  open("imgs/gen_imgs.sh", "w") do io
    write(io, """
      #!/usr/bin/env bash
      \${JULIA-julia} gen_imgs.jl

      for f in $ver/*.txt; do
        html=\${f%.txt}.html
        cat \$f | \${ANSI2HTML-ansi2html} --input-encoding=utf-8 --output-encoding=utf-8 >\$html
        \${WKHTMLTOIMAGE-wkhtmltoimage} --quiet --crop-w 800 --quality 85 \$html \${html%.html}.png
      done

      rm $ver/*.txt
      rm $ver/*.html
      """
    )
  end

  plain_readme = plain(readme)
  write(stdout, plain_readme)
  open("../README.md", "w") do io
    write(io, "<!-- WARNING: this file has been automatically generated, please update Unicodeplots/docs/generate_docs.jl instead, and run \$ julia generate_docs.jl to render README.md !! -->\n")
    write(io, plain_readme)
  end
  return
end

main()


text:
module bankNote

#--- functions
"""
Mimics the Cash found in a cash-registry systems

Idea: how about adding a penny, & a nickle ??

"""
function _5dollar(count::Interger,value=5)
end
function _10dollar(count::Interger,value=10)
end
function _20dollar(count::Interger, value=20)

end

#TODO: time of start counting of Inflation -i.e. inflation, since When?
"""
a generic dollar amount
has a value
Changing based on inflation
"""
# a generic dollar amount: has a value Changing based on inflation
#
function _Xdollar(value, ,inflation = 5 * 10^-2)
"""
returns the intrinsic value of a dollar
"""
    intrinsic_value =  (value - value * inflation)
    #if has
    return intrinsic_value
end

#The must-have factor
"""
based on netwon's renowned f = m * a in classical phyiscs
a dollar has a physical value, that is changing by changin the
1. velocity:
2. acceleration:

"""
function _Xdollar(value, velocity, acceleration,inflation=10^-1)

    intrinsic_value =  (value - value * inflation)
    #if has
end
end

max_stars_repo_name: adamwillisXanax/SolvencyPredictor

max_issues_repo_name: adamwillisXanax/SolvencyPredictor

max_forks_repo_name: adamwillisXanax/SolvencyPredictor


text:
@doc doc"""
Information of clusters in Swendsen-Wang algorithm.

# Fields
- `activated_bonds` : The number of activated (connected) bonds of each cluster.
- `clustersize` : The number of sites in each cluster.
- `clusterspin` : Spin variable of each cluster (e.g., 1 or -1 for `Ising`).
"""
mutable struct SWInfo
    activated_bonds :: Vector{Int}
    clustersize :: Vector{Int}
    clusterspin :: Vector{Int}
end

numclusters(sw::SWInfo) = length(sw.clustersize)

@doc """
    SW_update!(model, param::Parameter)
    SW_update!(model, T::Real, Js::AbstractArray)

Updates spin configuration by Swendsen-Wang algorithm
under temperature `T=param["T"]` and coupling constants `J=param["J"]`
"""
@inline function SW_update!(model::Union{Ising, Potts, Clock, XY}, param::Parameter)
    p = convert_parameter(model, param)
    return SW_update!(model, p...)
end

function SW_update!(model::Ising, T::Real, Js::AbstractArray)
    rng = model.rng
    ps = -expm1.((-2.0/T).*Js)
    nsites = numsites(model)
    nbonds = numbonds(model)
    nbt = numbondtypes(model)
    activated_bonds = zeros(Int,nbt)
    uf = UnionFind(nsites)
    @inbounds for bond in bonds(model)
        s1,s2 = source(bond), target(bond)
        bt = bondtype(bond)
        if model.spins[s1] == model.spins[s2] && rand(rng) < ps[bt]
            activated_bonds[bt] += 1
            unify!(uf, s1,s2)
        end
    end
    nc = clusterize!(uf)
    clustersize = zeros(Int, nc)
    clusterspin = rand(rng,[1,-1], nc)

    @inbounds for site in 1:nsites
        id = clusterid(uf, site)
        model.spins[site] = clusterspin[id]
        clustersize[id] += 1
    end
    return SWInfo(activated_bonds, clustersize, clusterspin)
end

function SW_update!(model::Potts, T::Real, Js::AbstractArray)
    rng = model.rng
    ps = -expm1.((-1.0/T).*Js)
    nsites = numsites(model)
    nbonds = numbonds(model)
    nbt = numbondtypes(model)
    activated_bonds = zeros(Int,nbt)
    uf = UnionFind(nsites)
    @inbounds for bond in bonds(model)
        s1,s2 = source(bond), target(bond)
        bt = bondtype(bond)
        if model.spins[s1] == model.spins[s2] && rand(rng) < ps[bt]
            activated_bonds[bt] += 1
            unify!(uf, s1,s2)
        end
    end
    nc = clusterize!(uf)
    clustersize = zeros(Int, nc)
    clusterspin = rand(rng,1:model.Q, nc)

    @inbounds for site in 1:nsites
        id = clusterid(uf, site)
        model.spins[site] = clusterspin[id]
        clustersize[id] += 1
    end
    return SWInfo(activated_bonds, clustersize, clusterspin)
end

function SW_update!(model::Clock, T::Real, Js::AbstractArray)
    rng = model.rng
    nsites = numsites(model)
    nbonds = numbonds(model)
    m2bJ = (-2/T).*Js
    m = rand(rng, 1:model.Q)-1
    rspins = zeros(Int, nsites)
    @inbounds for s in 1:nsites
        rspins[s] = mod1(model.spins[s]-m, model.Q)
    end
    uf = UnionFind(nsites)
    @inbounds for bond in bonds(model)
        s1,s2 = source(bond), target(bond)
        bt = bondtype(bond)
        if rand(rng) < -expm1(m2bJ[bt]*model.sines_sw[rspins[s1]]*model.sines_sw[rspins[s2]])
            unify!(uf, s1,s2)
        end
    end
    nc = clusterize!(uf)
    toflips = rand(rng, Bool, nc)
    clustersize = zeros(Int, nc)
    @inbounds for site in 1:nsites
        id = clusterid(uf, site)
        s = ifelse(toflips[id], model.Q-rspins[site]+1, rspins[site])
        clustersize[id] += 1
        model.spins[site] = mod1(s+m, model.Q)
    end

    return nothing
end

function SW_update!(model::XY, T::Real, Js::AbstractArray)
    rng = model.rng
    nsites = numsites(model)
    nbonds = numbonds(model)
    m2bJ = (-2/T).*Js
    m = 0.5*rand(rng)
    pspins = zeros(nsites)
    @inbounds for s in 1:nsites
        pspins[s] = cospi(2(model.spins[s]-m))
    end
    uf = UnionFind(nsites)
    @inbounds for bond in bonds(model)
        s1,s2 = source(bond), target(bond)
        bt = bondtype(bond)
        if rand(rng) < -expm1(m2bJ[bt]*pspins[s1]*pspins[s2])
            unify!(uf, s1,s2)
        end
    end
    nc = clusterize!(uf)
    toflips = rand(rng, Bool, nc)
    clustersize = zeros(Int, nc)
    @inbounds for site in 1:nsites
        id = clusterid(uf, site)
        s = model.spins[site]
        s = ifelse(toflips[id], s, 2m+0.5-s)
        s = mod(s, 1.0)
        clustersize[id] += 1
        model.spins[site] = s
    end

    return nothing
end


text:
module BEAST

using Distributed
using LinearAlgebra
using SharedArrays
using SparseArrays
using FillArrays
using BlockArrays
using SparseMatrixDicts

using SauterSchwabQuadrature
using SauterSchwab3D
using FastGaussQuadrature
using LinearMaps
using LiftedMaps

using TimerOutputs

import LinearAlgebra: cross, dot
import LinearAlgebra: ×, ⋅

import SharedArrays: sdata

export dot

export planewave
export RefSpace, numfunctions, coordtype, scalartype, assemblydata, geometry, refspace, valuetype
export lagrangecxd0, lagrangec0d1, duallagrangec0d1
export duallagrangecxd0
export lagdimension
export restrict
export raviartthomas, raowiltonglisson, positions
export brezzidouglasmarini
export brezzidouglasmarini3d
export nedelecd3d
export nedelecc3d
export portcells, rt_ports, getindex_rtg, subset
export StagedTimeStep
export subdsurface,subdBasis,assemblydata,refspace
export spatialbasis, temporalbasis
export ⊗
export timebasisc0d1
export timebasiscxd0
export timebasisdelta
export timebasisshiftedlagrange
export TimeBasisDeltaShifted
export ntrace
export strace
export ttrace
export SingleLayer
export DoubleLayer
export DoubleLayerTransposed
export HyperSingular
export HH3DSingleLayerTDBIO
export HH3DDoubleLayerTDBIO
export ∂n
export HH3DHyperSingularFDBIO
export NitscheHH3
export MWSingleLayerTDIO
export MWDoubleLayerTDIO
export MWFarField3DTD
export MWFarField3D
export MWSingleLayer3D, MWHyperSingular, MWWeaklySingular
export MWDoubleLayer3D
export PlaneWaveMW
export dipolemw3d, DipoleMW
export TangTraceMW, CrossTraceMW
export curl
export MWSingleLayerField3D
export SingleLayerTrace
export DoubleLayerRotatedMW3D
export MWSingleLayerPotential3D

export VIEOperator
export VSIEOperator

export gmres
export @hilbertspace, @varform, @discretise
export solve
export convolve
export marchonintime
export RungeKuttaConvolutionQuadrature
export laplace_to_z, inverse_z_transform, real_inverse_z_transform
export butcher_tableau_radau_2stages
export butcher_tableau_radau_3stages
export creategaussian
export derive, integrate
export fouriertransform
export assemble
export Identity
export shapevals
export NCross
export quadrule, elements
export blockassembler
export localoperator
export localoperator2
export assemble
export facecurrents
export potential
export get_scatter_parameters
export quaddata

export DofInterpolate

export kernelvals
export integrand
export shapevals
export ScalarTrace
export PlaneWaveDirichlet
export PlaneWaveNeumann

struct NormalVector end

using CompScienceMeshes
using Combinatorics
using FFTW
using SparseArrays

function convolve end

include("utils/polynomial.jl")
include("utils/mixedblockarrays.jl")
include("timedomain/convop.jl")
include("utils/sparsend.jl")
include("utils/specialfns.jl")
include("utils/combinatorics.jl")
include("utils/linearspace.jl")
include("utils/matrixconv.jl")
include("utils/polyeig.jl")
include("utils/zeromap.jl")

include("bases/basis.jl")
include("bases/lincomb.jl")
include("bases/trace.jl")
include("bases/restrict.jl")
include("bases/divergence.jl")

include("bases/local/laglocal.jl")
include("bases/local/rtlocal.jl")
include("bases/local/ndlocal.jl")
include("bases/local/bdmlocal.jl")
include("bases/local/ndlcclocal.jl")
include("bases/local/ndlcdlocal.jl")
include("bases/local/bdm3dlocal.jl")

include("bases/lagrange.jl")
include("bases/rtspace.jl")
include("bases/rtxspace.jl")
include("bases/bcspace.jl")
include("bases/ndspace.jl")
include("bases/bdmdiv.jl")
include("bases/ndlccspace.jl")
include("bases/ndlcdspace.jl")
include("bases/bdm3dspace.jl")

include("bases/subdbasis.jl")
include("bases/stagedtimestep.jl")

include("bases/timebasis.jl")
include("bases/tensorbasis.jl")

include("quadrature/quadstrats.jl")
include("quadrature/double_quadrature.jl")
include("quadrature/singularity_extraction.jl")

include("excitation.jl")
include("operator.jl")
include("localop.jl")
include("multiplicativeop.jl")
include("identityop.jl")
include("integralop.jl")
include("interpolation.jl")
include("quaddata.jl")
include("postproc.jl")
include("postproc/segcurrents.jl")

include("timedomain/tdintegralop.jl")
include("timedomain/tdexcitation.jl")
include("timedomain/motlu.jl")
include("timedomain/tdtimeops.jl")
include("timedomain/rkcq.jl")
include("timedomain/zdomain.jl")

# Support for Maxwell equations
include("maxwell/mwexc.jl")
include("maxwell/mwops.jl")
include("maxwell/wiltonints.jl")
include("maxwell/sauterschwabints_rt.jl")
include("maxwell/sauterschwabints_bdm.jl")
include("maxwell/nxdbllayer.jl")
include("maxwell/nitsche.jl")
include("maxwell/farfield.jl")
include("maxwell/nearfield.jl")
include("maxwell/spotential.jl")
include("maxwell/maxwell.jl")
include("maxwell/sourcefield.jl")

# Support for the Helmholtz equatio
include("helmholtz2d/helmholtzop.jl")

include("helmholtz3d/hh3dexc.jl")
include("helmholtz3d/hh3dops.jl")
include("helmholtz3d/nitsche.jl")
include("helmholtz3d/hh3dnear.jl")

#suport for Volume Integral equation
include("volumeintegral/vie.jl")
include("volumeintegral/vieexc.jl")
include("volumeintegral/vieops.jl")
include("volumeintegral/farfield.jl")
include("volumeintegral/vsie.jl")
include("volumeintegral/vsieops.jl")
include("volumeintegral/sauterschwab_ints.jl")

include("decoupled/dpops.jl")
include("decoupled/potentials.jl")

include("helmholtz3d/timedomain/tdhh3dops.jl")
include("helmholtz3d/timedomain/tdhh3dexc.jl")
include("helmholtz3d/timedomain/tdhh3dpp.jl")

include("maxwell/timedomain/mwtdops.jl")
include("maxwell/timedomain/mwtdexc.jl")
include("maxwell/timedomain/tdfarfield.jl")

include("utils/butchertableau.jl")
include("utils/variational.jl")

include("solvers/solver.jl")
include("solvers/lusolver.jl")
include("solvers/itsolver.jl")

const x̂ = point(1,0,0)
const ŷ = point(0,1,0)
const ẑ = point(0,0,1)
export x̂, ŷ, ẑ

const n = NormalVector()
export n

const to = TimerOutput()

end # module


text:
using Base.Threads

function logsoftmax!(out::AbstractVecOrMat, xs::AbstractVecOrMat)
  @threads for j = 1:size(xs, 2)
    @inbounds begin
      xi_max = xs[1, j]
      for i = 1:size(out, 1)
        xi_max = max(xi_max, xs[i, j])
      end
      s = zero(eltype(out))
      for i = 1:size(out, 1)
        s += exp(xs[i, j] - xi_max)
      end
      for i = 1:size(out, 1)
        out[i, j] = xs[i, j] - log(s) - xi_max
      end
    end
  end
  out
end

logsoftmax!(xs) = logsoftmax!(xs, xs)
logsoftmax(xs) = logsoftmax!(similar(xs), xs)

∇logsoftmax(Δ, xs) = ∇softmax(Δ ./ max.(eps(eltype(xs)),softmax(xs)), xs)

"""
    logsoftmax(xs) = log.(exp.(xs) ./ sum(exp.(xs)))

logsoftmax computes the log of softmax(xs) and it is more numerically stable
than softmax function in computing the cross entropy loss.
"""
logsoftmax


text:
function test_kron()
  @testset ExtendedTestSet "Kron" begin
    for A in Any[simple_matrix(Float64, 2, 3), simple_sparse_matrix(Float64, 10, 10)]
      for B in Any[
        simple_matrix(Float64, 2, 3),
        simple_matrix(ComplexF64, 2, 3),
        simple_sparse_matrix(Float64, 10, 10),
      ]
        K = kron(A, B)
        normK = norm(K, 1)
        T1 = kron(LinearOperator(A), B)
        T2 = kron(A, LinearOperator(B))
        T3 = kron(LinearOperator(A), LinearOperator(B))
        for T in [T1, T2, T3]
          @test norm(K - Matrix(T), 1) < eps() * normK
          @test norm(K' - Matrix(T'), 1) < eps() * normK
          @test norm(transpose(K) - Matrix(transpose(T)), 1) < eps() * normK
          m, n = size(K)
          err = 0.0
          for t = 1:100
            x = simple_vector(Float64, n)
            Kx = K * x
            Tx = T * x
            err += norm(Kx - Tx, 1)

            x = simple_vector(Float64, m)
            Kx = K' * x
            Tx = T' * x
            err += norm(Kx - Tx, 1)

            Kx = transpose(K) * x
            Tx = transpose(T) * x
            err += norm(Kx - Tx, 1)
          end
          @test err < 1e-12 * normK
        end
      end
    end
  end

  @testset ExtendedTestSet "issue110" begin
    A = rand(2, 2)
    op = LinearOperator(A)
    K = kron(A, op)
    x = rand(Complex{Float64}, 4)
    y = K * x
    @test eltype(y) == Complex{Float64}
  end
end

test_kron()


text:
@enum inverter_inner_vars begin
    md_var = 1
    mq_var = 2
    Vdc_var = 3
    Vdo_var = 5
    Vqo_var = 6
    ω_freq_estimator_var = 7
    v_control_var = 8
    ω_control_var = 9
    δdqRI_var = 10 # alias for δθ_vsm, TODO: should δθ_vsm ever be accessed as external state? RH: Most likely
    VR_inv_var = 11
    VI_inv_var = 12
    Vdcnv_var = 13
    Vqcnv_var = 14
end

Base.to_index(ix::inverter_inner_vars) = Int(ix)

include("inverter_components/outer_control.jl")
include("inverter_components/voltage_source_control.jl")
include("inverter_components/converter.jl")
include("inverter_components/dc_source.jl")
include("inverter_components/frequency_estimator.jl")
include("inverter_components/filter.jl")

mutable struct DynInverter{C <: Converter,
                           O <: OuterControl,
                           VC <: VSControl,
                           DC<: DCSource,
                           P <: FrequencyEstimator,
                           F <: Filter} <: DynInjection
    number::Int64
    name::Symbol
    bus::PSY.Bus
    ω_ref::Float64
    V_ref::Float64
    P_ref::Float64
    Q_ref::Float64
    MVABase::Float64
    converter::C
    outercontrol::O
    vscontrol::VC
    dc_source::DC
    freq_estimator::P
    filter::F #add MVAbase here
    n_states::Int64
    states::Vector{Symbol}
    inner_vars::Vector{Float64}
    local_state_ix::Dict{InverterComponent,Vector{Int64}}
    input_port_mapping::Dict{InverterComponent,Vector{Int64}}

        function DynInverter(number::Int64,
                            name::Symbol,
                            bus::PSY.Bus,
                            ω_ref::Float64,
                            V_ref::Float64,
                            P_ref::Float64,
                            Q_ref::Float64,
                            MVABase::Float64,
                            converter::C,
                            outercontrol::O,
                            vscontrol::VC,
                            dc_source::DC,
                            freq_estimator::P,
                            filter::F) where {C<:Converter,
                                              O<:OuterControl,
                                              VC<:VSControl,
                                              DC<:DCSource,
                                              P<:FrequencyEstimator,
                                              F<:Filter}

            n_states = (converter.n_states +
                       outercontrol.n_states +
                       vscontrol.n_states +
                       dc_source.n_states +
                       freq_estimator.n_states +
                       filter.n_states)

            states = vcat(converter.states,
                        outercontrol.states,
                        vscontrol.states,
                        dc_source.states,
                        freq_estimator.states,
                        filter.states)

            components = [converter,
                          outercontrol,
                          vscontrol,
                          dc_source,
                          freq_estimator,
                          filter]

            new{C, O, VC, DC, P, F}(number,
                                    name,
                                    bus,
                                    ω_ref,
                                    V_ref,
                                    P_ref,
                                    Q_ref,
                                    MVABase,
                                    converter,
                                    outercontrol,
                                    vscontrol,
                                    dc_source,
                                    freq_estimator,
                                    filter,
                                    n_states,
                                    states,
                                    zeros(14),
                                    _make_state_mapping(components, states),
                                    _make_port_mapping(components, states))

        end
end

get_inverter_Sbase(device::DynInverter) = device.converter.s_rated
get_inverter_Vref(device::DynInverter) = device.V_ref


text:
"""
    @derived function foofunc(rt::Salsa.Runtime, x::Int, y::Vector{Int})::Int ... end

This macro is used to mark a julia function as a Salsa Derived Function, which means the
Salsa framework will cache its return value, keyed on its inputs, and correctly re-evaluate
it in future invocations if any of the Salsa computations it invokes have changed.

This function must be a mathematically _pure_ function, meaning it should not depend on any
outside state, and may only access state through other Salsa computations, called via the
`Runtime`, which must be the first argument to any derived function).

The return value of this function is cached, so that (if no dependencies have been
invalidated) the next time this function is called with the same input arguments, the
cached value will be returned instead, and this function will not execute.

During execution of this function, Salsa will automatically track all calls made to other
Salsa computations (calling other `@derived` functions or input functions) on the
provided `Runtime`. This set of runtime _dependencies_ is used to track
_cache-invalidation_. That is, if any of the inputs reachable along a dependency path from
this function are changed, then any subsequent call to this function will trigger a full
computation, and the function will be rerun. (NOTE, though, that the Early-Exit Optimziation
means that if the same value is returned, we can avoid recomputing any values further down
the dependency chain.)

# Example
```julia-repl
julia> @declare_input student_grade(name::String)::Float64
(student_grade, set_student_grade!, delete_student_grade!)

julia> @derived function letter_grade(rt, name)
           println("computing grade for ", name)
           ["D","C","B","A"][Int(round(student_grade(rt, name)))]
       end
letter_grade (generic function with 1 method)

julia> rt = Runtime();

julia> set_student_grade!(rt, "John", 3.25)  # Set initial grade

julia> letter_grade(rt, "John")
computing grade for John
"B"

julia> letter_grade(rt, "John")  # Uses cached value for letter_grade("John") (no output)
"B"

julia> set_student_grade!(rt, "John", 3.8)  # Change input; invalidates cache for letter_grade().

julia> letter_grade(rt, "John")  # Re-runs the computation sinc its input has changed.
computing grade for John
"A"
```
"""
macro derived(f)
    dict = MacroTools.splitdef(f)

    fname = dict[:name]
    args = dict[:args]

    # _argnames and _argtypes fill in anonymous names for unnamed args (`::Int`) and `Any`
    # for untyped args. `fullargs` will have all args w/ names and types.
    argnames = _argnames(args)
    argtypes = _argtypes(args)
    # Ensure that every argument is named, even unnamed parameters, so that they can be
    # forwarded from the outer function into the inner one.
    fullargs = deepcopy(args)
    for (i,a) in enumerate(fullargs)
        if a isa Expr && a.head == :(::) && length(a.args) == 1
            pushfirst!(a.args, argnames[i])
        end
    end

    # Get the type of the first argument to verify it is a runtime sub- or supertype.
    # NOTE: I am PRETTY SURE it's okay to eval here. Function definitions already require
    # argument *types* to be defined already, so evaling the types should be A OKAY!
    FirstArgType = Core.eval(__module__, first(argtypes))

    # Assert that the @derived function starts with a runtime arg. The arg can be untyped,
    # or unnamed, it just has to be at least able to hold a Runtime.
    if !(
        length(argtypes) >= 1 &&
        # This allows any input like these: `_`, `rt`, `::Runtime`, `::MyRuntime`, `r::Any`
        # And disallows inputs like these: `::Int`, `x::String`.
        (FirstArgType <: Runtime || FirstArgType >: Runtime)
    )
        err_str = "@derived functions must take a `Runtime` as the first argument."
        if length(argtypes) >= 1
            err_str *= " Got unexpected $(FirstArgType) instead."
        end
        throw(ArgumentError(err_str))
    end

    # Rename user function.
    userfname = Symbol("%%__user_$fname")
    dict[:name] = userfname
    userfunc = MacroTools.combinedef(dict)

    # Construct the originally named, visible function
    dict[:name] = fname
    dict[:args] = fullargs
    dict[:body] = quote
        args = ($(argnames[2:end]...),)
        key = $DerivedKey{typeof($fname)}(args)
        # TODO: Without this, derived functions are all type unstable, unless the user puts
        # a return type annotation on the function.. :( But we have to turn this off
        # because the compiler is hanging, taking >1 hour in Delve.
        # TODO: File an issue about this. This shouldn't be happening!
        #RT = $(Core.Compiler.return_type)($userfname, typeof(($(argnames[1]), args...)))
        $memoized_lookup_unwrapped($(argnames[1]), key) #::RT
    end
    visible_func = MacroTools.combinedef(dict)

    esc(
        quote
            $userfunc

            # Attach any docstring before this macrocall to the "visible" function.
            Core.@__doc__ $visible_func

            @inline function $Salsa.get_user_function(
                $(fullargs[1]),
                ::$DerivedKey{typeof($fname)},
            )
                return $userfname
            end

            $fname
        end,
    )
end

########## Methods added by the @derived macro.

# This function needs to be forward declared so that the `@derived` macro can add a method
# to it from the user's module where it was called.
function get_user_function end