diff --git a/CITATION.cff b/CITATION.cff index 0f167f5b..d854c348 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,7 +5,7 @@ authors: given-names: "Harrison" orcid: "https://orcid.org/0000-0002-8368-4641" title: "AGNI" -version: 0.6.0 +version: 0.6.1 doi: 10.xx/xx.xx -date-released: 2024-07-17 +date-released: 2024-07-18 url: "https://github.com/nichollsh/AGNI" diff --git a/Project.toml b/Project.toml index 61f5bb53..e5939dc1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "AGNI" uuid = "ede838c1-9ec3-4ebe-8ae8-da4091b3f21c" authors = ["Harrison Nicholls "] -version = "0.6.0" +version = "0.6.1" [deps] ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63" diff --git a/get_data.sh b/get_data.sh index e315b14d..c05b3157 100755 --- a/get_data.sh +++ b/get_data.sh @@ -2,6 +2,9 @@ # Download and unpack required and/or optional data # All files can be found on OSF at https://osf.io/8dumn/ +# Exit script if any of the commands fail +set -e + # Check that curl is installed if ! [ -x "$(command -v curl)" ]; then echo 'ERROR: curl is not installed.' >&2 @@ -47,64 +50,77 @@ function osf { # target file path tgt="$2/$3" - rm -f $tgt - echo " $1 > $tgt" + + # exists? + if [[ -f "$tgt" ]]; then + echo " $1 > file already exists" + return 0 + fi # get data + echo " $1 > $tgt" mkdir -p $2 curl -LsS "https://osf.io/download/$1/" > $tgt -} - -# Handle user input -case $1 in - "basic") - echo $help_basic - - osf qmp4e $res/spectral_files/Oak/318/ Oak.sf - osf 5fxr7 $res/spectral_files/Oak/318/ Oak.sf_k - - osf heuza $res/spectral_files/Dayspring/48/ Dayspring.sf - osf c5jv3 $res/spectral_files/Dayspring/48/ Dayspring.sf_k - - osf b5gsh $res/spectral_files/Dayspring/256/ Dayspring.sf - osf dn6wh $res/spectral_files/Dayspring/256/ Dayspring.sf_k - osf 2qdu8 $res/stellar_spectra sun.txt - ;; - - "highres") - echo $help_highres - - osf p672d $res/spectral_files/Honeyside/4096/ Honeyside.sf - osf ujb4z $res/spectral_files/Honeyside/4096/ Honeyside.sf_k - ;; - - "steam") - echo $help_steam - - osf 6rvfe $res/spectral_files/Frostflow/16/ Frostflow.sf - osf kxve8 $res/spectral_files/Frostflow/16/ Frostflow.sf_k - - osf 9n6mw $res/spectral_files/Frostflow/48/ Frostflow.sf - osf xfap8 $res/spectral_files/Frostflow/48/ Frostflow.sf_k - - osf mnvyq $res/spectral_files/Frostflow/256/ Frostflow.sf - osf tzsgc $res/spectral_files/Frostflow/256/ Frostflow.sf_k - ;; + return 0 +} - "stellar") - echo $help_stellar - osf mabp2 $res/stellar_spectra trappist-1.txt - osf rk7mj $res/stellar_spectra eps-eri.txt - osf agsrq $res/stellar_spectra hd97658.txt - osf ehfsy $res/stellar_spectra gj1214.txt - ;; +# Handle request for downloading a group of data +function handle_request { + case $1 in + "basic") + echo $help_basic + + osf qmp4e $res/spectral_files/Oak/318/ Oak.sf + osf 5fxr7 $res/spectral_files/Oak/318/ Oak.sf_k + + osf heuza $res/spectral_files/Dayspring/48/ Dayspring.sf + osf c5jv3 $res/spectral_files/Dayspring/48/ Dayspring.sf_k + + osf b5gsh $res/spectral_files/Dayspring/256/ Dayspring.sf + osf dn6wh $res/spectral_files/Dayspring/256/ Dayspring.sf_k + + osf 2qdu8 $res/stellar_spectra sun.txt + ;; + + "highres") + echo $help_highres + + osf p672d $res/spectral_files/Honeyside/4096/ Honeyside.sf + osf ujb4z $res/spectral_files/Honeyside/4096/ Honeyside.sf_k + ;; + + "steam") + echo $help_steam + + osf 6rvfe $res/spectral_files/Frostflow/16/ Frostflow.sf + osf kxve8 $res/spectral_files/Frostflow/16/ Frostflow.sf_k + + osf 9n6mw $res/spectral_files/Frostflow/48/ Frostflow.sf + osf xfap8 $res/spectral_files/Frostflow/48/ Frostflow.sf_k + + osf mnvyq $res/spectral_files/Frostflow/256/ Frostflow.sf + osf tzsgc $res/spectral_files/Frostflow/256/ Frostflow.sf_k + ;; + + "stellar") + echo $help_stellar + osf mabp2 $res/stellar_spectra trappist-1.txt + osf rk7mj $res/stellar_spectra eps-eri.txt + osf agsrq $res/stellar_spectra hd97658.txt + osf ehfsy $res/stellar_spectra gj1214.txt + osf 2qdu8 $res/stellar_spectra sun.txt + ;; + + *) + echo "$help" + return 0 + ;; + esac + return 0 +} - *) - echo "$help" - exit 1 - ;; -esac +handle_request $1 echo "Done!" diff --git a/res/config/55cnce_chem.toml b/res/config/55cnce_chem.toml index 67357692..602a4b72 100644 --- a/res/config/55cnce_chem.toml +++ b/res/config/55cnce_chem.toml @@ -40,12 +40,13 @@ title = "Roughly 55 Cancri e @ fO2=IW" thermo_funct = true sensible_heat = false latent_heat = true - convection_type = "mlt" + convection = true solution_type = 3 solvers = ["newton"] dx_max = 400.0 initial_state = ["iso", "2700"] - linesearch = false + linesearch = false + easy_start = false converge_atol = 1.0e-2 converge_rtol = 1.0e-3 diff --git a/res/config/condense.toml b/res/config/condense.toml index b4f22c2a..c7ab9322 100644 --- a/res/config/condense.toml +++ b/res/config/condense.toml @@ -36,7 +36,7 @@ title = "Condensation test" verbosity = 1 max_steps = 300 max_runtime = 400 - num_levels = 38 + num_levels = 35 continua = true rayleigh = false cloud = false @@ -45,12 +45,13 @@ title = "Condensation test" thermo_funct = true sensible_heat = true latent_heat = true - convection_type = "mlt" + convection = true solution_type = 3 solvers = ["newton"] dx_max = 500.0 initial_state = ["loglin","600"] - linesearch = true + linesearch = true + easy_start = true converge_atol = 0.1 converge_rtol = 1.0e-3 diff --git a/res/config/default.toml b/res/config/default.toml index beb1a98b..8663c1c5 100644 --- a/res/config/default.toml +++ b/res/config/default.toml @@ -49,12 +49,13 @@ title = "Default" # Name for this configuration file thermo_funct = false # Use temperature-dependent thermodynamic properties? sensible_heat = false # Include sensible heat transport at the surface? latent_heat = false # Include heat release from phase change - convection_type = "" # Convection type (mlt = use mixing length theory). + convection = true # Include heat transport by convection solution_type = 0 # Solution type (see wiki). solvers = [] # Ordered list of solvers to apply (see wiki). dx_max = 200.0 # Maximum step size [Kelvin], when using nonlinear solvers initial_state = ["dry", "sat", "H2O"] # Ordered list of requests describing the initial state of the atmosphere (see wiki). linesearch = false # Use linesearch? + easy_start = false # Initially down-scale convective/condensation fluxes, if initial guess is poor. converge_atol = 1.0e-3 # Convergence criterion on absolute flux divergence [W m-2]. converge_rtol = 1.0e-1 # Convergence criterion on relative flux divergence [dimensionless]. diff --git a/res/config/hotdry.toml b/res/config/hotdry.toml index 30a0ecd6..4ba6b70c 100644 --- a/res/config/hotdry.toml +++ b/res/config/hotdry.toml @@ -44,12 +44,13 @@ title = "Hot and dry" thermo_funct = true sensible_heat = true latent_heat = false - convection_type = "mlt" + convection = true solution_type = 3 solvers = ["newton"] dx_max = 400.0 initial_state = ["iso","2300"] - linesearch = false + linesearch = false + easy_start = false converge_atol = 1.0e-2 converge_rtol = 1.0e-4 diff --git a/src/AGNI.jl b/src/AGNI.jl index 65cdfbda..c511aff3 100755 --- a/src/AGNI.jl +++ b/src/AGNI.jl @@ -286,7 +286,7 @@ module AGNI flag_aer::Bool = cfg["execution" ]["aerosol"] overlap::Int = cfg["execution" ]["overlap_method"] thermo_funct::Bool = cfg["execution" ]["thermo_funct"] - conv_type::String = cfg["execution" ]["convection_type"] + incl_convect::Bool = cfg["execution" ]["convection"] incl_sens::Bool = cfg["execution" ]["sensible_heat"] incl_latent::Bool = cfg["execution" ]["latent_heat"] sol_type::Int = cfg["execution" ]["solution_type"] @@ -294,6 +294,7 @@ module AGNI initial_req::Array{String,1} = cfg["execution" ]["initial_state"] dx_max::Float64 = cfg["execution" ]["dx_max"] linesearch::Bool = cfg["execution" ]["linesearch"] + easy_start::Bool = cfg["execution" ]["easy_start"] conv_atol::Float64 = cfg["execution" ]["converge_atol"] conv_rtol::Float64 = cfg["execution" ]["converge_rtol"] max_steps::Int = cfg["execution" ]["max_steps"] @@ -455,8 +456,6 @@ module AGNI end # Solver variables - incl_convect::Bool= !isempty(conv_type) - use_mlt::Bool = (conv_type == "mlt") modplot::Int = 0 incl_conduct::Bool = false @@ -498,9 +497,10 @@ module AGNI convect=incl_convect, latent=incl_latent, sens_heat=incl_sens, max_steps=max_steps, max_runtime=max_runtime, - conv_atol=conv_atol, - conv_rtol=conv_rtol, method=method_idx, + conv_atol=conv_atol, conv_rtol=conv_rtol, + method=method_idx, dx_max=dx_max, linesearch=linesearch, + easy_start=easy_start, modplot=modplot,save_frames=plt_ani) return_success = return_success && solver_success @@ -529,7 +529,7 @@ module AGNI plt_vmr && plotting.plot_vmr(atmos, joinpath(atmos.OUT_DIR,"plot_vmrs.png"), size_x=600) plt_cff && plotting.plot_contfunc(atmos, joinpath(atmos.OUT_DIR,"plot_contfunc.png")) plt_tmp && plotting.plot_pt(atmos, joinpath(atmos.OUT_DIR,"plot_ptprofile.png"), incl_magma=(sol_type==2)) - plt_flx && plotting.plot_fluxes(atmos, joinpath(atmos.OUT_DIR,"plot_fluxes.png"), incl_mlt=use_mlt, incl_eff=(sol_type==3), incl_cdct=incl_conduct, incl_latent=incl_latent) + plt_flx && plotting.plot_fluxes(atmos, joinpath(atmos.OUT_DIR,"plot_fluxes.png"), incl_mlt=incl_convect, incl_eff=(sol_type==3), incl_cdct=incl_conduct, incl_latent=incl_latent) plt_ems && plotting.plot_emission(atmos, joinpath(atmos.OUT_DIR,"plot_emission.png")) plt_alb && plotting.plot_albedo(atmos, joinpath(atmos.OUT_DIR,"plot_albedo.png")) diff --git a/src/atmosphere.jl b/src/atmosphere.jl index 91187bae..8872d653 100644 --- a/src/atmosphere.jl +++ b/src/atmosphere.jl @@ -169,7 +169,11 @@ module atmosphere # Conduction flux_cdct::Array{Float64,1} # Conductive flux [W m-2] - # Phase change + # Phase change + phs_tau_mix::Float64 # Time scale (mixed composition) + phs_tau_sgl::Float64 # Time scale (single gas) + phs_wrk_df::Array{Float64,1} # work array: flux difference + phs_wrk_fl::Array{Float64,1} # work array: edge fluxes flux_l::Array{Float64, 1} # Latent heat energy flux [W m-2] mask_l::Array{Bool,1} # Layers transporting latent heat @@ -310,7 +314,7 @@ module atmosphere end # Code versions - atmos.AGNI_VERSION = "0.6.0" + atmos.AGNI_VERSION = "0.6.1" atmos.SOCRATES_VERSION = readchomp(joinpath(ENV["RAD_DIR"],"version")) @debug "AGNI VERSION = $(atmos.AGNI_VERSION)" @debug "Using SOCRATES at $(ENV["RAD_DIR"])" @@ -416,6 +420,10 @@ module atmosphere atmos.cloud_arr_l = zeros(Float64, atmos.nlev_c) atmos.cloud_arr_f = zeros(Float64, atmos.nlev_c) + # Phase change timescales [seconds] + atmos.phs_tau_mix = 1.0e4 # mixed composition case + atmos.phs_tau_sgl = 1.0e4 # single gas case + # Hardcoded cloud properties atmos.cond_alpha = 0.0 # 0% of condensate is retained (i.e. complete rainout) atmos.cloud_val_r = 1.0e-5 # 10 micron droplets @@ -1347,10 +1355,12 @@ module atmosphere atmos.mask_l = falses(atmos.nlev_l) # Phase change atmos.mask_c = falses(atmos.nlev_l) # Dry convection + atmos.phs_wrk_df = zeros(Float64, atmos.nlev_c) # flux difference + atmos.phs_wrk_fl = zeros(Float64, atmos.nlev_l) # edge fluxes atmos.flux_l = zeros(Float64, atmos.nlev_l) # Latent heat / phase change atmos.flux_cdry = zeros(Float64, atmos.nlev_l) # Dry convection atmos.flux_cdct = zeros(Float64, atmos.nlev_l) # Conduction - atmos.Kzz = zeros(Float64, atmos.nlev_l) + atmos.Kzz = zeros(Float64, atmos.nlev_l) # eddy diffusion coeff. atmos.flux_tot = zeros(Float64, atmos.nlev_l) atmos.flux_dif = zeros(Float64, atmos.nlev_c) diff --git a/src/dump.jl b/src/dump.jl index d8d3611a..4e6e032a 100644 --- a/src/dump.jl +++ b/src/dump.jl @@ -85,8 +85,8 @@ module dump # into PROTEUS without compatibility issues. # Absorb output from these calls, because they spam the Debug logger - @debug "ALL OUTPUT SUPPRESSED" - with_logger(NullLogger()) do + @debug "ALL DEBUG SUPPRESSED" + with_logger(MinLevelLogger(current_logger(), Logging.Info-200)) do ds = Dataset(fname,"c") @@ -327,8 +327,9 @@ module dump var_albs[:] = atmos.albedo_s_arr close(ds) + end # suppress output - @debug "ALL OUTPUT RESTORED" + @debug "ALL DEBUG RESTORED" return nothing end # end write_ncdf diff --git a/src/energy.jl b/src/energy.jl index 2c2ca8e3..5068ce08 100644 --- a/src/energy.jl +++ b/src/energy.jl @@ -355,7 +355,7 @@ module energy - `pmin::Float64` pressure [bar] below which convection is disabled - `mltype::Int` mixing length value (0: scale height, 1: asymptotic) """ - function mlt!(atmos::atmosphere.Atmos_t; pmin::Float64=1.0e-4, mltype::Int=1) + function mlt!(atmos::atmosphere.Atmos_t; pmin::Float64=1.0e-9, mltype::Int=1) pmin *= 1.0e5 # convert bar to Pa @@ -383,11 +383,6 @@ module energy continue end - # Skip condensing regions - # if atmos.mask_l[i] - # continue - # end - m1 = atmos.layer_mass[i-1] m2 = atmos.layer_mass[i] mt = m1+m2 @@ -476,6 +471,17 @@ module energy end end + # Check for spurious shallow convection in condensing regions + # If found, reset convective flux to zero AT THIS LAYER ONLY. + # for i in 2:atmos.nlev_l-1 + # if any(atmos.mask_l[i:end]) + # if atmos.mask_c[i] && !atmos.mask_c[i-1] && !atmos.mask_c[i+1] + # atmos.mask_c[i] = false + # atmos.flux_cdry[i] = 0.0 + # end + # end + # end + return nothing end # end of mlt @@ -502,14 +508,6 @@ module energy fill!(atmos.flux_l, 0.0) fill!(atmos.mask_l, false) - # Timescales [s] - timescale_mix::Float64 = 1e4 # mixture - timescale_sin::Float64 = 1e5 # single gas - - # Work arrays - df::Array{Float64,1} = zeros(Float64, atmos.nlev_c) # flux difference - fl::Array{Float64,1} = zeros(Float64, atmos.nlev_l) # edge fluxes - # Single-gas relaxation case single::Bool = Bool(atmos.gas_num == 1) E_accum::Float64 = 0.0 @@ -519,8 +517,8 @@ module energy for c in atmos.condensates # reset df,fl for this condensable - fill!(df, 0.0) - fill!(fl, 0.0) + fill!(atmos.phs_wrk_df,0.0) + fill!(atmos.phs_wrk_fl,0.0) # Loop from bottom to top for i in 1:atmos.nlev_c @@ -541,11 +539,11 @@ module energy end # relaxation function - df[i] = (atmos.gas_vmr[c][i]-qsat) * - atmos.p[i] * atmos.layer_thick[i]/timescale_sin + atmos.phs_wrk_df[i] = (atmos.gas_vmr[c][i]-qsat) * + atmos.p[i] * atmos.layer_thick[i]/atmos.phs_tau_sgl # flag layer as set by saturation - if df[i] > 1.0e-10 + if atmos.phs_wrk_df[i] > 1.0e-10 atmos.gas_sat[c][i] = true end @@ -555,8 +553,8 @@ module energy # Calculate latent heat release at this level from the contributions # of condensation (+) and evaporation (-), and a fixed timescale. - df[i] += phys.get_Lv(atmos.gas_dat[c], atmos.tmp[i]) * ( - atmos.gas_yield[c][i] / timescale_mix) + atmos.phs_wrk_df[i] += phys.get_Lv(atmos.gas_dat[c], atmos.tmp[i]) * + (atmos.gas_yield[c][i] / atmos.phs_tau_mix) end @@ -566,25 +564,25 @@ module energy if single # find top of dry region for i in 1:atmos.nlev_c - if abs(df[i]) > 0 + if abs(atmos.phs_wrk_df[i]) > 0 i_dry_top=i+1 end end - E_accum = sum(df[1:i_dry_top]) + E_accum = sum(atmos.phs_wrk_df[1:i_dry_top]) # evaporative flux in dry region for i in i_dry_top:atmos.nlev_c if E_accum < 1.0e-2 # dissipate all of the flux - df[i] = -E_accum + atmos.phs_wrk_df[i] = -E_accum E_accum = 0.0 break else # dissipate some fraction of the accumuated flux - df[i] = -0.9*E_accum - E_accum += df[i] + atmos.phs_wrk_df[i] = -0.9*E_accum + E_accum += atmos.phs_wrk_df[i] end end @@ -593,21 +591,21 @@ module energy # Convert divergence to cell-edge fluxes. # Assuming zero condensation at TOA, integrating downwards for i in 1:atmos.nlev_c - fl[i+1] = max(df[i] + fl[i], 0.0) + atmos.phs_wrk_fl[i+1] = max(atmos.phs_wrk_df[i] + atmos.phs_wrk_fl[i], 0.0) end # Ensure that flux is zero at bottom of dry region. for i in 1:atmos.nlev_c # check for where no phase change is occuring below this level - if maximum(abs.(df[i:end])) < 1.0e-5 + if maximum(abs.(atmos.phs_wrk_df[i:end])) < 1.0e-5 # if so, set all phase change fluxes to zero in that region - fl[i+1:end] .= 0.0 + atmos.phs_wrk_fl[i+1:end] .= 0.0 break end end # add energy from this gas to total - atmos.flux_l[:] .+= fl[:] + atmos.flux_l[:] .+= atmos.phs_wrk_fl[:] # calculate mask atmos.mask_l[:] .= (abs.(atmos.flux_l[:]) .> 1.0e-10) @@ -658,11 +656,12 @@ module energy - `sens_heat::Bool` include TKE sensible heat transport - `conduct::Bool` include conductive heat transport - `convect_sf::Float64` scale factor applied to convection fluxes + - `latent_sf::Float64` scale factor applied to phase change fluxes - `calc_cf::Bool=false` calculate LW contribution function? """ function calc_fluxes!(atmos::atmosphere.Atmos_t, latent::Bool, convect::Bool, sens_heat::Bool, conduct::Bool; - convect_sf::Float64=1.0, + convect_sf::Float64=1.0, latent_sf::Float64=1.0, calc_cf::Bool=false) # Reset fluxes @@ -670,7 +669,13 @@ module energy # +Condensation and evaporation if atmos.condense_any && latent + # Calc flux energy.condense_diffuse!(atmos) + + # Modulate? + atmos.flux_l *= latent_sf + + # Add to total flux atmos.flux_tot += atmos.flux_l end diff --git a/src/phys.jl b/src/phys.jl index f68e2ddf..c226eb2b 100644 --- a/src/phys.jl +++ b/src/phys.jl @@ -49,7 +49,7 @@ module phys const G_grav::Float64 = 6.67430e-11 # NIST CODATA # Molecule mean molecular weight, kg mol-1 - const lookup_mmw = Dict{String, Float64}([ + const lookup_mmw::Dict{String, Float64} = Dict{String, Float64}([ # molecules ("H2O", 1.801530E-02 ), ("CO2", 4.401000E-02 ), @@ -223,7 +223,7 @@ module phys end # end gas struct # Pre-defined colors - const lookup_color = Dict{String, String}([ + const lookup_color::Dict{String, String} = Dict{String, String}([ # common volatiles ("H2O", "#027FB1" ), ("CO2", "#D24901" ), @@ -465,29 +465,33 @@ module phys else # have data => load from file @debug(" ncdf") - ds = Dataset(fpath,"r") - - # scalar properties - gas.mmw = ds["mmw"][1] - gas.T_trip = ds["T_trip"][1] - gas.T_crit = ds["T_crit"][1] - gas.JANAF_name = String(ds["JANAF"][:]) - - # variable properties - gas.cap_T = ds["cap_T"][:] - gas.cap_C = ds["cap_C"][:] - - gas.lat_T = ds["lat_T"][:] - gas.lat_H = ds["lat_H"][:] - - gas.sat_T = ds["sat_T"][:] - gas.sat_P = ds["sat_P"][:] - if length(gas.sat_P) < 3 - gas.no_sat = true - end + @debug "ALL DEBUG SUPPRESSED" + with_logger(MinLevelLogger(current_logger(), Logging.Info-200)) do + ds = Dataset(fpath,"r") + + # scalar properties + gas.mmw = ds["mmw"][1] + gas.T_trip = ds["T_trip"][1] + gas.T_crit = ds["T_crit"][1] + gas.JANAF_name = String(ds["JANAF"][:]) + + # variable properties + gas.cap_T = ds["cap_T"][:] + gas.cap_C = ds["cap_C"][:] + + gas.lat_T = ds["lat_T"][:] + gas.lat_H = ds["lat_H"][:] + + gas.sat_T = ds["sat_T"][:] + gas.sat_P = ds["sat_P"][:] + if length(gas.sat_P) < 3 + gas.no_sat = true + end - # close file - close(ds) + # close file + close(ds) + end + @debug "ALL DEBUG RESTORED" # setup interpolators gas.cap_I = Interpolator(gas.cap_T, gas.cap_C) diff --git a/src/setpt.jl b/src/setpt.jl index 0e028313..8506a70e 100644 --- a/src/setpt.jl +++ b/src/setpt.jl @@ -13,6 +13,7 @@ module setpt using PCHIPInterpolation using NCDatasets + using LoggingExtras # Read atmosphere T(p) from a CSV file (does not overwrite p_boa and p_toa) function fromcsv!(atmos::atmosphere.Atmos_t, fpath::String) @@ -130,42 +131,48 @@ module setpt # Open file fpath = abspath(fpath) - ds = Dataset(fpath,"r") - - # Allocate interleaved temperature profile - nlev_c::Int = length(ds["p"][:]) - arr_n::Int = nlev_c + nlev_c + 1 - arr_T::Array{Float64, 1} = zeros(Float64, arr_n) - arr_P::Array{Float64, 1} = zeros(Float64, arr_n) - - # top - arr_T[1] = ds["tmpl"][1] - arr_P[1] = min(ds["pl"][1],atmos.pl[1]) # extend to lower pressures - - # middle - idx::Int = 0 - for i in 1:nlev_c - idx = (i-1)*2 - arr_T[idx+1] = ds["tmpl"][i] - arr_T[idx+2] = ds["tmp"][i] - arr_P[idx+1] = ds["pl"][i] - arr_P[idx+2] = ds["p"][i] - end + @debug "Setting PT from NetCDF file " + @debug "ALL DEBUG SUPPRESSED" + with_logger(MinLevelLogger(current_logger(), Logging.Info-200)) do + ds = Dataset(fpath,"r") + + # Allocate interleaved temperature profile + nlev_c::Int = length(ds["p"][:]) + arr_n::Int = nlev_c + nlev_c + 1 + arr_T::Array{Float64, 1} = zeros(Float64, arr_n) + arr_P::Array{Float64, 1} = zeros(Float64, arr_n) + + # top + arr_T[1] = ds["tmpl"][1] + arr_P[1] = min(ds["pl"][1],atmos.pl[1]) # extend to lower pressures + + # middle + idx::Int = 0 + for i in 1:nlev_c + idx = (i-1)*2 + arr_T[idx+1] = ds["tmpl"][i] + arr_T[idx+2] = ds["tmp"][i] + arr_P[idx+1] = ds["pl"][i] + arr_P[idx+2] = ds["p"][i] + end - # bottom - arr_T[end] = ds["tmpl"][end] - arr_P[end] = max(ds["pl"][end], atmos.pl[end]) # extend to higher pressures + # bottom + arr_T[end] = ds["tmpl"][end] + arr_P[end] = max(ds["pl"][end], atmos.pl[end]) # extend to higher pressures - # interpolate - itp = Interpolator(log10.(arr_P), arr_T) - atmos.tmpl[:] .= itp.(log10.(atmos.pl[:])) # Cell edges - atmos.tmp[:] .= itp.(log10.(atmos.p[:])) # Cell centres + # properties + atmos.tmp_surf = ds["tmp_surf"][1] - # properties - atmos.tmp_surf = ds["tmp_surf"][1] + # Close file + close(ds) - # Close file - close(ds) + # interpolate + itp = Interpolator(log10.(arr_P), arr_T) + atmos.tmpl[:] .= itp.(log10.(atmos.pl[:])) # Cell edges + atmos.tmp[:] .= itp.(log10.(atmos.p[:])) # Cell centres + + end + @debug "ALL DEBUG RESTORED" return end # end load_ncdf diff --git a/src/solver.jl b/src/solver.jl index fbf21344..ba195f5b 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -85,7 +85,7 @@ module solver - `fdo::Int` finite difference: scheme order (2nd or 4th) - `method::Int` numerical method (1: Newton-Raphson, 2: Gauss-Newton, 3: Levenberg-Marquardt) - `linesearch::Bool` use a linesearch algorithm to determine the best step size - - `modulate_mlt::Bool` improve convergence with convection by introducing MLT gradually + - `easy_start::Bool` improve convergence by introducing convection and phase change gradually - `perturb_all::Bool` always recalculate entire Jacobian matrix? Otherwise updates columns only as required - `detect_plateau::Bool` assist solver when it is stuck in a region of small dF/dT - `modplot::Int` iteration frequency at which to make plots @@ -106,8 +106,8 @@ module solver max_steps::Int=2000, max_runtime::Float64=600.0, fdw::Float64=3.0e-5, fdc::Bool=true, fdo::Int=2, method::Int=1, - linesearch::Bool=true, modulate_mlt::Bool=false, - detect_plateau::Bool=true, perturb_all::Bool=true, + linesearch::Bool=true, easy_start::Bool=true, + detect_plateau::Bool=true, perturb_all::Bool=false, modplot::Int=1, save_frames::Bool=true, modprint::Int=1, conv_atol::Float64=1.0e-2, conv_rtol::Float64=1.0e-3 @@ -136,8 +136,8 @@ module solver # Execution parameters # -------------------- # convection - convect_incr::Float64 = 3.0 # Factor to increase convect_sf when modulating convection - convect_sf::Float64 = 1.0e-5 # Convective flux scale factor + easy_incr::Float64 = 3.0 # Factor by which to increase easy_sf at each step + easy_sf::Float64 = 1.0e-5 # Convective & phase change flux scale factor # finite difference fdr::Float64 = 0.01 # Use forward difference if cost ratio is below this value @@ -146,11 +146,11 @@ module solver perturb_mod::Int = 10 # Do full jacobian at least this frequently # linesearch - ls_method::Int = 2 # linesearch algorithm (1: golden, 2: backtracking) + ls_method::Int = 1 # linesearch algorithm (1: golden, 2: backtracking) ls_tau::Float64 = 0.5 # backtracking downscale size ls_increase::Float64 = 1.5 # factor by which cost can increase ls_max_steps::Int = 15 # maximum steps - ls_min_scale::Float64 = 1.0e-5 # minimum scale + ls_min_scale::Float64 = 4.0e-5 # minimum scale # plateau plateau_n::Int = 3 # Plateau declared when plateau_i > plateau_n @@ -247,7 +247,7 @@ module solver # Calculate fluxes energy.calc_fluxes!(atmos, latent, convect, sens_heat, conduct, - convect_sf=convect_sf) + convect_sf=easy_sf, latent_sf=easy_sf) # Energy divergence term atmos.flux_dif[:] .-= atmos.ediv_add[:] @@ -438,10 +438,10 @@ module solver fill!(r_old, 1.0e98) # ^ energy.reset_fluxes!(atmos) # reset energy fluxes - # Modulate convection? - modulate_mlt = modulate_mlt && convect - if !modulate_mlt - convect_sf = 1.0 + # Modulate convection and phase change? + easy_start = easy_start && (convect || latent) + if !easy_start + easy_sf = 1.0 end # Initial plot @@ -509,21 +509,21 @@ module solver step_ok = step_ok && atmosphere.calc_layer_props!(atmos) # Check convective modulation - if modulate_mlt + if easy_start # We are modulating stepflags *= "M" # Check if sf needs to be increased if c_cur < max(100.0*conv_rtol, 10.0) - if convect_sf < 1.0 - # increase sf => reduce modulation by convect_incr + if easy_sf < 1.0 + # increase sf => reduce modulation by easy_incr stepflags *= "r" - convect_sf = min(1.0, convect_sf*convect_incr) - @debug "convect_sf = $convect_sf" - + easy_sf = min(1.0, easy_sf*easy_incr) + @debug "easy_sf = $easy_sf" + # done modulating - if convect_sf > 0.99 - modulate_mlt = false + if easy_sf > 0.99 + easy_start = false end end end @@ -534,7 +534,7 @@ module solver stepflags *= "-" else # No modulation at this point - convect_sf = 1.0 + easy_sf = 1.0 end # Determine which parts of the Jacobian matrix need to be updated @@ -728,7 +728,7 @@ module solver # Converged? @debug " check convergence" - if (c_cur < conv_atol + conv_rtol * c_max) && !modulate_mlt + if (c_cur < conv_atol + conv_rtol * c_max) && !easy_start code = 0 break end