From 482c8f1b1b8d25513cc66a76770070232f9502ed Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Wed, 27 Sep 2023 11:56:53 +0200 Subject: [PATCH 01/14] add reusable functions in a central file (note that this will require changes to the other apps as well) --- RisingSphere/RisingSphere_Dash.jl | 587 ++++++++++---------- RisingSphere/dash_functions_RisingSphere.jl | 36 ++ src/{dash_functions.jl => dash_tools.jl} | 96 ++-- 3 files changed, 366 insertions(+), 353 deletions(-) create mode 100644 RisingSphere/dash_functions_RisingSphere.jl rename src/{dash_functions.jl => dash_tools.jl} (90%) diff --git a/RisingSphere/RisingSphere_Dash.jl b/RisingSphere/RisingSphere_Dash.jl index 6402adb..89426ff 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/RisingSphere/RisingSphere_Dash.jl @@ -4,324 +4,331 @@ using LaMEM using UUIDs using Interpolations -GUI_version = "0.1.0" - -include("../src/dash_functions.jl") -cmaps = read_colormaps() - -title_app = "Rising Sphere example" -ParamFile = "RisingSphere.dat" -OutFile = "RiseSphere" - -base_dir = pwd() -cd(base_dir) - -# We also use a time-card that has maximum(Vz) -function make_time_card() - item = dbc_row([ - html_p(), - dbc_card([ - dbc_label(" Time : 0 Myrs", id="label-time"), - dbc_label(" Timestep : 0", id="label-timestep"), - dbc_label(" Maximum Vz : 0", id="label-max-vz"), - ], - color="secondary", - class_name="mx-auto col-11", - outline=true), - html_p()]) - return item -end - - - -#app = dash(external_stylesheets=[dbc_themes.CYBORG]) -app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP], prevent_initial_callbacks=false) -app.title = title_app - -# Main code layout -app.layout = html_div() do - dbc_container(className="mxy-auto", fluid=true, [ - make_title(title_app), - dbc_row([ - dbc_col([ - make_plot(), # show graph - make_plot_controls(), # show media buttons - make_id_label(), # show user id + + +function RisingSphere() + GUI_version = "0.1.0" + + include("dash_functions_RisingSphere.jl") + include("../src/dash_tools.jl") + cmaps = read_colormaps() + + title_app = "Rising Sphere example" + ParamFile = "RisingSphere.dat" + OutFile = "RiseSphere" + + base_dir = pwd() + cd(base_dir) + + # We also use a time-card that has maximum(Vz) + function make_time_card() + item = dbc_row([ + html_p(), + dbc_card([ + dbc_label(" Time : 0 Myrs", id="label-time"), + dbc_label(" Timestep : 0", id="label-timestep"), + dbc_label(" Maximum Vz : 0", id="label-max-vz"), + ], + color="secondary", + class_name="mx-auto col-11", + outline=true), + html_p()]) + return item + end + + + + #app = dash(external_stylesheets=[dbc_themes.CYBORG]) + app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP], prevent_initial_callbacks=false) + app.title = title_app + + # Main code layout + app.layout = html_div() do + dbc_container(className="mxy-auto", fluid=true, [ + make_title(title_app), + dbc_row([ + dbc_col([ + make_plot(), # show graph + make_plot_controls(), # show media buttons + make_id_label(), # show user id + ]), + dbc_col([ + make_time_card(), # show simulation time info + make_menu(), # show menu with simulation parameters, rheological parameters, and plotting parameters + make_run_button() # show the run simulation button + ]) ]), - dbc_col([ - make_time_card(), # show simulation time info - make_menu(), # show menu with simulation parameters, rheological parameters, and plotting parameters - make_run_button() # show the run simulation button - ]) - ]), - - # Store a unique number of our session in the webpage - dcc_store(id="session-id", data=""), - - # Store info related to the simulation and current timestep - dcc_store(id="current_timestep", data="0"), - dcc_store(id="last_timestep", data="0"), - dcc_store(id="update_fig", data="0"), - - # Start an interval that updates the number every second - dcc_interval(id="session-interval", interval=100, n_intervals=0, disabled=true) - ]) - -end - -# This creates an initial session id that is unique for this session -# it will run on first start -callback!(app, - Output("session-id", "data"), - Output("label-id", "children"), - Input("session-id", "data") -) do session_id - - session_id = UUIDs.uuid4() - str = "id=$(session_id), v=$(GUI_version)" - - - return String("$(session_id)"), str -end - -# Call run button -callback!(app, - Output("session-interval", "disabled"), - Input("button-run", "n_clicks"), - Input("button-run", "disabled"), - Input("button-play", "n_clicks"), State("domain_width", "value"), - State("nel_x", "value"), - State("nel_z", "value"), - State("n_timesteps", "value"), - State("density_sphere", "value"), - State("density_matrix", "value"), - State("radius_sphere", "value"), - State("viscosity", "value"), - State("last_timestep", "data"), - State("plot_field", "value"), - State("session-id", "data"), - prevent_initial_call=true -) do n_run, active_run, n_play, - domain_width, nel_x, nel_z, n_timesteps, - sphere_density, matrix_density, sphere_radius, viscosity, - last_timestep, plot_field, session_id - - trigger = get_trigger() - disable_interval = true - if trigger == "button-run.n_clicks" - base_dir = pwd() - - args = "-nstep_max $(n_timesteps) -radius[0] $sphere_radius -rho[0] $matrix_density -rho[1] $sphere_density -nel_x $nel_x -nel_z $nel_z -coord_x $(-domain_width/2),$(domain_width/2) -coord_z $(-domain_width/2),$(domain_width/2)" - - # We clicked the run button - user_dir = simulation_directory(session_id, clean=true) - cd(user_dir) - - pfile = joinpath(base_dir,ParamFile) - run_lamem(pfile, 1, args, wait=false) - disable_interval = false - cd(base_dir) # return to main directory - - elseif trigger == "button-run.disabled" - last_t = parse(Int, last_timestep) - if active_run == true || last_t < n_timesteps - disable_interval = false - end - elseif trigger == "button-play.n_clicks" - last_t = parse(Int, last_timestep) - @show last_t - disable_interval = false + # Store a unique number of our session in the webpage + dcc_store(id="session-id", data=""), + + # Store info related to the simulation and current timestep + dcc_store(id="current_timestep", data="0"), + dcc_store(id="last_timestep", data="0"), + dcc_store(id="update_fig", data="0"), + + # Start an interval that updates the number every second + dcc_interval(id="session-interval", interval=100, n_intervals=0, disabled=true) + ]) + end - - return disable_interval -end - -# deactivate the button -callback!(app, - Output("button-run", "disabled"), - Output("button-run", "color"), - Input("button-run", "n_clicks"), - Input("session-interval", "n_intervals"), - State("last_timestep", "data"), - State("current_timestep", "data"), - prevent_initial_call=true -) do n_run, n_inter, last_timestep, current_timestep - - cur_t = parse(Int, current_timestep) # current timestep - last_t = parse(Int, last_timestep) # last timestep available on disk - if cur_t < last_t - button_run_disable = true - button_color = "danger" - else - button_run_disable = false - button_color = "primary" + + # This creates an initial session id that is unique for this session + # it will run on first start + callback!(app, + Output("session-id", "data"), + Output("label-id", "children"), + Input("session-id", "data") + ) do session_id + + session_id = UUIDs.uuid4() + str = "id=$(session_id), v=$(GUI_version)" + + + return String("$(session_id)"), str end - return button_run_disable, button_color -end - -# Check if *.pvd file on disk changed and a new timestep is available -callback!(app, - Output("last_timestep", "data"), - Output("update_fig", "data"), - Input("session-interval", "n_intervals"), - Input("button-run", "n_clicks"), - State("current_timestep", "data"), - State("update_fig", "data"), - State("session-id", "data"), - prevent_initial_call=true -) do n_inter, n_run, current_timestep, update_fig, session_id - trigger = get_trigger() - user_dir = simulation_directory(session_id, clean=false) - if trigger == "session-interval.n_intervals" - if has_pvd_file(OutFile, user_dir) + # Call run button + callback!(app, + Output("session-interval", "disabled"), + Input("button-run", "n_clicks"), + Input("button-run", "disabled"), + Input("button-play", "n_clicks"), State("domain_width", "value"), + State("nel_x", "value"), + State("nel_z", "value"), + State("n_timesteps", "value"), + State("density_sphere", "value"), + State("density_matrix", "value"), + State("radius_sphere", "value"), + State("viscosity", "value"), + State("last_timestep", "data"), + State("plot_field", "value"), + State("session-id", "data"), + prevent_initial_call=true + ) do n_run, active_run, n_play, + domain_width, nel_x, nel_z, n_timesteps, + sphere_density, matrix_density, sphere_radius, viscosity, + last_timestep, plot_field, session_id + + trigger = get_trigger() + disable_interval = true + if trigger == "button-run.n_clicks" + base_dir = pwd() - # Read LaMEM *.pvd file - Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) + args = "-nstep_max $(n_timesteps) -radius[0] $sphere_radius -rho[0] $matrix_density -rho[1] $sphere_density -nel_x $nel_x -nel_z $nel_z -coord_x $(-domain_width/2),$(domain_width/2) -coord_z $(-domain_width/2),$(domain_width/2)" + + # We clicked the run button + user_dir = simulation_directory(session_id, clean=true) + cd(user_dir) + + pfile = joinpath(base_dir,ParamFile) + run_lamem(pfile, 1, args, wait=false) + disable_interval = false + cd(base_dir) # return to main directory - # Update the labels and data stored in webpage about the last timestep - last_time = "$(Timestep[end])" + elseif trigger == "button-run.disabled" + last_t = parse(Int, last_timestep) + if active_run == true || last_t < n_timesteps + disable_interval = false + end - update_fig = "$(parse(Int,update_fig)+1)" + elseif trigger == "button-play.n_clicks" + last_t = parse(Int, last_timestep) + @show last_t + disable_interval = false + end + + return disable_interval + end + + # deactivate the button + callback!(app, + Output("button-run", "disabled"), + Output("button-run", "color"), + Input("button-run", "n_clicks"), + Input("session-interval", "n_intervals"), + State("last_timestep", "data"), + State("current_timestep", "data"), + prevent_initial_call=true + ) do n_run, n_inter, last_timestep, current_timestep + + cur_t = parse(Int, current_timestep) # current timestep + last_t = parse(Int, last_timestep) # last timestep available on disk + if cur_t < last_t + button_run_disable = true + button_color = "danger" else - last_time = "0" - update_fig = "0" + button_run_disable = false + button_color = "primary" end - elseif trigger == "button-run.n_clicks" - last_time = "0" - update_fig = "0" + return button_run_disable, button_color end - return last_time, update_fig -end - -# Update the figure if the signal is given to do so -callback!(app, - Output("label-timestep", "children"), - Output("label-time", "children"), - Output("current_timestep", "data"), - Output("figure_main", "figure"), - Output("plot_field", "options"), - Output("contour_option", "options"), - Output("label-max-vz","children"), - Input("update_fig", "data"), - Input("current_timestep", "data"), - Input("button-run", "n_clicks"), - Input("button-start", "n_clicks"), - Input("button-last", "n_clicks"), - Input("button-forward", "n_clicks"), - Input("button-back", "n_clicks"), - Input("button-play", "n_clicks"), - State("last_timestep", "data"), - State("session-id", "data"), - State("plot_field", "value"), - State("switch-contour", "value"), - State("contour_option", "value"), - State("switch-velocity", "value"), - State("color_map_option", "value"), - prevent_initial_call=true -) do update_fig, current_timestep, n_run, n_start, n_last, n_back, n_forward, n_play, last_timestep, session_id, -plot_field, switch_contour, contour_field, switch_velocity, color_map_option - - trigger = get_trigger() - - # Get info about timesteps - cur_t = parse(Int, current_timestep) # current timestep - last_t = parse(Int, last_timestep) # last timestep available on disk - fig_cross = [] - fields_available = ["phase"] - maxVz = 0 - if trigger == "current_timestep.data" || - trigger == "update_fig.data" || - trigger == "button-start.n_clicks" || - trigger == "button-last.n_clicks" || - trigger == "button-back.n_clicks" || - trigger == "button-forward.n_clicks" || - trigger == "button-play.n_clicks" - + # Check if *.pvd file on disk changed and a new timestep is available + callback!(app, + Output("last_timestep", "data"), + Output("update_fig", "data"), + Input("session-interval", "n_intervals"), + Input("button-run", "n_clicks"), + State("current_timestep", "data"), + State("update_fig", "data"), + State("session-id", "data"), + prevent_initial_call=true + ) do n_inter, n_run, current_timestep, update_fig, session_id + trigger = get_trigger() user_dir = simulation_directory(session_id, clean=false) - if has_pvd_file(OutFile, user_dir) - - Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) # all timesteps - id = findall(Timestep .== cur_t)[1] - if trigger == "button-start.n_clicks" || trigger == "button-play.n_clicks" - cur_t = 0 - id = 1 - elseif trigger == "button-last.n_clicks" - cur_t = Timestep[end] - id = length(Timestep) - elseif (trigger == "button-forward.n_clicks") && (id < length(Timestep)) - cur_t = Timestep[id+1] - id = id + 1 - elseif (trigger == "button-back.n_clicks") && (id > 1) - cur_t = Timestep[id-1] - id = id - 1 - end + if trigger == "session-interval.n_intervals" + if has_pvd_file(OutFile, user_dir) + + # Read LaMEM *.pvd file + Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) - # Load data - x, y, Vz, time, fields_available = get_data(OutFile, cur_t, "velocity_z", user_dir) - x, y, data, time, fields_available = get_data(OutFile, cur_t, plot_field, user_dir) - - add_contours = active_switch(switch_contour) - if add_contours - x_con, y_con, data_con, _, _ = get_data(OutFile, cur_t, contour_field, user_dir) + # Update the labels and data stored in webpage about the last timestep + last_time = "$(Timestep[end])" + + update_fig = "$(parse(Int,update_fig)+1)" else - x_con, y_con, data_con = x, y, data + last_time = "0" + update_fig = "0" end + elseif trigger == "button-run.n_clicks" - # update the plot - add_velocity = active_switch(switch_velocity) - - fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con, field=plot_field, cmaps; - add_contours=add_contours, contour_field=contour_field, - add_velocity=add_velocity, - colorscale=color_map_option, - session_id=session_id) - - if trigger == "current_timestep.data" || trigger == "update_fig.data" || trigger == "button-play.n_clicks" - if cur_t < last_t - cur_t = Timestep[id+1] # update current timestep + last_time = "0" + update_fig = "0" + end + + return last_time, update_fig + end + + # Update the figure if the signal is given to do so + callback!(app, + Output("label-timestep", "children"), + Output("label-time", "children"), + Output("current_timestep", "data"), + Output("figure_main", "figure"), + Output("plot_field", "options"), + Output("contour_option", "options"), + Output("label-max-vz","children"), + Input("update_fig", "data"), + Input("current_timestep", "data"), + Input("button-run", "n_clicks"), + Input("button-start", "n_clicks"), + Input("button-last", "n_clicks"), + Input("button-forward", "n_clicks"), + Input("button-back", "n_clicks"), + Input("button-play", "n_clicks"), + State("last_timestep", "data"), + State("session-id", "data"), + State("plot_field", "value"), + State("switch-contour", "value"), + State("contour_option", "value"), + State("switch-velocity", "value"), + State("color_map_option", "value"), + prevent_initial_call=true + ) do update_fig, current_timestep, n_run, n_start, n_last, n_back, n_forward, n_play, last_timestep, session_id, + plot_field, switch_contour, contour_field, switch_velocity, color_map_option + + trigger = get_trigger() + + # Get info about timesteps + cur_t = parse(Int, current_timestep) # current timestep + last_t = parse(Int, last_timestep) # last timestep available on disk + fig_cross = [] + fields_available = ["phase"] + maxVz = 0 + if trigger == "current_timestep.data" || + trigger == "update_fig.data" || + trigger == "button-start.n_clicks" || + trigger == "button-last.n_clicks" || + trigger == "button-back.n_clicks" || + trigger == "button-forward.n_clicks" || + trigger == "button-play.n_clicks" + + user_dir = simulation_directory(session_id, clean=false) + if has_pvd_file(OutFile, user_dir) + + Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) # all timesteps + id = findall(Timestep .== cur_t)[1] + if trigger == "button-start.n_clicks" || trigger == "button-play.n_clicks" + cur_t = 0 + id = 1 + elseif trigger == "button-last.n_clicks" + cur_t = Timestep[end] + id = length(Timestep) + elseif (trigger == "button-forward.n_clicks") && (id < length(Timestep)) + cur_t = Timestep[id+1] + id = id + 1 + elseif (trigger == "button-back.n_clicks") && (id > 1) + cur_t = Timestep[id-1] + id = id - 1 + end + + # Load data + x, y, Vz, time, fields_available = get_data(OutFile, cur_t, "velocity_z", user_dir) + x, y, data, time, fields_available = get_data(OutFile, cur_t, plot_field, user_dir) + + add_contours = active_switch(switch_contour) + if add_contours + x_con, y_con, data_con, _, _ = get_data(OutFile, cur_t, contour_field, user_dir) + else + x_con, y_con, data_con = x, y, data end + + # update the plot + add_velocity = active_switch(switch_velocity) + + fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con, field=plot_field, cmaps; + add_contours=add_contours, contour_field=contour_field, + add_velocity=add_velocity, + colorscale=color_map_option, + session_id=session_id) + + if trigger == "current_timestep.data" || trigger == "update_fig.data" || trigger == "button-play.n_clicks" + if cur_t < last_t + cur_t = Timestep[id+1] # update current timestep + end + end + maxVz = maximum(Vz) + + else + time = 0 end - maxVz = maximum(Vz) - else - time = 0 + elseif trigger == "button-run.n_clicks" + cur_t = 0 + time = 0.0 end - elseif trigger == "button-run.n_clicks" - cur_t = 0 - time = 0.0 - end - - # update the labels - label_timestep = "Timestep: $cur_t" - label_time = "Time : $time Myrs" - label_maxVz = "Maximum Vz : $maxVz cm/yr" - current_timestep = "$cur_t" + # update the labels + label_timestep = "Timestep: $cur_t" + label_time = "Time : $time Myrs" + label_maxVz = "Maximum Vz : $maxVz cm/yr" + current_timestep = "$cur_t" - @show current_timestep - return label_timestep, label_time, current_timestep, fig_cross, fields_available, fields_available, label_maxVz -end + @show current_timestep + return label_timestep, label_time, current_timestep, fig_cross, fields_available, fields_available, label_maxVz + end -# Enable or disable contours -callback!(app, - Output("contour_option", "disabled"), - Input("switch-contour", "value")) do switch_contour - if !isnothing(switch_contour) - if isempty(switch_contour) - disable_contours = true + # Enable or disable contours + callback!(app, + Output("contour_option", "disabled"), + Input("switch-contour", "value")) do switch_contour + if !isnothing(switch_contour) + if isempty(switch_contour) + disable_contours = true + else + disable_contours = false + end else - disable_contours = false + disable_contours = true end - else - disable_contours = true + return disable_contours end - return disable_contours -end -run_server(app, debug=false) + run_server(app, debug=false) + + +end \ No newline at end of file diff --git a/RisingSphere/dash_functions_RisingSphere.jl b/RisingSphere/dash_functions_RisingSphere.jl new file mode 100644 index 0000000..51945c5 --- /dev/null +++ b/RisingSphere/dash_functions_RisingSphere.jl @@ -0,0 +1,36 @@ +using DelimitedFiles + +""" +Returns an accordion menu containing the rheological parameters. +""" +function make_rheological_parameters() + return dbc_accordionitem(title="Rheological Parameters", [ + make_accordion_item("ρₛ (kg/m³):", "density_sphere", "Density of the sphere in kg/m³ (0 < ρₛ ≤ 10_000.0).", 3000.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("ρₘ (kg/m³):", "density_matrix", "Density of the matrix in kg/m³ (0 < ρₛ ≤ 10_000.0).", 3400.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("rₛ (km):", "radius_sphere", "Radius of the sphere in kilometers (0 < rₛ ≤ Lₓ).", 0.1, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("ηₘ (log₁₀(Pa⋅s)):", "viscosity", "Logarithm of the viscosity of the matrix (15 < ηₘ ≤ 25).", 25.0, 15.0, 25.0), + ]) +end + + +""" +Creates a setup with noisy temperature and one phase +""" +function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100; args) + Grid = ReadLaMEM_InputFile(ParamFile, args=args) + Phases = zeros(Int64, size(Grid.X)) + Temp = ones(Float64, size(Grid.X)) * ΔT / 2 + Temp = Temp + rand(size(Temp)...) .* ampl_noise + Phases[Grid.Z.>0.0] .= 1 + Temp[Grid.Z.>0.0] .= 0.0 + + Model3D = CartData(Grid, (Phases=Phases, Temp=Temp)) # Create LaMEM model + Write_Paraview(Model3D, "LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) + + Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core + + return nothing +end diff --git a/src/dash_functions.jl b/src/dash_tools.jl similarity index 90% rename from src/dash_functions.jl rename to src/dash_tools.jl index fc51f0e..0de05d1 100644 --- a/src/dash_functions.jl +++ b/src/dash_tools.jl @@ -1,5 +1,4 @@ -using DelimitedFiles - +# various handy and reusable functions """ Creates the main figure plot. """ @@ -59,6 +58,8 @@ function create_main_figure(OutFile, cur_t, x=1:10, y=1:10, data=rand(10, 10), return pl end + + """ x, z, data = get_data(OutFile::String, tstep::Int64=0, field::String="phase", Dir="") @@ -105,7 +106,6 @@ function vector_tensor() return scalar, vector, tensor end - """ This extracts a LaMEM datafield and in case it is a tensor or scalar (and has _x, _z or so at the end). """ @@ -276,6 +276,7 @@ function read_colormaps(; dir_colormaps="../src/assets/colormaps/" , scaling=256 return colormaps end + """ Returns a row containing the title of the page. """ @@ -301,16 +302,6 @@ function make_plot() return item end -""" -Returns a column containing a screenshot button. -""" -function make_screenshot_button() - item = dbc_col([ - dbc_button("Save figure", id="button-save-fig", color="secondary", size="sg", class_name="col-4") - ], class_name="d-grid gap-2 d-md-flex justify-content-md-center") - return item -end - """ Returns a column containing all the media control buttons. """ @@ -352,6 +343,18 @@ function make_plot_controls() return item end + +""" +Returns a column containing a screenshot button. +""" +function make_screenshot_button() + item = dbc_col([ + dbc_button("Save figure", id="button-save-fig", color="secondary", size="sg", class_name="col-4") + ], class_name="d-grid gap-2 d-md-flex justify-content-md-center") + return item +end + + """ Return a row with the id of the current user session. """ @@ -360,6 +363,23 @@ function make_id_label() return item end + + +""" +Returns an accordion menu containing the simulation parameters. +""" +function make_simulation_parameters() + return dbc_accordionitem(title="Simulation Parameters", [ + make_accordion_item("Lₓ (km):", "domain_width", "Width of the domain, given in kilometers.", 1.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 64, 2), + dbc_row(html_p()), + make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 64, 2), + dbc_row(html_p()), + make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 30, 1), + ]) +end + """ Returns a row containing a card with time information of the simulation. """ @@ -405,36 +425,6 @@ function make_accordion_item(label::String="param", idx::String="id", msg::Strin return item end -""" -Returns an accordion menu containing the simulation parameters. -""" -function make_simulation_parameters() - return dbc_accordionitem(title="Simulation Parameters", [ - make_accordion_item("Lₓ (km):", "domain_width", "Width of the domain, given in kilometers.", 1.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 64, 2), - dbc_row(html_p()), - make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 64, 2), - dbc_row(html_p()), - make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 30, 1), - ]) -end - -""" -Returns an accordion menu containing the rheological parameters. -""" -function make_rheological_parameters() - return dbc_accordionitem(title="Rheological Parameters", [ - make_accordion_item("ρₛ (kg/m³):", "density_sphere", "Density of the sphere in kg/m³ (0 < ρₛ ≤ 10_000.0).", 3000.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("ρₘ (kg/m³):", "density_matrix", "Density of the matrix in kg/m³ (0 < ρₛ ≤ 10_000.0).", 3400.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("rₛ (km):", "radius_sphere", "Radius of the sphere in kilometers (0 < rₛ ≤ Lₓ).", 0.1, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("ηₘ (log₁₀(Pa⋅s)):", "viscosity", "Logarithm of the viscosity of the matrix (15 < ηₘ ≤ 25).", 25.0, 15.0, 25.0), - ]) -end - """ Returns an accordion menu containing the plotting parameters. """ @@ -526,26 +516,6 @@ function simulation_directory(session_id; clean=true) return user_dir end -""" -Creates a setup with noisy temperature and one phase -""" -function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100; args) - Grid = ReadLaMEM_InputFile(ParamFile, args=args) - Phases = zeros(Int64, size(Grid.X)) - Temp = ones(Float64, size(Grid.X)) * ΔT / 2 - Temp = Temp + rand(size(Temp)...) .* ampl_noise - Phases[Grid.Z.>0.0] .= 1 - Temp[Grid.Z.>0.0] .= 0.0 - - Model3D = CartData(Grid, (Phases=Phases, Temp=Temp)) # Create LaMEM model - Write_Paraview(Model3D, "LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) - - Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core - - return nothing -end - - has_pvd_file(OutFile, user_dir) = isfile(joinpath(user_dir, OutFile * ".pvd")) From f0bea87a2c3cb0ef7015a5ad0acd9ae09a4d5fc5 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Wed, 27 Sep 2023 15:18:54 +0200 Subject: [PATCH 02/14] this allows running the rising sphere test from any directory with: using InteractiveGeodynamics RisingSphere() --- Project.toml | 12 ++++++++++-- RisingSphere/RisingSphere_Dash.jl | 21 +++++++++++++++------ src/InteractiveGeodynamics.jl | 2 ++ src/dash_tools.jl | 14 +++++++++----- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/Project.toml b/Project.toml index cb5c726..02c692c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,11 +1,12 @@ name = "InteractiveGeodynamics" uuid = "3ccad509-8039-4f04-ad0e-35c379e37327" authors = ["Boris Kaus "] -version = "0.1.0" +version = "0.1.1" [deps] Dash = "1b08a953-4be3-4667-9a23-3db579824955" DashBootstrapComponents = "1b08a953-4be3-4667-9a23-fa6d05876a1e" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" GeophysicalModelGenerator = "3700c31b-fa53-48a6-808a-ef22d5a84742" Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" LaMEM = "2e889f3d-35ce-4a77-8ea2-858aecb630f7" @@ -16,6 +17,13 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] -GeophysicalModelGenerator = "0.4.12" +Dash = "1.3" +DashBootstrapComponents = "1.4.1" +GeophysicalModelGenerator = "0.4" +Interpolations = "0.14" LaMEM = "0.1.12" +PlotlyJS = "0.18" +Revise = "3.5.2" +Statistics = "1.9.0" julia = "1.7" +DelimitedFiles = "1.9" \ No newline at end of file diff --git a/RisingSphere/RisingSphere_Dash.jl b/RisingSphere/RisingSphere_Dash.jl index 89426ff..ca73704 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/RisingSphere/RisingSphere_Dash.jl @@ -4,13 +4,21 @@ using LaMEM using UUIDs using Interpolations +export RisingSphere +pkg_dir = pkgdir(InteractiveGeodynamics) +include(joinpath(pkg_dir,"src/dash_tools.jl")) +""" + +This starts a rising sphere GUI +""" function RisingSphere() - GUI_version = "0.1.0" + pkg_dir = pkgdir(InteractiveGeodynamics) + include(joinpath(pkg_dir,"RisingSphere/dash_functions_RisingSphere.jl")) - include("dash_functions_RisingSphere.jl") - include("../src/dash_tools.jl") + GUI_version = "0.1.0" + pkg_dir = pkgdir(InteractiveGeodynamics); cmaps = read_colormaps() title_app = "Rising Sphere example" @@ -54,7 +62,7 @@ function RisingSphere() ]), dbc_col([ make_time_card(), # show simulation time info - make_menu(), # show menu with simulation parameters, rheological parameters, and plotting parameters + make_menu(cmaps), # show menu with simulation parameters, rheological parameters, and plotting parameters make_run_button() # show the run simulation button ]) ]), @@ -113,7 +121,8 @@ function RisingSphere() trigger = get_trigger() disable_interval = true if trigger == "button-run.n_clicks" - base_dir = pwd() + cur_dir = pwd() + base_dir = joinpath(pkgdir(InteractiveGeodynamics),"RisingSphere") args = "-nstep_max $(n_timesteps) -radius[0] $sphere_radius -rho[0] $matrix_density -rho[1] $sphere_density -nel_x $nel_x -nel_z $nel_z -coord_x $(-domain_width/2),$(domain_width/2) -coord_z $(-domain_width/2),$(domain_width/2)" @@ -124,7 +133,7 @@ function RisingSphere() pfile = joinpath(base_dir,ParamFile) run_lamem(pfile, 1, args, wait=false) disable_interval = false - cd(base_dir) # return to main directory + cd(cur_dir) # return to main directory elseif trigger == "button-run.disabled" last_t = parse(Int, last_timestep) diff --git a/src/InteractiveGeodynamics.jl b/src/InteractiveGeodynamics.jl index f9c3b03..4b4faa1 100644 --- a/src/InteractiveGeodynamics.jl +++ b/src/InteractiveGeodynamics.jl @@ -1,5 +1,7 @@ module InteractiveGeodynamics +# Rising sphere app +include("../RisingSphere/RisingSphere_Dash.jl") end # module InteractiveGeodynamics diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 0de05d1..9a3d722 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -245,7 +245,11 @@ end """ This reads colormaps and transfers them into plotly format. The colormaps are supposed to be provided in ascii text format """ -function read_colormaps(; dir_colormaps="../src/assets/colormaps/" , scaling=256) +function read_colormaps(; dir_colormaps="" , scaling=256) + if isempty(dir_colormaps) + dir_colormaps=joinpath(pkgdir(InteractiveGeodynamics),"src/assets/colormaps/") + end + # Read all colormaps colormaps = NamedTuple(); for map in readdir(dir_colormaps) @@ -288,7 +292,7 @@ end """ Returns a row containing the main plot. """ -function make_plot() +function make_plot(OutFile="") item = dbc_row([ dcc_graph(id="figure_main", figure=create_main_figure(OutFile, 0), @@ -428,7 +432,7 @@ end """ Returns an accordion menu containing the plotting parameters. """ -function make_plotting_parameters() +function make_plotting_parameters(cmaps) item = dbc_accordionitem(title="Plotting Parameters", [ dbc_row([ dbc_label("Select field to plot: ", size="md"), @@ -467,12 +471,12 @@ end """ Return a row containing the menu with the simulation, rheological and plotting parameters. """ -function make_menu() +function make_menu(cmaps) item = dbc_row([ dbc_accordion(always_open=true, [ make_simulation_parameters(), make_rheological_parameters(), - make_plotting_parameters(), + make_plotting_parameters(cmaps), ]), ]) return item From a43b46d645b2c2bc96fea0791a6e2ab9b90b0dd1 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Thu, 28 Sep 2023 09:02:01 +0200 Subject: [PATCH 03/14] adapted the convection example to make it run from any directory --- RayleighBenardConvection/Convection_Dash.jl | 555 +++++++++--------- ...ctions.jl => dash_functions_convection.jl} | 123 ++-- src/InteractiveGeodynamics.jl | 9 +- src/dash_tools.jl | 27 +- 4 files changed, 381 insertions(+), 333 deletions(-) rename RayleighBenardConvection/{dash_functions.jl => dash_functions_convection.jl} (99%) diff --git a/RayleighBenardConvection/Convection_Dash.jl b/RayleighBenardConvection/Convection_Dash.jl index 13a032e..fc724e5 100644 --- a/RayleighBenardConvection/Convection_Dash.jl +++ b/RayleighBenardConvection/Convection_Dash.jl @@ -1,317 +1,340 @@ +module ConvectionTools + using Dash, DashBootstrapComponents using PlotlyJS using LaMEM using UUIDs using Interpolations using GeophysicalModelGenerator +using DelimitedFiles +export Convection -GUI_version = "0.1.0" - -include("dash_functions.jl") -cmaps = read_colormaps() - -title_app = "Rayleigh-Benard Convection" -ParamFile = "Convection.dat" -OutFile = "Convection" - -base_dir = pwd() -cd(base_dir) +pkg_dir = Base.pkgdir(ConvectionTools) -#app = dash(external_stylesheets=[dbc_themes.CYBORG]) -app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP, dbc_icons.BOOTSTRAP], prevent_initial_callbacks=false) -app.title = title_app +include(joinpath(pkg_dir,"src/dash_tools.jl")) +include(joinpath(pkg_dir,"RayleighBenardConvection/dash_functions_convection.jl")) + -# Main code layout -app.layout = html_div() do - dbc_container(className="mxy-auto", fluid=true, [ - make_title(title_app), - dbc_row([ - dbc_col([ - make_plot(), # show graph - make_plot_controls(), # show media buttons - make_id_label(), # show user id +""" + This starts a rising sphere GUI +""" +function Convection() + pkg_dir = Base.pkgdir(ConvectionTools) + cmaps = read_colormaps(dir_colormaps=joinpath(pkg_dir,"src/assets/colormaps/")) + + GUI_version = "0.1.1" + + title_app = "Rayleigh-Benard Convection" + ParamFile = "Convection.dat" + OutFile = "Convection" + + base_dir = pwd() + cd(base_dir) + + #app = dash(external_stylesheets=[dbc_themes.CYBORG]) + app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP, dbc_icons.BOOTSTRAP], prevent_initial_callbacks=false) + app.title = title_app + + # Main code layout + app.layout = html_div() do + dbc_container(className="mxy-auto", fluid=true, [ + make_title(title_app), + dbc_row([ + dbc_col([ + make_plot("",cmaps), # show graph + make_plot_controls(), # show media buttons + make_id_label(), # show user id + ]), + dbc_col([ + make_time_card(), # show simulation time info + make_menu(cmaps), # show menu with simulation parameters, rheological parameters, and plotting parameters + make_run_button() # show the run simulation button + ]) ]), - dbc_col([ - make_time_card(), # show simulation time info - make_menu(), # show menu with simulation parameters, rheological parameters, and plotting parameters - make_run_button() # show the run simulation button - ]) - ]), - # Store a unique number of our session in the webpage - dcc_store(id="session-id", data=""), + # Store a unique number of our session in the webpage + dcc_store(id="session-id", data=""), - # Store info related to the simulation and current timestep - dcc_store(id="current_timestep", data="0"), - dcc_store(id="last_timestep", data="0"), - dcc_store(id="update_fig", data="0"), + # Store info related to the simulation and current timestep + dcc_store(id="current_timestep", data="0"), + dcc_store(id="last_timestep", data="0"), + dcc_store(id="update_fig", data="0"), - # Start an interval that updates the number every second - dcc_interval(id="session-interval", interval=100, n_intervals=0, disabled=true) - ]) + # Start an interval that updates the number every second + dcc_interval(id="session-interval", interval=100, n_intervals=0, disabled=true) + ]) -end + end -# This creates an initial session id that is unique for this session -# it will run on first start -callback!(app, - Output("session-id", "data"), - Output("label-id", "children"), - Input("session-id", "data") -) do session_id - - session_id = UUIDs.uuid4() - str = "id=$(session_id), v=$(GUI_version)" - return String("$(session_id)"), str -end + # This creates an initial session id that is unique for this session + # it will run on first start + callback!(app, + Output("session-id", "data"), + Output("label-id", "children"), + Input("session-id", "data") + ) do session_id + + session_id = UUIDs.uuid4() + str = "id=$(session_id), v=$(GUI_version)" + return String("$(session_id)"), str + end -# Call run button -callback!(app, - Output("session-interval", "disabled"), - Input("button-run", "n_clicks"), - Input("button-run", "disabled"), - Input("button-play", "n_clicks"), - State("domain_width", "value"), - State("domain_height", "value"), - State("nel_x", "value"), - State("nel_z", "value"), - State("n_timesteps", "value"), - State("ΔT", "value"), - State("γ", "value"), - State("cohesion", "value"), - State("viscosity", "value"), - State("last_timestep", "data"), - State("plot_field", "value"), - State("session-id", "data"), - State("switch-FreeSurf","value"), - prevent_initial_call=true -) do n_run, active_run, n_play, - domain_width, domain_height, nel_x, nel_z, n_timesteps, - ΔT, γ, cohesion, viscosity, - last_timestep, plot_field, session_id, FreeSurface - - trigger = get_trigger() - disable_interval = true - if trigger == "button-run.n_clicks" - cd(base_dir) + # Call run button + callback!(app, + Output("session-interval", "disabled"), + Input("button-run", "n_clicks"), + Input("button-run", "disabled"), + Input("button-play", "n_clicks"), + State("domain_width", "value"), + State("domain_height", "value"), + State("nel_x", "value"), + State("nel_z", "value"), + State("n_timesteps", "value"), + State("ΔT", "value"), + State("γ", "value"), + State("cohesion", "value"), + State("viscosity", "value"), + State("last_timestep", "data"), + State("plot_field", "value"), + State("session-id", "data"), + State("switch-FreeSurf","value"), + prevent_initial_call=true + ) do n_run, active_run, n_play, + domain_width, domain_height, nel_x, nel_z, n_timesteps, + ΔT, γ, cohesion, viscosity, + last_timestep, plot_field, session_id, FreeSurface + + trigger = get_trigger() + disable_interval = true + user_dir = simulation_directory(session_id, clean=false) + if trigger == "button-run.n_clicks" + cur_dir = pwd() + base_dir = joinpath(pkgdir(ConvectionTools),"RayleighBenardConvection") + + viscosity = 10.0^viscosity + cohesion *= 1.0e6 + + Δx = domain_width/nel_x # y-width + + if FreeSurface === nothing + args = "-nstep_max $(n_timesteps) -eta_fk[0] $(viscosity) -gamma_fk[0] $γ -TRef_fk[0] $(ΔT/2) -ch[0] $(cohesion) -nel_x $nel_x -nel_z $nel_z -coord_x $(-domain_width/2),$(domain_width/2) -coord_z $(-domain_height),0 -coord_y $(-Δx/2),$(Δx/2) -temp_bot $ΔT" + else + args = "-nstep_max $(n_timesteps) -eta_fk[0] $(viscosity) -gamma_fk[0] $γ -TRef_fk[0] $(ΔT/2) -ch[0] $(cohesion) -nel_x $nel_x -coord_x $(-domain_width/2),$(domain_width/2) -coord_y $(-Δx/2),$(Δx/2) -temp_bot $ΔT" + end - viscosity = 10.0^viscosity - cohesion *= 1.0e6 + println("args = ", args) - Δx = domain_width/nel_x # y-width - - if FreeSurface === nothing - args = "-nstep_max $(n_timesteps) -eta_fk[0] $(viscosity) -gamma_fk[0] $γ -TRef_fk[0] $(ΔT/2) -ch[0] $(cohesion) -nel_x $nel_x -nel_z $nel_z -coord_x $(-domain_width/2),$(domain_width/2) -coord_z $(-domain_height),0 -coord_y $(-Δx/2),$(Δx/2) -temp_bot $ΔT" - else - args = "-nstep_max $(n_timesteps) -eta_fk[0] $(viscosity) -gamma_fk[0] $γ -TRef_fk[0] $(ΔT/2) -ch[0] $(cohesion) -nel_x $nel_x -coord_x $(-domain_width/2),$(domain_width/2) -coord_y $(-Δx/2),$(Δx/2) -temp_bot $ΔT" - end + # We clicked the run button + user_dir = simulation_directory(session_id, clean=true) + cd(user_dir) + + pfile = joinpath(base_dir,ParamFile) + CreateSetup(pfile, ΔT, args=args) + run_lamem(pfile, 1, args, wait=false) + disable_interval = false + cd(cur_dir) # return to main directory - println("args = ", args) + elseif trigger == "button-run.disabled" + last_t = parse(Int, last_timestep) + if active_run == true || last_t < n_timesteps + disable_interval = false + end - # We clicked the run button - user_dir = make_new_directory(session_id) - cd(user_dir) - - clean_directory() # removes all existing LaMEM files - pfile = base_dir * "/" * ParamFile - CreateSetup(pfile, ΔT, args=args) - run_lamem(pfile, 1, args, wait=false) - disable_interval = false - - elseif trigger == "button-run.disabled" - last_t = parse(Int, last_timestep) - if active_run == true || last_t < n_timesteps + elseif trigger == "button-play.n_clicks" + last_t = parse(Int, last_timestep) + # @show last_t disable_interval = false end - - elseif trigger == "button-play.n_clicks" - last_t = parse(Int, last_timestep) - # @show last_t - disable_interval = false + + return disable_interval end + - return disable_interval -end + # deactivate the button + callback!(app, + Output("button-run", "disabled"), + Output("button-run", "color"), + Input("button-run", "n_clicks"), + Input("session-interval", "n_intervals"), + State("last_timestep", "data"), + State("current_timestep", "data"), + prevent_initial_call=true + ) do n_run, n_inter, last_timestep, current_timestep + + cur_t = parse(Int, current_timestep) # current timestep + last_t = parse(Int, last_timestep) # last timestep available on disk + if cur_t < last_t + button_run_disable = true + button_color = "danger" + else + button_run_disable = false + button_color = "primary" + end -# deactivate the button -callback!(app, - Output("button-run", "disabled"), - Output("button-run", "color"), - Input("button-run", "n_clicks"), - Input("session-interval", "n_intervals"), - State("last_timestep", "data"), - State("current_timestep", "data"), - prevent_initial_call=true -) do n_run, n_inter, last_timestep, current_timestep - - cur_t = parse(Int, current_timestep) # current timestep - last_t = parse(Int, last_timestep) # last timestep available on disk - if cur_t < last_t - button_run_disable = true - button_color = "danger" - else - button_run_disable = false - button_color = "primary" + return button_run_disable, button_color end - return button_run_disable, button_color -end + # Check if *.pvd file on disk changed and a new timestep is available + callback!(app, + Output("last_timestep", "data"), + Output("update_fig", "data"), + Input("session-interval", "n_intervals"), + Input("button-run", "n_clicks"), + State("current_timestep", "data"), + State("update_fig", "data"), + State("session-id", "data"), + prevent_initial_call=true + ) do n_inter, n_run, current_timestep, update_fig, session_id + trigger = get_trigger() + user_dir = simulation_directory(session_id, clean=false) + if trigger == "session-interval.n_intervals" + if has_pvd_file(OutFile, user_dir) + # Read LaMEM *.pvd file + Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) + + # Update the labels and data stored in webpage about the last timestep + last_time = "$(Timestep[end])" + + update_fig = "$(parse(Int,update_fig)+1)" + else + last_time = "0" + update_fig = "0" + end + elseif trigger == "button-run.n_clicks" -# Check if *.pvd file on disk changed and a new timestep is available -callback!(app, - Output("last_timestep", "data"), - Output("update_fig", "data"), - Input("session-interval", "n_intervals"), - Input("button-run", "n_clicks"), - State("current_timestep", "data"), - State("update_fig", "data"), - State("session-id", "data"), - prevent_initial_call=true -) do n_inter, n_run, current_timestep, update_fig, session_id - trigger = get_trigger() - if trigger == "session-interval.n_intervals" - if isfile(OutFile * ".pvd") - # Read LaMEM *.pvd file - Timestep, _, Time = Read_LaMEM_simulation(OutFile) - - # Update the labels and data stored in webpage about the last timestep - last_time = "$(Timestep[end])" - - update_fig = "$(parse(Int,update_fig)+1)" - else last_time = "0" update_fig = "0" end - elseif trigger == "button-run.n_clicks" - last_time = "0" - update_fig = "0" + return last_time, update_fig end - return last_time, update_fig -end + # Update the figure if the signal is given to do so + callback!(app, + Output("label-timestep", "children"), + Output("label-time", "children"), + Output("current_timestep", "data"), + Output("figure_main", "figure"), + Output("plot_field", "options"), + Output("contour_option", "options"), + Input("update_fig", "data"), + Input("current_timestep", "data"), + Input("button-run", "n_clicks"), + Input("button-start", "n_clicks"), + Input("button-last", "n_clicks"), + Input("button-forward", "n_clicks"), + Input("button-back", "n_clicks"), + Input("button-play", "n_clicks"), + State("last_timestep", "data"), + State("session-id", "data"), + State("plot_field", "value"), + State("switch-contour", "value"), + State("contour_option", "value"), + State("switch-velocity", "value"), + State("color_map_option", "value"), + prevent_initial_call=true + ) do update_fig, current_timestep, n_run, n_start, n_last, n_back, n_forward, n_play, last_timestep, session_id, + plot_field, switch_contour, contour_field, switch_velocity, color_map_option + + trigger = get_trigger() + + # Get info about timesteps + cur_t = parse(Int, current_timestep) # current timestep + last_t = parse(Int, last_timestep) # last timestep available on disk + fig_cross = [] + fields_available = ["phase"] + if trigger == "current_timestep.data" || + trigger == "update_fig.data" || + trigger == "button-start.n_clicks" || + trigger == "button-last.n_clicks" || + trigger == "button-back.n_clicks" || + trigger == "button-forward.n_clicks" || + trigger == "button-play.n_clicks" + + user_dir = simulation_directory(session_id, clean=false) + if has_pvd_file(OutFile, user_dir) + Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) # all timesteps + id = findall(Timestep .== cur_t)[1] + if trigger == "button-start.n_clicks" || trigger == "button-play.n_clicks" + cur_t = 0 + id = 1 + elseif trigger == "button-last.n_clicks" + cur_t = Timestep[end] + id = length(Timestep) + elseif (trigger == "button-forward.n_clicks") && (id < length(Timestep)) + cur_t = Timestep[id+1] + id = id + 1 + elseif (trigger == "button-back.n_clicks") && (id > 1) + cur_t = Timestep[id-1] + id = id - 1 + end -# Update the figure if the signal is given to do so -callback!(app, - Output("label-timestep", "children"), - Output("label-time", "children"), - Output("current_timestep", "data"), - Output("figure_main", "figure"), - Output("plot_field", "options"), - Output("contour_option", "options"), - Input("update_fig", "data"), - Input("current_timestep", "data"), - Input("button-run", "n_clicks"), - Input("button-start", "n_clicks"), - Input("button-last", "n_clicks"), - Input("button-forward", "n_clicks"), - Input("button-back", "n_clicks"), - Input("button-play", "n_clicks"), - State("last_timestep", "data"), - State("session-id", "data"), - State("plot_field", "value"), - State("switch-contour", "value"), - State("contour_option", "value"), - State("switch-velocity", "value"), - State("color_map_option", "value"), - prevent_initial_call=true -) do update_fig, current_timestep, n_run, n_start, n_last, n_back, n_forward, n_play, last_timestep, session_id, -plot_field, switch_contour, contour_field, switch_velocity, color_map_option - - trigger = get_trigger() - - # Get info about timesteps - cur_t = parse(Int, current_timestep) # current timestep - last_t = parse(Int, last_timestep) # last timestep available on disk - fig_cross = [] - fields_available = ["phase"] - if trigger == "current_timestep.data" || - trigger == "update_fig.data" || - trigger == "button-start.n_clicks" || - trigger == "button-last.n_clicks" || - trigger == "button-back.n_clicks" || - trigger == "button-forward.n_clicks" || - trigger == "button-play.n_clicks" - - if isfile(OutFile * ".pvd") - Timestep, _, Time = Read_LaMEM_simulation(OutFile) # all timesteps - id = findall(Timestep .== cur_t)[1] - if trigger == "button-start.n_clicks" || trigger == "button-play.n_clicks" - cur_t = 0 - id = 1 - elseif trigger == "button-last.n_clicks" - cur_t = Timestep[end] - id = length(Timestep) - elseif (trigger == "button-forward.n_clicks") && (id < length(Timestep)) - cur_t = Timestep[id+1] - id = id + 1 - elseif (trigger == "button-back.n_clicks") && (id > 1) - cur_t = Timestep[id-1] - id = id - 1 - end + # Load data + x, y, data, time, fields_available = get_data(OutFile, cur_t, plot_field, user_dir) + add_contours = active_switch(switch_contour) + if add_contours + x_con, y_con, data_con, _, _ = get_data(OutFile, cur_t, contour_field, user_dir) + else + x_con, y_con, data_con = x, y, data + end + + # update the plot + add_velocity = active_switch(switch_velocity) + + + fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con; + add_contours=add_contours, contour_field=contour_field, + add_velocity=add_velocity, + colorscale=color_map_option, + session_id=session_id, + cmaps=cmaps, + field=plot_field) + + if trigger == "current_timestep.data" || trigger == "update_fig.data" || trigger == "button-play.n_clicks" + if cur_t < last_t + cur_t = Timestep[id+1] # update current timestep + end + end - # Load data - x, y, data, time, fields_available = get_data(OutFile, cur_t, plot_field) - if !isnothing(switch_contour) - add_contours = true - x_con, y_con, data_con, _, _ = get_data(OutFile, cur_t, contour_field) else - x_con, y_con, data_con = x, y, data - add_contours = false + time = 0 end - # update the plot - if isnothing(switch_velocity) - add_velocity = false - else - add_velocity = true - end + elseif trigger == "button-run.n_clicks" + cur_t = 0 + time = 0.0 + end + # update the labels + label_timestep = "Timestep: $cur_t" + label_time = "Time: $time Myrs" + current_timestep = "$cur_t" - fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con, field=plot_field, cmaps; - add_contours=add_contours, contour_field=contour_field, - add_velocity=add_velocity, - colorscale=color_map_option) + # @show current_timestep + println("Timsetep ", cur_t) + return label_timestep, label_time, current_timestep, fig_cross, fields_available, fields_available + end - if trigger == "current_timestep.data" || trigger == "update_fig.data" || trigger == "button-play.n_clicks" - if cur_t < last_t - cur_t = Timestep[id+1] # update current timestep - end + # + callback!(app, + Output("contour_option", "disabled"), + Input("switch-contour", "value")) do switch_contour + if !isnothing(switch_contour) + if isempty(switch_contour) + disable_contours = true + else + disable_contours = false end - else - time = 0 + disable_contours = true end - - elseif trigger == "button-run.n_clicks" - cur_t = 0 - time = 0.0 + return disable_contours end + - # update the labels - label_timestep = "Timestep: $cur_t" - label_time = "Time: $time Myrs" - current_timestep = "$cur_t" + run_server(app, debug=false) - # @show current_timestep - println("Timsetep ", cur_t) - return label_timestep, label_time, current_timestep, fig_cross, fields_available, fields_available + return app end -# -callback!(app, - Output("contour_option", "disabled"), - Input("switch-contour", "value")) do switch_contour - if !isnothing(switch_contour) - if isempty(switch_contour) - disable_contours = true - else - disable_contours = false - end - else - disable_contours = true - end - return disable_contours end - -run_server(app, debug=false) diff --git a/RayleighBenardConvection/dash_functions.jl b/RayleighBenardConvection/dash_functions_convection.jl similarity index 99% rename from RayleighBenardConvection/dash_functions.jl rename to RayleighBenardConvection/dash_functions_convection.jl index 6305a10..9a19452 100644 --- a/RayleighBenardConvection/dash_functions.jl +++ b/RayleighBenardConvection/dash_functions_convection.jl @@ -1,5 +1,46 @@ using DelimitedFiles + +""" +Returns an accordion menu containing the simulation parameters. +""" +function make_simulation_parameters() + return dbc_accordionitem(title="Simulation Parameters", [ + make_accordion_item("Width (km):", "domain_width", "Width of the domain, given in kilometers.", 2000.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("Height (km):", "domain_height", "Height of the domain, given in kilometers.", 1000.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 128, 2), + dbc_row(html_p()), + make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 64, 2), + dbc_row(html_p()), + make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 250, 1), + ]) +end + +""" +Returns an accordion menu containing the rheological parameters. +""" +function make_rheological_parameters() + return dbc_accordionitem(title="Rheological Parameters", [ + make_accordion_item("ΔT:", "ΔT", "Temperature difference between the base and the top.", 2000.0, 1.0-10, 10_000.0), + dbc_row(html_p()), + make_accordion_item("η=η₀exp(-γT), γ:", "γ", "Parameter for Frank-Kamenetzky viscosity (0.0 ≤ γ ≤ 1.0)", 0.001, 0.0, 1.0), + dbc_row(html_p()), + make_accordion_item("Cohesion (MPa):", "cohesion", "Logarithm of the cohesion of the model (0 ≤ cohesion ≤ 10_000) [MPa].", 500.0, 0.0, 10_000.0), + dbc_row(html_p()), + make_accordion_item("η (log₁₀(Pa⋅s)):", "viscosity", "Logarithm of the viscosity of the matrix (15 < η ≤ 25).", 21.0, 15.0, 25.0), + dbc_row(html_p()), + dbc_row([ + dbc_checklist(options=["FreeSurf"], + id="switch-FreeSurf", + switch=true, + ) + ]), + ]) +end + +#= """ Creates the main figure plot. """ @@ -8,7 +49,8 @@ function create_main_figure( x=-10:10, y=-10:0, data=rand(10, 20), # heatmap plot x_con=-10:10, y_con=-10:0, data_con=rand(10, 20), # contour plot cmaps=read_colormaps() # colormaps - ; colorscale="batlow", field="phase", add_contours=true, add_velocity=false, contour_field="phase") + ; colorscale="batlow", field="phase", add_contours=true, add_velocity=false, + contour_field="phase", session_id="") cbar_thk = 20 @@ -86,7 +128,29 @@ function create_main_figure( return pl end +=# +""" +Creates a setup with noisy temperature and one phase +""" +function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100; args) + Grid = ReadLaMEM_InputFile(ParamFile, args=args) + Phases = zeros(Int64, size(Grid.X)) + Temp = ones(Float64, size(Grid.X)) * ΔT / 2 + Temp = Temp + rand(size(Temp)...) .* ampl_noise + Phases[Grid.Z.>0.0] .= 1 + Temp[Grid.Z.>0.0] .= 0.0 + + Model3D = CartData(Grid, (Phases=Phases, Temp=Temp)) # Create LaMEM model + Write_Paraview(Model3D, "LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) + + Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core + + return nothing +end + + +#= """ x, z, data = get_data(OutFile::String, tstep::Int64=0, field::String="phase") @@ -457,44 +521,9 @@ function make_accordion_item(label::String="param", idx::String="id", msg::Strin return item end -""" -Returns an accordion menu containing the simulation parameters. -""" -function make_simulation_parameters() - return dbc_accordionitem(title="Simulation Parameters", [ - make_accordion_item("Width (km):", "domain_width", "Width of the domain, given in kilometers.", 2000.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("Height (km):", "domain_height", "Height of the domain, given in kilometers.", 1000.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 128, 2), - dbc_row(html_p()), - make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 64, 2), - dbc_row(html_p()), - make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 250, 1), - ]) -end -""" -Returns an accordion menu containing the rheological parameters. -""" -function make_rheological_parameters() - return dbc_accordionitem(title="Rheological Parameters", [ - make_accordion_item("ΔT:", "ΔT", "Temperature difference between the base and the top.", 2000.0, 1.0-10, 10_000.0), - dbc_row(html_p()), - make_accordion_item("η=η₀exp(-γT), γ:", "γ", "Parameter for Frank-Kamenetzky viscosity (0.0 ≤ γ ≤ 1.0)", 0.001, 0.0, 1.0), - dbc_row(html_p()), - make_accordion_item("Cohesion (MPa):", "cohesion", "Logarithm of the cohesion of the model (0 ≤ cohesion ≤ 10_000) [MPa].", 500.0, 0.0, 10_000.0), - dbc_row(html_p()), - make_accordion_item("η (log₁₀(Pa⋅s)):", "viscosity", "Logarithm of the viscosity of the matrix (15 < η ≤ 25).", 21.0, 15.0, 25.0), - dbc_row(html_p()), - dbc_row([ - dbc_checklist(options=["FreeSurf"], - id="switch-FreeSurf", - switch=true, - ) - ]), - ]) -end + + """ Returns an accordion menu containing the plotting parameters. @@ -577,21 +606,5 @@ function make_new_directory(session_id) return user_dir end -""" -Creates a setup with noisy temperature and one phase -""" -function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100; args) - Grid = ReadLaMEM_InputFile(ParamFile, args=args) - Phases = zeros(Int64, size(Grid.X)) - Temp = ones(Float64, size(Grid.X)) * ΔT / 2 - Temp = Temp + rand(size(Temp)...) .* ampl_noise - Phases[Grid.Z.>0.0] .= 1 - Temp[Grid.Z.>0.0] .= 0.0 - - Model3D = CartData(Grid, (Phases=Phases, Temp=Temp)) # Create LaMEM model - Write_Paraview(Model3D, "LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) - Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core - - return nothing -end \ No newline at end of file +=# \ No newline at end of file diff --git a/src/InteractiveGeodynamics.jl b/src/InteractiveGeodynamics.jl index 4b4faa1..28d448a 100644 --- a/src/InteractiveGeodynamics.jl +++ b/src/InteractiveGeodynamics.jl @@ -1,7 +1,14 @@ module InteractiveGeodynamics +pkg_dir = Base.pkgdir(InteractiveGeodynamics) + # Rising sphere app -include("../RisingSphere/RisingSphere_Dash.jl") +#include("../RisingSphere/RisingSphere_Dash.jl") + +# Convection app +include("../RayleighBenardConvection/Convection_Dash.jl") +using .ConvectionTools +export Convection end # module InteractiveGeodynamics diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 9a3d722..03d47de 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -3,10 +3,15 @@ Creates the main figure plot. """ function create_main_figure(OutFile, cur_t, x=1:10, y=1:10, data=rand(10, 10), - x_con=1:10, y_con=1:10, data_con=rand(10, 10), cmaps=read_colormaps() + x_con=1:10, y_con=1:10, data_con=rand(10, 10) ; - colorscale="batlow", field="phase", add_contours=true, add_velocity=false, contour_field="phase", - session_id="") + colorscale="batlow", + field="phase", + add_contours=true, + add_velocity=false, + contour_field="phase", + session_id="", + cmaps=[]) data_plot = [heatmap(x=x, y=y, @@ -246,9 +251,9 @@ end This reads colormaps and transfers them into plotly format. The colormaps are supposed to be provided in ascii text format """ function read_colormaps(; dir_colormaps="" , scaling=256) - if isempty(dir_colormaps) - dir_colormaps=joinpath(pkgdir(InteractiveGeodynamics),"src/assets/colormaps/") - end + #if isempty(dir_colormaps) + # dir_colormaps=joinpath(pkgdir(InteractiveGeodynamics),"src/assets/colormaps/") + #end # Read all colormaps colormaps = NamedTuple(); @@ -292,10 +297,10 @@ end """ Returns a row containing the main plot. """ -function make_plot(OutFile="") +function make_plot(OutFile="",cmaps=[]) item = dbc_row([ dcc_graph(id="figure_main", - figure=create_main_figure(OutFile, 0), + figure=create_main_figure(OutFile, 0, cmaps=cmaps), #animate = false, #responsive=false, #clickData = true, @@ -528,11 +533,11 @@ has_pvd_file(OutFile, user_dir) = isfile(joinpath(user_dir, OutFile * ".pvd")) Returns true if the switch is on """ function active_switch(switch) - active_switch=false; + active_switch_val=false; if !isnothing(switch) if !isempty(switch) - active_switch = true + active_switch_val = true end end - return active_switch + return active_switch_val end \ No newline at end of file From aaf8e4fdc638fb17a7f95549f342bb1f7d8585e8 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Thu, 28 Sep 2023 12:35:54 +0200 Subject: [PATCH 04/14] make convection and rising sphere examples consistent with modified way of doing things (make them work from any directory) --- RayleighBenardConvection/Convection_Dash.jl | 6 +-- RisingSphere/RisingSphere_Dash.jl | 30 +++++++------- src/InteractiveGeodynamics.jl | 9 ++++- src/dash_tools.jl | 43 ++++++++++++++++++--- 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/RayleighBenardConvection/Convection_Dash.jl b/RayleighBenardConvection/Convection_Dash.jl index fc724e5..0ee12f9 100644 --- a/RayleighBenardConvection/Convection_Dash.jl +++ b/RayleighBenardConvection/Convection_Dash.jl @@ -1,5 +1,4 @@ module ConvectionTools - using Dash, DashBootstrapComponents using PlotlyJS using LaMEM @@ -7,13 +6,14 @@ using UUIDs using Interpolations using GeophysicalModelGenerator using DelimitedFiles + export Convection pkg_dir = Base.pkgdir(ConvectionTools) include(joinpath(pkg_dir,"src/dash_tools.jl")) include(joinpath(pkg_dir,"RayleighBenardConvection/dash_functions_convection.jl")) - + """ This starts a rising sphere GUI @@ -311,7 +311,7 @@ function Convection() current_timestep = "$cur_t" # @show current_timestep - println("Timsetep ", cur_t) + println("Timestep ", cur_t) return label_timestep, label_time, current_timestep, fig_cross, fields_available, fields_available end diff --git a/RisingSphere/RisingSphere_Dash.jl b/RisingSphere/RisingSphere_Dash.jl index ca73704..bdb19a2 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/RisingSphere/RisingSphere_Dash.jl @@ -1,25 +1,25 @@ +module RisingSphereTools + using Dash, DashBootstrapComponents using PlotlyJS using LaMEM using UUIDs using Interpolations -export RisingSphere +export RisingSphere -pkg_dir = pkgdir(InteractiveGeodynamics) +pkg_dir = pkgdir(RisingSphereTools) include(joinpath(pkg_dir,"src/dash_tools.jl")) +include(joinpath(pkg_dir,"RisingSphere/dash_functions_RisingSphere.jl")) """ - -This starts a rising sphere GUI + This starts a rising sphere GUI """ function RisingSphere() - pkg_dir = pkgdir(InteractiveGeodynamics) - include(joinpath(pkg_dir,"RisingSphere/dash_functions_RisingSphere.jl")) + pkg_dir = pkgdir(RisingSphereTools) GUI_version = "0.1.0" - pkg_dir = pkgdir(InteractiveGeodynamics); - cmaps = read_colormaps() + cmaps = read_colormaps(dir_colormaps=joinpath(pkg_dir,"src/assets/colormaps/")) title_app = "Rising Sphere example" ParamFile = "RisingSphere.dat" @@ -56,7 +56,7 @@ function RisingSphere() make_title(title_app), dbc_row([ dbc_col([ - make_plot(), # show graph + make_plot("",cmaps), # show graph make_plot_controls(), # show media buttons make_id_label(), # show user id ]), @@ -101,7 +101,8 @@ function RisingSphere() Output("session-interval", "disabled"), Input("button-run", "n_clicks"), Input("button-run", "disabled"), - Input("button-play", "n_clicks"), State("domain_width", "value"), + Input("button-play", "n_clicks"), + State("domain_width", "value"), State("nel_x", "value"), State("nel_z", "value"), State("n_timesteps", "value"), @@ -122,7 +123,7 @@ function RisingSphere() disable_interval = true if trigger == "button-run.n_clicks" cur_dir = pwd() - base_dir = joinpath(pkgdir(InteractiveGeodynamics),"RisingSphere") + base_dir = joinpath(pkgdir(RisingSphereTools),"RisingSphere") args = "-nstep_max $(n_timesteps) -radius[0] $sphere_radius -rho[0] $matrix_density -rho[1] $sphere_density -nel_x $nel_x -nel_z $nel_z -coord_x $(-domain_width/2),$(domain_width/2) -coord_z $(-domain_width/2),$(domain_width/2)" @@ -287,11 +288,12 @@ function RisingSphere() # update the plot add_velocity = active_switch(switch_velocity) - fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con, field=plot_field, cmaps; + fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con; add_contours=add_contours, contour_field=contour_field, add_velocity=add_velocity, colorscale=color_map_option, - session_id=session_id) + session_id=session_id, + field=plot_field, cmaps=cmaps) if trigger == "current_timestep.data" || trigger == "update_fig.data" || trigger == "button-play.n_clicks" if cur_t < last_t @@ -340,4 +342,6 @@ function RisingSphere() run_server(app, debug=false) +end + end \ No newline at end of file diff --git a/src/InteractiveGeodynamics.jl b/src/InteractiveGeodynamics.jl index 28d448a..06553a0 100644 --- a/src/InteractiveGeodynamics.jl +++ b/src/InteractiveGeodynamics.jl @@ -1,9 +1,14 @@ module InteractiveGeodynamics -pkg_dir = Base.pkgdir(InteractiveGeodynamics) + + +#pkg_dir = Base.pkgdir(InteractiveGeodynamics) +#include(joinpath(pkg_dir,"src/dash_tools.jl")) # Rising sphere app -#include("../RisingSphere/RisingSphere_Dash.jl") +include("../RisingSphere/RisingSphere_Dash.jl") +using .RisingSphereTools +export RisingSphere # Convection app include("../RayleighBenardConvection/Convection_Dash.jl") diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 03d47de..95d0f40 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -1,3 +1,13 @@ +#module Dash_tools + +using DelimitedFiles +using Dash, DashBootstrapComponents +using PlotlyJS + +#export create_main_figure, get_data, get_trigger, read_colormaps, active_switch, has_pvd_file, +# make_title, make_plot, make_plot_controls, make_id_label, make_time_card, make_menu, +# make_accordion_item, make_rheological_parameters + # various handy and reusable functions """ Creates the main figure plot. @@ -407,9 +417,26 @@ function make_time_card() end """ -Retunrs a row containing a label, a tooltip and a filling box. +Returns a row containing a label, a tooltip and a filling box. """ -function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::Float64=1.0, min::Float64=1.0e-10, max::Float64=10_000.0) +function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::_T=1*one(_T), min=nothing, max=nothing) where _T <: Number + + if isa(_T, Float64) + if isnothing(min) + min = 1e-10 + end + if isnothing(max) + max = 10000 + end + elseif isa(_T, Int64) + if isnothing(min) + min = 2 + end + if isnothing(max) + max = 10_000 + end + end + item = dbc_row([ # domain width dbc_col([ dbc_label(label, id=idx*"_label", size="md"), @@ -420,19 +447,21 @@ function make_accordion_item(label::String="param", idx::String="id", msg::Strin return item end +#= """ -Retunrs a row containing a label, a tooltip and a filling box. +Returns a row containing a label, a tooltip and a filling box. """ -function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::Int64=2, min::Int64=2, max::Int64=10_000) +function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::Int64=2, mini::Int64=2, maxi::Int64=10_000) item = dbc_row([ # domain width dbc_col([ dbc_label(label, id=idx*"_label", size="md"), dbc_tooltip(msg, target=idx*"_label") ]), - dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=min, size="md")) + dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=mini, size="md")) ]) return item end +=# """ Returns an accordion menu containing the plotting parameters. @@ -540,4 +569,6 @@ function active_switch(switch) end end return active_switch_val -end \ No newline at end of file +end + +#end \ No newline at end of file From f776f027d5b01cce55be07c5f673b2dadaf6c060 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Thu, 28 Sep 2023 15:00:56 +0200 Subject: [PATCH 05/14] add RayleighTaylor example as well --- RayleighTaylorInstability/RTI_Dash.jl | 575 +++++++++--------- ...ash_functions.jl => dash_functions_RTI.jl} | 165 ++--- RisingSphere/RisingSphere_Dash.jl | 2 +- RisingSphere/dash_functions_RisingSphere.jl | 14 + src/InteractiveGeodynamics.jl | 9 +- src/dash_tools.jl | 15 +- 6 files changed, 397 insertions(+), 383 deletions(-) rename RayleighTaylorInstability/{dash_functions.jl => dash_functions_RTI.jl} (99%) diff --git a/RayleighTaylorInstability/RTI_Dash.jl b/RayleighTaylorInstability/RTI_Dash.jl index d417612..912e868 100644 --- a/RayleighTaylorInstability/RTI_Dash.jl +++ b/RayleighTaylorInstability/RTI_Dash.jl @@ -1,3 +1,5 @@ +module RTITools + using Dash, DashBootstrapComponents using PlotlyJS using LaMEM @@ -5,334 +7,337 @@ using UUIDs using Interpolations using GeophysicalModelGenerator -GUI_version = "0.1.0" - -include("dash_functions.jl") -cmaps = read_colormaps() +export RayleighTaylor -title_app = "Rayleigh Taylor Instability" -ParamFile = "RTI.dat" -OutFile = "RTI" +pkg_dir = Base.pkgdir(RTITools) -base_dir = pwd() -cd(base_dir) - -#app = dash(external_stylesheets=[dbc_themes.CYBORG]) -app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP, dbc_icons.BOOTSTRAP], prevent_initial_callbacks=false) -app.title = title_app +include(joinpath(pkg_dir,"src/dash_tools.jl")) +include(joinpath(pkg_dir,"RayleighTaylorInstability/dash_functions_RTI.jl")) + +""" + This starts a RayleighTaylor instability GUI +""" +function RayleighTaylor() + pkg_dir = Base.pkgdir(RTITools) + + GUI_version = "0.1.1" + cmaps = read_colormaps(dir_colormaps=joinpath(pkg_dir,"src/assets/colormaps/")) -# Main code layout -app.layout = html_div() do - dbc_container(className="mxy-auto", fluid=true, [ - make_title(title_app), - dbc_row([ - dbc_col([ - make_plot(), # show graph - make_plot_controls(), # show media buttons - make_id_label(), # show user id + title_app = "Rayleigh Taylor Instability" + ParamFile = "RTI.dat" + OutFile = "RTI" + + #app = dash(external_stylesheets=[dbc_themes.CYBORG]) + app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP, dbc_icons.BOOTSTRAP], prevent_initial_callbacks=false) + app.title = title_app + + # Main code layout + app.layout = html_div() do + dbc_container(className="mxy-auto", fluid=true, [ + make_title(title_app), + dbc_row([ + dbc_col([ + make_plot("",cmaps), # show graph + make_plot_controls(), # show media buttons + make_id_label(), # show user id + ]), + dbc_col([ + make_time_card(), # show simulation time info + make_menu(cmaps), # show menu with simulation parameters, rheological parameters, and plotting parameters + make_run_button() # show the run simulation button + ]) ]), - dbc_col([ - make_time_card(), # show simulation time info - make_menu(), # show menu with simulation parameters, rheological parameters, and plotting parameters - make_run_button() # show the run simulation button - ]) - ]), - # Store a unique number of our session in the webpage - dcc_store(id="session-id", data=""), + # Store a unique number of our session in the webpage + dcc_store(id="session-id", data=""), - # Store info related to the simulation and current timestep - dcc_store(id="current_timestep", data="0"), - dcc_store(id="last_timestep", data="0"), - dcc_store(id="update_fig", data="0"), + # Store info related to the simulation and current timestep + dcc_store(id="current_timestep", data="0"), + dcc_store(id="last_timestep", data="0"), + dcc_store(id="update_fig", data="0"), - # Start an interval that updates the number every second - dcc_interval(id="session-interval", interval=100, n_intervals=0, disabled=true) - ]) - -end + # Start an interval that updates the number every second + dcc_interval(id="session-interval", interval=100, n_intervals=0, disabled=true) + ]) -# This creates an initial session id that is unique for this session -# it will run on first start -callback!(app, - Output("session-id", "data"), - Output("label-id", "children"), - Input("session-id", "data") -) do session_id - - session_id = UUIDs.uuid4() - str = "id=$(session_id), v=$(GUI_version)" - return String("$(session_id)"), str -end - -# Call run button -callback!(app, - Output("session-interval", "disabled"), - Input("button-run", "n_clicks"), - Input("button-run", "disabled"), - Input("button-play", "n_clicks"), - State("domain_width", "value"), - State("depth", "value"), - State("nel_x", "value"), - State("nel_z", "value"), - State("n_timesteps", "value"), - State("switch-FreeSurf", "value"), - State("switch-Layers", "value"), - State("last_timestep", "data"), - State("plot_field", "value"), - State("session-id", "data"), - State("viscosity_upper", "value"), - State("viscosity_lower", "value"), - State("density_upper", "value"), - State("density_lower", "value"), - prevent_initial_call=true -) do n_run, active_run, n_play, - domain_width, depth, nel_x, nel_z, n_timesteps, - open_top, layers, - last_timestep, plot_field, session_id, - η_up,η_lo,ρ_up,ρ_lo - + end - # print(layers) - # print(open_top) + # This creates an initial session id that is unique for this session + # it will run on first start + callback!(app, + Output("session-id", "data"), + Output("label-id", "children"), + Input("session-id", "data") + ) do session_id + + session_id = UUIDs.uuid4() + str = "id=$(session_id), v=$(GUI_version)" + return String("$(session_id)"), str + end - trigger = get_trigger() - disable_interval = true - if trigger == "button-run.n_clicks" - cd(base_dir) + # Call run button + callback!(app, + Output("session-interval", "disabled"), + Input("button-run", "n_clicks"), + Input("button-run", "disabled"), + Input("button-play", "n_clicks"), + State("domain_width", "value"), + State("depth", "value"), + State("nel_x", "value"), + State("nel_z", "value"), + State("n_timesteps", "value"), + State("switch-FreeSurf", "value"), + State("switch-Layers", "value"), + State("last_timestep", "data"), + State("plot_field", "value"), + State("session-id", "data"), + State("viscosity_upper", "value"), + State("viscosity_lower", "value"), + State("density_upper", "value"), + State("density_lower", "value"), + prevent_initial_call=true + ) do n_run, active_run, n_play, + domain_width, depth, nel_x, nel_z, n_timesteps, + open_top, layers, + last_timestep, plot_field, session_id, + η_up,η_lo,ρ_up,ρ_lo - η_up = 10.0^η_up - η_lo = 10.0^η_lo - Hi_value = depth - W = domain_width - if open_top === nothing - open_top = 0 - else - open_top = 1 - end - - # print(open_top) - - if layers === nothing - layers = false - else - layers = true - end - - # print(layers)c + # print(layers) + # print(open_top) - args = "-nstep_max $(n_timesteps) -eta[0] $η_up -eta[1] $η_up -eta[2] $η_lo -rho[0] $ρ_up -rho[1] $ρ_up -rho[2] $ρ_lo -open_top_bound $open_top -nel_x $nel_x -nel_z $nel_z -coord_x $(-W/2),$(W/2)" - println("args = ", args) + trigger = get_trigger() + disable_interval = true + if trigger == "button-run.n_clicks" + cur_dir = pwd() + base_dir = joinpath(pkgdir(RTITools),"RayleighTaylorInstability") + + + η_up = 10.0^η_up + η_lo = 10.0^η_lo + Hi_value = depth + W = domain_width + open_top_bound = active_switch(open_top) + + # print(open_top) + addlayers = active_switch(layers) + + # print(layers)c + + + args = "-nstep_max $(n_timesteps) -eta[0] $η_up -eta[1] $η_up -eta[2] $η_lo -rho[0] $ρ_up -rho[1] $ρ_up -rho[2] $ρ_lo -open_top_bound $(Int64(open_top_bound)) -nel_x $nel_x -nel_z $nel_z -coord_x $(-W/2),$(W/2)" + println("args = ", args) + + # We clicked the run button + user_dir = simulation_directory(session_id, clean=true) + cd(user_dir) + + pfile = joinpath(base_dir,ParamFile) + + # Create the setup + CreateSetup(pfile, addlayers, Hi_value, args=args) + + run_lamem(pfile, 1, args, wait=false) + cd(cur_dir) # return to main directory - - # We clicked the run button - user_dir = make_new_directory(session_id) - cd(user_dir) - clean_directory() # removes all existing LaMEM files - pfile = base_dir * "/" * ParamFile - - # Create the setup - CreateSetup(pfile, layers, Hi_value, args=args) - - run_lamem(pfile, 1, args, wait=false) + disable_interval = false - disable_interval = false + elseif trigger == "button-run.disabled" + last_t = parse(Int, last_timestep) + if active_run == true || last_t < n_timesteps + disable_interval = false + end - elseif trigger == "button-run.disabled" - last_t = parse(Int, last_timestep) - if active_run == true || last_t < n_timesteps + elseif trigger == "button-play.n_clicks" + last_t = parse(Int, last_timestep) + # @show last_t disable_interval = false end - - elseif trigger == "button-play.n_clicks" - last_t = parse(Int, last_timestep) - # @show last_t - disable_interval = false + + return disable_interval end - - return disable_interval -end -# deactivate the button -callback!(app, - Output("button-run", "disabled"), - Output("button-run", "color"), - Input("button-run", "n_clicks"), - Input("session-interval", "n_intervals"), - State("last_timestep", "data"), - State("current_timestep", "data"), - prevent_initial_call=true -) do n_run, n_inter, last_timestep, current_timestep - - cur_t = parse(Int, current_timestep) # current timestep - last_t = parse(Int, last_timestep) # last timestep available on disk - if cur_t < last_t - button_run_disable = true - button_color = "danger" - else - button_run_disable = false - button_color = "primary" + # deactivate the button + callback!(app, + Output("button-run", "disabled"), + Output("button-run", "color"), + Input("button-run", "n_clicks"), + Input("session-interval", "n_intervals"), + State("last_timestep", "data"), + State("current_timestep", "data"), + prevent_initial_call=true + ) do n_run, n_inter, last_timestep, current_timestep + + cur_t = parse(Int, current_timestep) # current timestep + last_t = parse(Int, last_timestep) # last timestep available on disk + if cur_t < last_t + button_run_disable = true + button_color = "danger" + else + button_run_disable = false + button_color = "primary" + end + + return button_run_disable, button_color end - return button_run_disable, button_color -end + # Check if *.pvd file on disk changed and a new timestep is available + callback!(app, + Output("last_timestep", "data"), + Output("update_fig", "data"), + Input("session-interval", "n_intervals"), + Input("button-run", "n_clicks"), + State("current_timestep", "data"), + State("update_fig", "data"), + State("session-id", "data"), + prevent_initial_call=true + ) do n_inter, n_run, current_timestep, update_fig, session_id + trigger = get_trigger() + user_dir = simulation_directory(session_id, clean=false) + if trigger == "session-interval.n_intervals" + if has_pvd_file(OutFile, user_dir) + # Read LaMEM *.pvd file + Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) + + # Update the labels and data stored in webpage about the last timestep + last_time = "$(Timestep[end])" + + update_fig = "$(parse(Int,update_fig)+1)" + else + last_time = "0" + update_fig = "0" + end + elseif trigger == "button-run.n_clicks" -# Check if *.pvd file on disk changed and a new timestep is available -callback!(app, - Output("last_timestep", "data"), - Output("update_fig", "data"), - Input("session-interval", "n_intervals"), - Input("button-run", "n_clicks"), - State("current_timestep", "data"), - State("update_fig", "data"), - State("session-id", "data"), - prevent_initial_call=true -) do n_inter, n_run, current_timestep, update_fig, session_id - trigger = get_trigger() - if trigger == "session-interval.n_intervals" - if isfile(OutFile * ".pvd") - # Read LaMEM *.pvd file - Timestep, _, Time = Read_LaMEM_simulation(OutFile) - - # Update the labels and data stored in webpage about the last timestep - last_time = "$(Timestep[end])" - - update_fig = "$(parse(Int,update_fig)+1)" - else last_time = "0" update_fig = "0" end - elseif trigger == "button-run.n_clicks" - last_time = "0" - update_fig = "0" + return last_time, update_fig end - return last_time, update_fig -end + # Update the figure if the signal is given to do so + callback!(app, + Output("label-timestep", "children"), + Output("label-time", "children"), + Output("current_timestep", "data"), + Output("figure_main", "figure"), + Output("plot_field", "options"), + Output("contour_option", "options"), + Input("update_fig", "data"), + Input("current_timestep", "data"), + Input("button-run", "n_clicks"), + Input("button-start", "n_clicks"), + Input("button-last", "n_clicks"), + Input("button-forward", "n_clicks"), + Input("button-back", "n_clicks"), + Input("button-play", "n_clicks"), + State("last_timestep", "data"), + State("session-id", "data"), + State("plot_field", "value"), + State("switch-contour", "value"), + State("contour_option", "value"), + State("switch-velocity", "value"), + State("color_map_option", "value"), + prevent_initial_call=true + ) do update_fig, current_timestep, n_run, n_start, n_last, n_back, n_forward, n_play, last_timestep, session_id, + plot_field, switch_contour, contour_field, switch_velocity, color_map_option + + trigger = get_trigger() + + # Get info about timesteps + cur_t = parse(Int, current_timestep) # current timestep + last_t = parse(Int, last_timestep) # last timestep available on disk + fig_cross = [] + fields_available = ["phase"] + if trigger == "current_timestep.data" || + trigger == "update_fig.data" || + trigger == "button-start.n_clicks" || + trigger == "button-last.n_clicks" || + trigger == "button-back.n_clicks" || + trigger == "button-forward.n_clicks" || + trigger == "button-play.n_clicks" + + user_dir = simulation_directory(session_id, clean=false) + if has_pvd_file(OutFile, user_dir) + Timestep, _, Time = Read_LaMEM_simulation(OutFile, user_dir) # all timesteps + id = findall(Timestep .== cur_t)[1] + if trigger == "button-start.n_clicks" || trigger == "button-play.n_clicks" + cur_t = 0 + id = 1 + elseif trigger == "button-last.n_clicks" + cur_t = Timestep[end] + id = length(Timestep) + elseif (trigger == "button-forward.n_clicks") && (id < length(Timestep)) + cur_t = Timestep[id+1] + id = id + 1 + elseif (trigger == "button-back.n_clicks") && (id > 1) + cur_t = Timestep[id-1] + id = id - 1 + end -# Update the figure if the signal is given to do so -callback!(app, - Output("label-timestep", "children"), - Output("label-time", "children"), - Output("current_timestep", "data"), - Output("figure_main", "figure"), - Output("plot_field", "options"), - Output("contour_option", "options"), - Input("update_fig", "data"), - Input("current_timestep", "data"), - Input("button-run", "n_clicks"), - Input("button-start", "n_clicks"), - Input("button-last", "n_clicks"), - Input("button-forward", "n_clicks"), - Input("button-back", "n_clicks"), - Input("button-play", "n_clicks"), - State("last_timestep", "data"), - State("session-id", "data"), - State("plot_field", "value"), - State("switch-contour", "value"), - State("contour_option", "value"), - State("switch-velocity", "value"), - State("color_map_option", "value"), - prevent_initial_call=true -) do update_fig, current_timestep, n_run, n_start, n_last, n_back, n_forward, n_play, last_timestep, session_id, -plot_field, switch_contour, contour_field, switch_velocity, color_map_option - - trigger = get_trigger() - - # Get info about timesteps - cur_t = parse(Int, current_timestep) # current timestep - last_t = parse(Int, last_timestep) # last timestep available on disk - fig_cross = [] - fields_available = ["phase"] - if trigger == "current_timestep.data" || - trigger == "update_fig.data" || - trigger == "button-start.n_clicks" || - trigger == "button-last.n_clicks" || - trigger == "button-back.n_clicks" || - trigger == "button-forward.n_clicks" || - trigger == "button-play.n_clicks" - - if isfile(OutFile * ".pvd") - Timestep, _, Time = Read_LaMEM_simulation(OutFile) # all timesteps - id = findall(Timestep .== cur_t)[1] - if trigger == "button-start.n_clicks" || trigger == "button-play.n_clicks" - cur_t = 0 - id = 1 - elseif trigger == "button-last.n_clicks" - cur_t = Timestep[end] - id = length(Timestep) - elseif (trigger == "button-forward.n_clicks") && (id < length(Timestep)) - cur_t = Timestep[id+1] - id = id + 1 - elseif (trigger == "button-back.n_clicks") && (id > 1) - cur_t = Timestep[id-1] - id = id - 1 - end + # Load data + x, y, data, time, fields_available = get_data(OutFile, cur_t, plot_field, user_dir) + add_contours = active_switch(switch_contour) + if add_contours + x_con, y_con, data_con, _, _ = get_data(OutFile, cur_t, contour_field, user_dir) + else + x_con, y_con, data_con = x, y, data + end - # Load data - x, y, data, time, fields_available = get_data(OutFile, cur_t, plot_field) - if !isnothing(switch_contour) - add_contours = true - x_con, y_con, data_con, _, _ = get_data(OutFile, cur_t, contour_field) - else - x_con, y_con, data_con = x, y, data - add_contours = false - end - # update the plot + # update the plot + add_velocity = active_switch(switch_velocity) + + fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con; + add_contours=add_contours, contour_field=contour_field, + add_velocity=add_velocity, + colorscale=color_map_option, + session_id=session_id, + field=plot_field, cmaps=cmaps) + + if trigger == "current_timestep.data" || trigger == "update_fig.data" || trigger == "button-play.n_clicks" + if cur_t < last_t + cur_t = Timestep[id+1] # update current timestep + end + end - if isnothing(switch_velocity) - add_velocity = false else - add_velocity = true + time = 0 end + elseif trigger == "button-run.n_clicks" + cur_t = 0 + time = 0.0 + end - fig_cross = create_main_figure(OutFile, cur_t, x, y, data, x_con, y_con, data_con, field=plot_field, cmaps; - add_contours=add_contours, contour_field=contour_field, - add_velocity=add_velocity, - colorscale=color_map_option) + # update the labels + label_timestep = "Timestep: $cur_t" + label_time = "Time: $time Myrs" + current_timestep = "$cur_t" - if trigger == "current_timestep.data" || trigger == "update_fig.data" || trigger == "button-play.n_clicks" - if cur_t < last_t - cur_t = Timestep[id+1] # update current timestep - end - end + # @show current_timestep + println("Timestep ", current_timestep) + return label_timestep, label_time, current_timestep, fig_cross, fields_available, fields_available + end + # + callback!(app, + Output("contour_option", "disabled"), + Input("switch-contour", "value")) do switch_contour + if !isnothing(switch_contour) + if isempty(switch_contour) + disable_contours = true + else + disable_contours = false + end else - time = 0 + disable_contours = true end - - elseif trigger == "button-run.n_clicks" - cur_t = 0 - time = 0.0 + return disable_contours end - # update the labels - label_timestep = "Timestep: $cur_t" - label_time = "Time: $time Myrs" - current_timestep = "$cur_t" + run_server(app, debug=false) - # @show current_timestep - println("Timestep ", current_timestep) - return label_timestep, label_time, current_timestep, fig_cross, fields_available, fields_available end -# -callback!(app, - Output("contour_option", "disabled"), - Input("switch-contour", "value")) do switch_contour - if !isnothing(switch_contour) - if isempty(switch_contour) - disable_contours = true - else - disable_contours = false - end - else - disable_contours = true - end - return disable_contours end - -run_server(app, debug=false) diff --git a/RayleighTaylorInstability/dash_functions.jl b/RayleighTaylorInstability/dash_functions_RTI.jl similarity index 99% rename from RayleighTaylorInstability/dash_functions.jl rename to RayleighTaylorInstability/dash_functions_RTI.jl index 8feefde..7c21802 100644 --- a/RayleighTaylorInstability/dash_functions.jl +++ b/RayleighTaylorInstability/dash_functions_RTI.jl @@ -1,5 +1,90 @@ using DelimitedFiles + +""" +Returns an accordion menu containing the rheological parameters. +""" +function make_rheological_parameters() + return dbc_accordionitem(title="Rheological Parameters", [ + make_accordion_item("η_up(log₁₀(Pa⋅s)):", "viscosity_upper", "Logarithm of the viscosity of the upper layers.", 21.0, 16.0, 23.0), + dbc_row(html_p()), + make_accordion_item("η_lo(log₁₀(Pa⋅s)):", "viscosity_lower", "Logarithm of the viscosity of the lower layer", 20.0, 16.0, 23.0), + dbc_row(html_p()), + make_accordion_item("ρ_up:", "density_upper", "Density of the upper layers.", 2800.0, 2.0, 5000.0), + dbc_row(html_p()), + make_accordion_item("ρ_lo:", "density_lower", "Density of the lower layer.", 2200.0, 2.0, 5000.0), + ]) +end + +""" +Returns an accordion menu containing the simulation parameters. +""" +function make_simulation_parameters() + return dbc_accordionitem(title="Simulation Parameters", [ + make_accordion_item("Width (km):", "domain_width", "Width of the domain, given in kilometers.", 10.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("Depth of the interface (km):", "depth", "Depth of the interface, given in kilometers.", -2.5, -50.0), + dbc_row(html_p()), + make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 64, 2), + dbc_row(html_p()), + make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 32, 2), + dbc_row(html_p()), + make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 50, 1), + dbc_row(html_p()), + dbc_row([ + dbc_checklist(options=["FreeSurf"], + id="switch-FreeSurf", + switch=true, + ) + ]), + dbc_row(html_p()), + dbc_row([ + dbc_checklist(options=["Layers"], + id="switch-Layers", + switch=true, + ) + ]) + ]) +end + +""" +Creates a setup with noisy temperature and one phase +""" +function CreateSetup(ParamFile, layered_overburden=false, Hi=-5.0, ampl_noise=0.1, ; args) + Grid = ReadLaMEM_InputFile(ParamFile, args=args) + Phases = zeros(Int64, size(Grid.X)); + Temp = zeros(Float64,size(Grid.X)); + + + if layered_overburden + H_layer = 0.25; + for z_low = minimum(Grid.Z):2*H_layer:maximum(Grid.Z) + # print(z_low) + # z_low = -z_low + iz = findall( (Grid.Z[1,1,:] .> z_low) .& (Grid.Z[1,1,:] .<= (z_low+H_layer) )) + Phases[:,:,iz] .= 1; + end + end + + z_int = ones(Grid.nump_x)*Hi + rand(Grid.nump_x)*ampl_noise + # print(z_int) + # z_int = -z_int + for ix=1:Grid.nump_x, iy=1:Grid.nump_y + iz = findall(Grid.Z[ix,iy,:] .< z_int[ix] ) + Phases[ix,iy,iz] .= 2; + end + + # print(z_int) + + Model3D = CartData(Grid, (Phases=Phases,Temp=Temp)) # Create LaMEM model + Write_Paraview(Model3D,"LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) + + Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core + + return nothing +end + +#= """ Creates the main figure plot. """ @@ -457,51 +542,7 @@ function make_accordion_item(label::String="param", idx::String="id", msg::Strin return item end -""" -Returns an accordion menu containing the simulation parameters. -""" -function make_simulation_parameters() - return dbc_accordionitem(title="Simulation Parameters", [ - make_accordion_item("Width (km):", "domain_width", "Width of the domain, given in kilometers.", 10.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("Depth of the interface (km):", "depth", "Depth of the interface, given in kilometers.", -2.5, -50.0), - dbc_row(html_p()), - make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 32, 2), - dbc_row(html_p()), - make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 16, 2), - dbc_row(html_p()), - make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 50, 1), - dbc_row(html_p()), - dbc_row([ - dbc_checklist(options=["FreeSurf"], - id="switch-FreeSurf", - switch=true, - ) - ]), - dbc_row(html_p()), - dbc_row([ - dbc_checklist(options=["Layers"], - id="switch-Layers", - switch=true, - ) - ]) - ]) -end -""" -Returns an accordion menu containing the rheological parameters. -""" -function make_rheological_parameters() - return dbc_accordionitem(title="Rheological Parameters", [ - make_accordion_item("η_up(log₁₀(Pa⋅s)):", "viscosity_upper", "Logarithm of the viscosity of the upper layers.", 21.0, 16.0, 23.0), - dbc_row(html_p()), - make_accordion_item("η_lo(log₁₀(Pa⋅s)):", "viscosity_lower", "Logarithm of the viscosity of the lower layer", 20.0, 16.0, 23.0), - dbc_row(html_p()), - make_accordion_item("ρ_up:", "density_upper", "Density of the upper layers.", 2800.0, 2.0, 5000.0), - dbc_row(html_p()), - make_accordion_item("ρ_lo:", "density_lower", "Density of the lower layer.", 2200.0, 2.0, 5000.0), - ]) -end """ Returns an accordion menu containing the plotting parameters. @@ -584,39 +625,5 @@ function make_new_directory(session_id) return user_dir end -""" -Creates a setup with noisy temperature and one phase -""" -function CreateSetup(ParamFile, layered_overburden=false, Hi=-5.0, ampl_noise=0.1, ; args) - Grid = ReadLaMEM_InputFile(ParamFile, args=args) - Phases = zeros(Int64, size(Grid.X)); - Temp = zeros(Float64,size(Grid.X)); - - if layered_overburden - H_layer = 0.25; - for z_low = minimum(Grid.Z):2*H_layer:maximum(Grid.Z) - # print(z_low) - # z_low = -z_low - iz = findall( (Grid.Z[1,1,:] .> z_low) .& (Grid.Z[1,1,:] .<= (z_low+H_layer) )) - Phases[:,:,iz] .= 1; - end - end - - z_int = ones(Grid.nump_x)*Hi + rand(Grid.nump_x)*ampl_noise - # print(z_int) - # z_int = -z_int - for ix=1:Grid.nump_x, iy=1:Grid.nump_y - iz = findall(Grid.Z[ix,iy,:] .< z_int[ix] ) - Phases[ix,iy,iz] .= 2; - end - - # print(z_int) - - Model3D = CartData(Grid, (Phases=Phases,Temp=Temp)) # Create LaMEM model - Write_Paraview(Model3D,"LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) - - Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core - - return nothing -end \ No newline at end of file +=# \ No newline at end of file diff --git a/RisingSphere/RisingSphere_Dash.jl b/RisingSphere/RisingSphere_Dash.jl index bdb19a2..61a724c 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/RisingSphere/RisingSphere_Dash.jl @@ -341,7 +341,7 @@ function RisingSphere() run_server(app, debug=false) - + return app end end \ No newline at end of file diff --git a/RisingSphere/dash_functions_RisingSphere.jl b/RisingSphere/dash_functions_RisingSphere.jl index 51945c5..e589bf3 100644 --- a/RisingSphere/dash_functions_RisingSphere.jl +++ b/RisingSphere/dash_functions_RisingSphere.jl @@ -15,6 +15,20 @@ function make_rheological_parameters() ]) end +""" +Returns an accordion menu containing the simulation parameters. +""" +function make_simulation_parameters() + return dbc_accordionitem(title="Simulation Parameters", [ + make_accordion_item("Lₓ (km):", "domain_width", "Width of the domain, given in kilometers.", 1.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 64, 2), + dbc_row(html_p()), + make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 64, 2), + dbc_row(html_p()), + make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 30, 1), + ]) +end """ Creates a setup with noisy temperature and one phase diff --git a/src/InteractiveGeodynamics.jl b/src/InteractiveGeodynamics.jl index 06553a0..7f06b7c 100644 --- a/src/InteractiveGeodynamics.jl +++ b/src/InteractiveGeodynamics.jl @@ -1,15 +1,16 @@ module InteractiveGeodynamics - -#pkg_dir = Base.pkgdir(InteractiveGeodynamics) -#include(joinpath(pkg_dir,"src/dash_tools.jl")) - # Rising sphere app include("../RisingSphere/RisingSphere_Dash.jl") using .RisingSphereTools export RisingSphere +# RayleighTaylor app +include("../RayleighTaylorInstability/RTI_Dash.jl") +using .RTITools +export RayleighTaylor + # Convection app include("../RayleighBenardConvection/Convection_Dash.jl") using .ConvectionTools diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 95d0f40..0166a86 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -384,20 +384,7 @@ end -""" -Returns an accordion menu containing the simulation parameters. -""" -function make_simulation_parameters() - return dbc_accordionitem(title="Simulation Parameters", [ - make_accordion_item("Lₓ (km):", "domain_width", "Width of the domain, given in kilometers.", 1.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 64, 2), - dbc_row(html_p()), - make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 64, 2), - dbc_row(html_p()), - make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 30, 1), - ]) -end + """ Returns a row containing a card with time information of the simulation. From ed0af4c307fd3d964b06d29d8d964f1228f0c04e Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Thu, 28 Sep 2023 17:30:13 +0200 Subject: [PATCH 06/14] allow specifying http and port for the GUIs --- Project.toml | 4 +++- RayleighBenardConvection/Convection_Dash.jl | 10 +++++++--- RayleighTaylorInstability/RTI_Dash.jl | 10 ++++++---- RisingSphere/RisingSphere_Dash.jl | 9 ++++++--- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Project.toml b/Project.toml index 02c692c..be53de8 100644 --- a/Project.toml +++ b/Project.toml @@ -8,6 +8,7 @@ Dash = "1b08a953-4be3-4667-9a23-3db579824955" DashBootstrapComponents = "1b08a953-4be3-4667-9a23-fa6d05876a1e" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" GeophysicalModelGenerator = "3700c31b-fa53-48a6-808a-ef22d5a84742" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" LaMEM = "2e889f3d-35ce-4a77-8ea2-858aecb630f7" PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" @@ -19,11 +20,12 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] Dash = "1.3" DashBootstrapComponents = "1.4.1" +DelimitedFiles = "1.9" GeophysicalModelGenerator = "0.4" Interpolations = "0.14" LaMEM = "0.1.12" PlotlyJS = "0.18" Revise = "3.5.2" Statistics = "1.9.0" +HTTP = "1" julia = "1.7" -DelimitedFiles = "1.9" \ No newline at end of file diff --git a/RayleighBenardConvection/Convection_Dash.jl b/RayleighBenardConvection/Convection_Dash.jl index 0ee12f9..d153e55 100644 --- a/RayleighBenardConvection/Convection_Dash.jl +++ b/RayleighBenardConvection/Convection_Dash.jl @@ -6,6 +6,7 @@ using UUIDs using Interpolations using GeophysicalModelGenerator using DelimitedFiles +using HTTP export Convection @@ -16,9 +17,11 @@ include(joinpath(pkg_dir,"RayleighBenardConvection/dash_functions_convection.jl" """ - This starts a rising sphere GUI + Convection(host=HTTP.Sockets.localhost, port=8050) + +This starts a convection GUI """ -function Convection() +function Convection(host=HTTP.Sockets.localhost, port=8050) pkg_dir = Base.pkgdir(ConvectionTools) cmaps = read_colormaps(dir_colormaps=joinpath(pkg_dir,"src/assets/colormaps/")) @@ -332,7 +335,8 @@ function Convection() end - run_server(app, debug=false) + run_server(app, host, port, debug=false) + return app end diff --git a/RayleighTaylorInstability/RTI_Dash.jl b/RayleighTaylorInstability/RTI_Dash.jl index 912e868..a341dd0 100644 --- a/RayleighTaylorInstability/RTI_Dash.jl +++ b/RayleighTaylorInstability/RTI_Dash.jl @@ -6,6 +6,7 @@ using LaMEM using UUIDs using Interpolations using GeophysicalModelGenerator +using HTTP export RayleighTaylor @@ -15,9 +16,11 @@ include(joinpath(pkg_dir,"src/dash_tools.jl")) include(joinpath(pkg_dir,"RayleighTaylorInstability/dash_functions_RTI.jl")) """ - This starts a RayleighTaylor instability GUI + RayleighTaylor(; host=HTTP.Sockets.localhost, port=8050) + +This starts a RayleighTaylor instability GUI """ -function RayleighTaylor() +function RayleighTaylor(; host=HTTP.Sockets.localhost, port=8050) pkg_dir = Base.pkgdir(RTITools) GUI_version = "0.1.1" @@ -124,7 +127,6 @@ function RayleighTaylor() # print(layers)c - args = "-nstep_max $(n_timesteps) -eta[0] $η_up -eta[1] $η_up -eta[2] $η_lo -rho[0] $ρ_up -rho[1] $ρ_up -rho[2] $ρ_lo -open_top_bound $(Int64(open_top_bound)) -nel_x $nel_x -nel_z $nel_z -coord_x $(-W/2),$(W/2)" println("args = ", args) @@ -336,7 +338,7 @@ function RayleighTaylor() return disable_contours end - run_server(app, debug=false) + run_server(app, host, port, debug=false) end diff --git a/RisingSphere/RisingSphere_Dash.jl b/RisingSphere/RisingSphere_Dash.jl index 61a724c..f34da18 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/RisingSphere/RisingSphere_Dash.jl @@ -5,6 +5,7 @@ using PlotlyJS using LaMEM using UUIDs using Interpolations +using HTTP export RisingSphere @@ -13,9 +14,11 @@ include(joinpath(pkg_dir,"src/dash_tools.jl")) include(joinpath(pkg_dir,"RisingSphere/dash_functions_RisingSphere.jl")) """ - This starts a rising sphere GUI + RisingSphere(host=HTTP.Sockets.localhost, port=8050) + +This starts a rising sphere GUI """ -function RisingSphere() +function RisingSphere(host=HTTP.Sockets.localhost, port=8050) pkg_dir = pkgdir(RisingSphereTools) GUI_version = "0.1.0" @@ -339,7 +342,7 @@ function RisingSphere() end - run_server(app, debug=false) + run_server(app, host, port, debug=false) return app end From 9aad33f2b2c4bbc5efcaefdf2aa714b41edb4279 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Fri, 29 Sep 2023 16:25:01 +0200 Subject: [PATCH 07/14] update versions of LaMEM & GMG --- Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index be53de8..e76095f 100644 --- a/Project.toml +++ b/Project.toml @@ -21,9 +21,9 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" Dash = "1.3" DashBootstrapComponents = "1.4.1" DelimitedFiles = "1.9" -GeophysicalModelGenerator = "0.4" +GeophysicalModelGenerator = "0.5" Interpolations = "0.14" -LaMEM = "0.1.12" +LaMEM = "0.2" PlotlyJS = "0.18" Revise = "3.5.2" Statistics = "1.9.0" From 54ed02eebd4ebfa7a44bb8589f71d68d119e6822 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Fri, 29 Sep 2023 16:28:20 +0200 Subject: [PATCH 08/14] bugfixes to allow specifying a host & port --- RayleighBenardConvection/Convection_Dash.jl | 4 ++-- RayleighTaylorInstability/RTI_Dash.jl | 2 +- RisingSphere/RisingSphere_Dash.jl | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/RayleighBenardConvection/Convection_Dash.jl b/RayleighBenardConvection/Convection_Dash.jl index d153e55..1dc1a97 100644 --- a/RayleighBenardConvection/Convection_Dash.jl +++ b/RayleighBenardConvection/Convection_Dash.jl @@ -17,11 +17,11 @@ include(joinpath(pkg_dir,"RayleighBenardConvection/dash_functions_convection.jl" """ - Convection(host=HTTP.Sockets.localhost, port=8050) + Convection(; host=HTTP.Sockets.localhost, port=8050) This starts a convection GUI """ -function Convection(host=HTTP.Sockets.localhost, port=8050) +function Convection(; host=HTTP.Sockets.localhost, port=8050) pkg_dir = Base.pkgdir(ConvectionTools) cmaps = read_colormaps(dir_colormaps=joinpath(pkg_dir,"src/assets/colormaps/")) diff --git a/RayleighTaylorInstability/RTI_Dash.jl b/RayleighTaylorInstability/RTI_Dash.jl index a341dd0..7c77f3a 100644 --- a/RayleighTaylorInstability/RTI_Dash.jl +++ b/RayleighTaylorInstability/RTI_Dash.jl @@ -20,7 +20,7 @@ include(joinpath(pkg_dir,"RayleighTaylorInstability/dash_functions_RTI.jl")) This starts a RayleighTaylor instability GUI """ -function RayleighTaylor(; host=HTTP.Sockets.localhost, port=8050) +function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) pkg_dir = Base.pkgdir(RTITools) GUI_version = "0.1.1" diff --git a/RisingSphere/RisingSphere_Dash.jl b/RisingSphere/RisingSphere_Dash.jl index f34da18..55cdd0f 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/RisingSphere/RisingSphere_Dash.jl @@ -14,11 +14,11 @@ include(joinpath(pkg_dir,"src/dash_tools.jl")) include(joinpath(pkg_dir,"RisingSphere/dash_functions_RisingSphere.jl")) """ - RisingSphere(host=HTTP.Sockets.localhost, port=8050) + RisingSphere(; host=HTTP.Sockets.localhost, port=8050) This starts a rising sphere GUI """ -function RisingSphere(host=HTTP.Sockets.localhost, port=8050) +function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) pkg_dir = pkgdir(RisingSphereTools) GUI_version = "0.1.0" From bc9635602cd4de5252e35144cfe06db27413bc4f Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Sat, 30 Sep 2023 21:24:04 +0200 Subject: [PATCH 09/14] newer versions of LaMEM.jl have a different output format for vectors and tensors --- src/dash_tools.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 0166a86..43278e5 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -83,9 +83,8 @@ This loads the timestep `tstep` from a LaMEM simulation with field `field`. function get_data(OutFile::String, tstep::Int64=0, field::String="phase", Dir="") data,time = Read_LaMEM_timestep(OutFile, tstep, Dir) - + value = extract_data_fields(data, field) # get field; can handle tensors & vectors as well - fields= String.(keys(data.fields)) fields_available = get_fields(fields) @@ -139,7 +138,7 @@ function extract_data_fields(data, field) else id = findall(tensor.=="_"*extension)[1] end - value = data.fields[Symbol(name)][id,:,:,:] + value = data.fields[Symbol(name)][id] end return value end From 760921928cabfde130c5d611ee72ae1c3b6601d1 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Sat, 30 Sep 2023 21:29:42 +0200 Subject: [PATCH 10/14] make apps compatible with newer LaMEM version --- RayleighBenardConvection/Convection_Dash.jl | 28 +++++++++---------- RayleighTaylorInstability/RTI_Dash.jl | 28 +++++++++---------- RisingSphere/RisingSphere_Dash.jl | 30 ++++++++++----------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/RayleighBenardConvection/Convection_Dash.jl b/RayleighBenardConvection/Convection_Dash.jl index 1dc1a97..68e2b7a 100644 --- a/RayleighBenardConvection/Convection_Dash.jl +++ b/RayleighBenardConvection/Convection_Dash.jl @@ -72,8 +72,8 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) # This creates an initial session id that is unique for this session # it will run on first start callback!(app, - Output("session-id", "data"), - Output("label-id", "children"), + Dash.Output("session-id", "data"), + Dash.Output("label-id", "children"), Input("session-id", "data") ) do session_id @@ -84,7 +84,7 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) # Call run button callback!(app, - Output("session-interval", "disabled"), + Dash.Output("session-interval", "disabled"), Input("button-run", "n_clicks"), Input("button-run", "disabled"), Input("button-play", "n_clicks"), @@ -155,8 +155,8 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) # deactivate the button callback!(app, - Output("button-run", "disabled"), - Output("button-run", "color"), + Dash.Output("button-run", "disabled"), + Dash.Output("button-run", "color"), Input("button-run", "n_clicks"), Input("session-interval", "n_intervals"), State("last_timestep", "data"), @@ -179,8 +179,8 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) # Check if *.pvd file on disk changed and a new timestep is available callback!(app, - Output("last_timestep", "data"), - Output("update_fig", "data"), + Dash.Output("last_timestep", "data"), + Dash.Output("update_fig", "data"), Input("session-interval", "n_intervals"), Input("button-run", "n_clicks"), State("current_timestep", "data"), @@ -214,12 +214,12 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) # Update the figure if the signal is given to do so callback!(app, - Output("label-timestep", "children"), - Output("label-time", "children"), - Output("current_timestep", "data"), - Output("figure_main", "figure"), - Output("plot_field", "options"), - Output("contour_option", "options"), + Dash.Output("label-timestep", "children"), + Dash.Output("label-time", "children"), + Dash.Output("current_timestep", "data"), + Dash.Output("figure_main", "figure"), + Dash.Output("plot_field", "options"), + Dash.Output("contour_option", "options"), Input("update_fig", "data"), Input("current_timestep", "data"), Input("button-run", "n_clicks"), @@ -320,7 +320,7 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) # callback!(app, - Output("contour_option", "disabled"), + Dash.Output("contour_option", "disabled"), Input("switch-contour", "value")) do switch_contour if !isnothing(switch_contour) if isempty(switch_contour) diff --git a/RayleighTaylorInstability/RTI_Dash.jl b/RayleighTaylorInstability/RTI_Dash.jl index 7c77f3a..a080dc0 100644 --- a/RayleighTaylorInstability/RTI_Dash.jl +++ b/RayleighTaylorInstability/RTI_Dash.jl @@ -68,8 +68,8 @@ function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) # This creates an initial session id that is unique for this session # it will run on first start callback!(app, - Output("session-id", "data"), - Output("label-id", "children"), + Dash.Output("session-id", "data"), + Dash.Output("label-id", "children"), Input("session-id", "data") ) do session_id @@ -80,7 +80,7 @@ function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) # Call run button callback!(app, - Output("session-interval", "disabled"), + Dash.Output("session-interval", "disabled"), Input("button-run", "n_clicks"), Input("button-run", "disabled"), Input("button-play", "n_clicks"), @@ -161,8 +161,8 @@ function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) # deactivate the button callback!(app, - Output("button-run", "disabled"), - Output("button-run", "color"), + Dash.Output("button-run", "disabled"), + Dash.Output("button-run", "color"), Input("button-run", "n_clicks"), Input("session-interval", "n_intervals"), State("last_timestep", "data"), @@ -185,8 +185,8 @@ function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) # Check if *.pvd file on disk changed and a new timestep is available callback!(app, - Output("last_timestep", "data"), - Output("update_fig", "data"), + Dash.Output("last_timestep", "data"), + Dash.Output("update_fig", "data"), Input("session-interval", "n_intervals"), Input("button-run", "n_clicks"), State("current_timestep", "data"), @@ -220,12 +220,12 @@ function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) # Update the figure if the signal is given to do so callback!(app, - Output("label-timestep", "children"), - Output("label-time", "children"), - Output("current_timestep", "data"), - Output("figure_main", "figure"), - Output("plot_field", "options"), - Output("contour_option", "options"), + Dash.Output("label-timestep", "children"), + Dash.Output("label-time", "children"), + Dash.Output("current_timestep", "data"), + Dash.Output("figure_main", "figure"), + Dash.Output("plot_field", "options"), + Dash.Output("contour_option", "options"), Input("update_fig", "data"), Input("current_timestep", "data"), Input("button-run", "n_clicks"), @@ -324,7 +324,7 @@ function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) # callback!(app, - Output("contour_option", "disabled"), + Dash.Output("contour_option", "disabled"), Input("switch-contour", "value")) do switch_contour if !isnothing(switch_contour) if isempty(switch_contour) diff --git a/RisingSphere/RisingSphere_Dash.jl b/RisingSphere/RisingSphere_Dash.jl index 55cdd0f..a0ba204 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/RisingSphere/RisingSphere_Dash.jl @@ -87,8 +87,8 @@ function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) # This creates an initial session id that is unique for this session # it will run on first start callback!(app, - Output("session-id", "data"), - Output("label-id", "children"), + Dash.Output("session-id", "data"), + Dash.Output("label-id", "children"), Input("session-id", "data") ) do session_id @@ -101,7 +101,7 @@ function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) # Call run button callback!(app, - Output("session-interval", "disabled"), + Dash.Output("session-interval", "disabled"), Input("button-run", "n_clicks"), Input("button-run", "disabled"), Input("button-play", "n_clicks"), @@ -156,8 +156,8 @@ function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) # deactivate the button callback!(app, - Output("button-run", "disabled"), - Output("button-run", "color"), + Dash.Output("button-run", "disabled"), + Dash.Output("button-run", "color"), Input("button-run", "n_clicks"), Input("session-interval", "n_intervals"), State("last_timestep", "data"), @@ -180,8 +180,8 @@ function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) # Check if *.pvd file on disk changed and a new timestep is available callback!(app, - Output("last_timestep", "data"), - Output("update_fig", "data"), + Dash.Output("last_timestep", "data"), + Dash.Output("update_fig", "data"), Input("session-interval", "n_intervals"), Input("button-run", "n_clicks"), State("current_timestep", "data"), @@ -216,13 +216,13 @@ function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) # Update the figure if the signal is given to do so callback!(app, - Output("label-timestep", "children"), - Output("label-time", "children"), - Output("current_timestep", "data"), - Output("figure_main", "figure"), - Output("plot_field", "options"), - Output("contour_option", "options"), - Output("label-max-vz","children"), + Dash.Output("label-timestep", "children"), + Dash.Output("label-time", "children"), + Dash.Output("current_timestep", "data"), + Dash.Output("figure_main", "figure"), + Dash.Output("plot_field", "options"), + Dash.Output("contour_option", "options"), + Dash.Output("label-max-vz","children"), Input("update_fig", "data"), Input("current_timestep", "data"), Input("button-run", "n_clicks"), @@ -327,7 +327,7 @@ function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) # Enable or disable contours callback!(app, - Output("contour_option", "disabled"), + Dash.Output("contour_option", "disabled"), Input("switch-contour", "value")) do switch_contour if !isnothing(switch_contour) if isempty(switch_contour) From 4e6b5b7baf8f095a0ae288478de2c3fc8ee434fe Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Sat, 30 Sep 2023 22:15:56 +0200 Subject: [PATCH 11/14] moved apps to /src --- .../dash_functions_RTI.jl | 629 ------------------ src/InteractiveGeodynamics.jl | 6 +- .../RayleighBenardConvection}/Convection.dat | 0 .../Convection_Dash.jl | 4 +- .../Convection_LaMEM.jl | 0 .../dash_functions_convection.jl | 93 +-- .../RayleighTaylorInstability}/RTI.dat | 0 .../RayleighTaylorInstability}/RTI_Dash.jl | 4 +- .../RayleighTaylorInstability}/RTI_LaMEM.jl | 0 .../dash_functions_RTI.jl | 85 +++ {RisingSphere => src/RisingSphere}/.gitignore | 0 .../RisingSphere}/RisingSphere.dat | 0 .../RisingSphere}/RisingSphere_Dash.jl | 4 +- .../RisingSphere}/RisingSphere_LaMEM.jl | 0 .../dash_functions_RisingSphere.jl | 4 +- src/dash_tools.jl | 31 +- 16 files changed, 111 insertions(+), 749 deletions(-) delete mode 100644 RayleighTaylorInstability/dash_functions_RTI.jl rename {RayleighBenardConvection => src/RayleighBenardConvection}/Convection.dat (100%) rename {RayleighBenardConvection => src/RayleighBenardConvection}/Convection_Dash.jl (98%) rename {RayleighBenardConvection => src/RayleighBenardConvection}/Convection_LaMEM.jl (100%) rename {RayleighBenardConvection => src/RayleighBenardConvection}/dash_functions_convection.jl (85%) rename {RayleighTaylorInstability => src/RayleighTaylorInstability}/RTI.dat (100%) rename {RayleighTaylorInstability => src/RayleighTaylorInstability}/RTI_Dash.jl (98%) rename {RayleighTaylorInstability => src/RayleighTaylorInstability}/RTI_LaMEM.jl (100%) create mode 100644 src/RayleighTaylorInstability/dash_functions_RTI.jl rename {RisingSphere => src/RisingSphere}/.gitignore (100%) rename {RisingSphere => src/RisingSphere}/RisingSphere.dat (100%) rename {RisingSphere => src/RisingSphere}/RisingSphere_Dash.jl (98%) rename {RisingSphere => src/RisingSphere}/RisingSphere_LaMEM.jl (100%) rename {RisingSphere => src/RisingSphere}/dash_functions_RisingSphere.jl (95%) diff --git a/RayleighTaylorInstability/dash_functions_RTI.jl b/RayleighTaylorInstability/dash_functions_RTI.jl deleted file mode 100644 index 7c21802..0000000 --- a/RayleighTaylorInstability/dash_functions_RTI.jl +++ /dev/null @@ -1,629 +0,0 @@ -using DelimitedFiles - - -""" -Returns an accordion menu containing the rheological parameters. -""" -function make_rheological_parameters() - return dbc_accordionitem(title="Rheological Parameters", [ - make_accordion_item("η_up(log₁₀(Pa⋅s)):", "viscosity_upper", "Logarithm of the viscosity of the upper layers.", 21.0, 16.0, 23.0), - dbc_row(html_p()), - make_accordion_item("η_lo(log₁₀(Pa⋅s)):", "viscosity_lower", "Logarithm of the viscosity of the lower layer", 20.0, 16.0, 23.0), - dbc_row(html_p()), - make_accordion_item("ρ_up:", "density_upper", "Density of the upper layers.", 2800.0, 2.0, 5000.0), - dbc_row(html_p()), - make_accordion_item("ρ_lo:", "density_lower", "Density of the lower layer.", 2200.0, 2.0, 5000.0), - ]) -end - -""" -Returns an accordion menu containing the simulation parameters. -""" -function make_simulation_parameters() - return dbc_accordionitem(title="Simulation Parameters", [ - make_accordion_item("Width (km):", "domain_width", "Width of the domain, given in kilometers.", 10.0, 1.0e-10), - dbc_row(html_p()), - make_accordion_item("Depth of the interface (km):", "depth", "Depth of the interface, given in kilometers.", -2.5, -50.0), - dbc_row(html_p()), - make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 64, 2), - dbc_row(html_p()), - make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 32, 2), - dbc_row(html_p()), - make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 50, 1), - dbc_row(html_p()), - dbc_row([ - dbc_checklist(options=["FreeSurf"], - id="switch-FreeSurf", - switch=true, - ) - ]), - dbc_row(html_p()), - dbc_row([ - dbc_checklist(options=["Layers"], - id="switch-Layers", - switch=true, - ) - ]) - ]) -end - -""" -Creates a setup with noisy temperature and one phase -""" -function CreateSetup(ParamFile, layered_overburden=false, Hi=-5.0, ampl_noise=0.1, ; args) - Grid = ReadLaMEM_InputFile(ParamFile, args=args) - Phases = zeros(Int64, size(Grid.X)); - Temp = zeros(Float64,size(Grid.X)); - - - if layered_overburden - H_layer = 0.25; - for z_low = minimum(Grid.Z):2*H_layer:maximum(Grid.Z) - # print(z_low) - # z_low = -z_low - iz = findall( (Grid.Z[1,1,:] .> z_low) .& (Grid.Z[1,1,:] .<= (z_low+H_layer) )) - Phases[:,:,iz] .= 1; - end - end - - z_int = ones(Grid.nump_x)*Hi + rand(Grid.nump_x)*ampl_noise - # print(z_int) - # z_int = -z_int - for ix=1:Grid.nump_x, iy=1:Grid.nump_y - iz = findall(Grid.Z[ix,iy,:] .< z_int[ix] ) - Phases[ix,iy,iz] .= 2; - end - - # print(z_int) - - Model3D = CartData(Grid, (Phases=Phases,Temp=Temp)) # Create LaMEM model - Write_Paraview(Model3D,"LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) - - Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core - - return nothing -end - -#= -""" -Creates the main figure plot. -""" -function create_main_figure( - OutFile, cur_t, - x=-10:10, y=-10:0, data=rand(10, 20), # heatmap plot - x_con=-10:10, y_con=-10:0, data_con=rand(10, 20), # contour plot - cmaps=read_colormaps() # colormaps - ; colorscale="batlow", field="phase", add_contours=true, add_velocity=false, contour_field="phase") - - cbar_thk = 20 - - # add heatmap - data_plot = [ - heatmap( - x=x, - y=y, - z=data, - colorscale=cmaps[Symbol(colorscale)], - colorbar=attr(thickness=cbar_thk, title=field) - ) - ] - # add contours - if add_contours == true - push!( - data_plot, ( - contour( - x=x_con, - y=y_con, - z=data_con, - colorscale=cmaps[Symbol(colorscale)], - contours_coloring="lines", - line_width=2, - colorbar=attr(thickness=cbar_thk, title=contour_field, x=1.1, yanchor=0.5, contour_label=true), - ) - ) - ) - end - # add velocity - if add_velocity == true - arrowhead, line = calculate_quiver(OutFile, cur_t, cmaps; colorscale="batlow") - push!(data_plot, arrowhead) - push!(data_plot, line) - end - - pl = (id="fig_cross", - data=data_plot, - # colorbar=Dict("orientation" => "v", "len" => 0.5), - - layout=( - - # width="320vw", height="320vh", - xaxis=attr( - title="Width (km)", - tickfont_size=14, - tickfont_color="rgb(100, 100, 100)", - showgrid=false, - # zeroline=false, - # automargin=true, - # constrain="domain", - scaleanchor="y", - scaleratio=1.0, - showline=true, linewidth=2, linecolor="black", mirror=true, - ), - yaxis=attr( - title="Depth (km)", - # domain=[0,100], - tickfont_size=14, - tickfont_color="rgb(10, 10, 10)", - showgrid=false, - showline=true, linewidth=2, linecolor="black", mirror=true, - # range=[-10,0], - # zeroline=false, - # scaleanchor="x", - # scaleratio=1.0, - # constrain="domain", - # constrain="range", - ), margin=Dict([("l", 50), ("r", 50)])#), margin=Dict([("l", 350), ("r", 350)]) - ), - config=(edits = (shapePosition=true,)), scaleratio=1.0 - - - ) - - return pl -end - -""" - x, z, data = get_data(OutFile::String, tstep::Int64=0, field::String="phase") - -This loads the timestep `tstep` from a LaMEM simulation with field `field`. -""" -function get_data(OutFile::String, tstep::Int64=0, field::String="phase") - - data,time = Read_LaMEM_timestep(OutFile, tstep) - - value = extract_data_fields(data, field) # get field; can handle tensors & vectors as well - - - fields= String.(keys(data.fields)) - fields_available = get_fields(fields) - - x = data.x.val[:,1,1] - z = data.z.val[1,1,:] - - data2D = value[:,1,:]' - - return x, z, data2D, time[1], fields_available -end - -""" -Returns the trigger callback (simplifies code). -""" -function get_trigger() - - tr = callback_context().triggered; - trigger = [] - if !isempty(tr) - trigger = callback_context().triggered[1] - trigger = trigger[1] - end - return trigger -end - -""" -Add-ons to names for vector & tensors (used in dropdown menu). -""" -function vector_tensor() - vector = [ "_$a" for a in ["x","y","z"]] - tensor = [ "_$(b)$(a)" for a in ["x","y","z"], b in ["x","y","z"] ][:] - scalar = [""] - return scalar, vector, tensor -end - -""" -This extracts a LaMEM datafield and in case it is a tensor or scalar (and has _x, _z or so at the end). -""" -function extract_data_fields(data, field) - - _, vector, tensor = vector_tensor() - if hasfield(typeof(data.fields),Symbol(field)) # scalar - value = data.fields[Symbol(field)] - else # vector/tensor - extension = split(field,"_")[end] - n = length(extension) - name = field[1:end-n-1] - - if n==1 - id = findall(vector.=="_"*extension)[1] - else - id = findall(tensor.=="_"*extension)[1] - end - value = data.fields[Symbol(name)][id,:,:,:] - end - return value -end - -""" -Returns a list with fields. In case the LaMEM field is a vector field, it adds _x, _y etc; im case of tensor, _xx, _xy etc. -""" -function get_fields(fields) - - scalar, vector, tensor = vector_tensor() - - fields_available= [] - for f in fields - if f=="velocity" - add = vector - elseif f=="strain_rate" || f=="stress" - add = tensor - else - add = scalar - end - for a in add - push!(fields_available, f*a) - end - end - return fields_available -end - -""" -Functions building up to quiver plot -""" -function extract_velocity(OutFile, cur_t) - - data, _ = Read_LaMEM_timestep(OutFile, cur_t) - Vx = data.fields.velocity[1,:,1,:] - Vz = data.fields.velocity[3,:,1,:] - x_vel = data.x.val[:,1,1] - z_vel = data.z.val[1,1,:] - - return Vx, Vz, x_vel, z_vel -end - -""" -Interpolate velocities. -""" -function interpolate_velocities(x, z, Vx, Vz) - - # interpolate velocities to a quarter of original grid density - itp_Vx = interpolate((x, z), Vx, Gridded(Linear())) - itp_Vz = interpolate((x, z), Vz, Gridded(Linear())) - - interpolation_coords_x = LinRange(x[1], x[end], 15) - interpolation_coords_z = LinRange(z[1], z[end], 15) - - Vx_interpolated = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - Vz_interpolated = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - - itp_coords_x = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - itp_coords_z = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - - itp_coords_x = repeat(interpolation_coords_x, outer=length(interpolation_coords_z)) - itp_coords_z = repeat(interpolation_coords_z, inner=length(interpolation_coords_x)) - - for i in eachindex(itp_coords_x) - Vx_interpolated[i] = itp_Vx(itp_coords_x[i], itp_coords_z[i]) - Vz_interpolated[i] = itp_Vz(itp_coords_x[i], itp_coords_z[i]) - end - - return Vx_interpolated, Vz_interpolated, itp_coords_x, itp_coords_z -end - -""" -Calculate angle between two vectors. -""" -function calculate_angle(Vx_interpolated, Vz_interpolated) - angle = zeros(size(Vx_interpolated)) - north = [1, 0] - for i in eachindex(angle) - angle[i] = asind((north[1] * Vx_interpolated[i] + north[2] * Vz_interpolated[i]) / (sqrt(north[1]^2 + north[2]^2) * sqrt(Vx_interpolated[i]^2 + Vz_interpolated[i]^2))) - if isnan(angle[i]) == true - angle[i] = 180.0 - end - if angle[i] < 90 && angle[i] > -90 && Vz_interpolated[i] < 0 - angle[i] = 180.0 - angle[i] - end - end - return angle -end - -""" -Calculate quiver. -""" -function calculate_quiver(OutFile, cur_t, cmaps; colorscale="batlow") - - Vx, Vz, x, z = extract_velocity(OutFile, cur_t) - Vx_interpolated, Vy_interpolated, interpolation_coords_x, interpolation_coords_z = interpolate_velocities(x, z, Vx, Vz) - angle = calculate_angle(Vx_interpolated, Vy_interpolated) - magnitude = sqrt.(Vx_interpolated .^ 2 .+ Vy_interpolated .^ 2) - - arrow_head = scatter( - x=interpolation_coords_x, - y=interpolation_coords_z, - mode="markers", - colorscale=cmaps[Symbol(colorscale)], - marker=attr(size=15, color=magnitude, angle=angle, symbol="triangle-up"), - colorbar=attr(title="Velocity", thickness=5, x=1.4), - ) - - line = scatter( - x=interpolation_coords_x, - y=interpolation_coords_z, - mode="markers", - colorscale=cmaps[Symbol(colorscale)], - marker=attr(size=10, color=magnitude, angle=angle, symbol="line-ns", line=attr(width=2, color=magnitude)), - ) - return arrow_head, line -end - -""" -This reads colormaps and transfers them into plotly format. The colormaps are supposed to be provided in ascii text format -""" -function read_colormaps(; dir_colormaps="../src/assets/colormaps/" , scaling=256) - # Read all colormaps - colormaps = NamedTuple(); - for map in readdir(dir_colormaps) - data = readdlm(dir_colormaps*map) - name_str = map[1:end-4] - - if contains(name_str,"reverse") - reverse=true - data = data[end:-1:1,:] - else - reverse=false - end - - name = Symbol(name_str) - - # apply scaling - data_rgb = Int64.(round.(data*scaling)) - - # Create the format that plotly wants: - n = size(data,1) - fac = range(0,1,n) - data_col = [ [fac[i], "rgb($(data_rgb[i,1]),$(data_rgb[i,2]),$(data_rgb[i,3]))"] for i=1:n] - - col = NamedTuple{(name,)}((data_col,)) - colormaps = merge(colormaps, col) - end - - return colormaps -end - -""" -Returns a row containing the title of the page. -""" -function make_title(title_app::String) - item = dbc_row(html_h1(title_app), style=Dict("margin-top" => 0, "textAlign" => "center")) - return item -end - -""" -Returns a row containing the main plot. -""" -function make_plot() - # w = - # h = - item = dbc_row([ - dcc_graph(id="figure_main", - figure=create_main_figure(OutFile, 0), - #animate = false, - # responsive=true, - #clickData = true, - #config = PlotConfig(displayModeBar=false, scrollZoom = false), - style=attr(width="80vw", height="80vh"), - # style=attr(width="80vw"), - ) - ]) - return item -end - -""" -Returns a column containing a screenshot button. -""" -function make_screenshot_button() - item = dbc_col([ - dbc_button("Save figure", id="button-save-fig", color="secondary", size="sg", class_name="col-4") - ], class_name="d-grid gap-2 d-md-flex justify-content-md-center") - return item -end - -""" -Returns a column containing all the media control buttons. -""" -function make_media_buttons() - item = dbc_col([ - dbc_button( - [ - html_i(className="bi bi-skip-backward-fill"), - ], - id="button-start", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - dbc_button( - [ - html_i(className="bi bi-skip-start-fill"), - ], - id="button-back", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - dbc_button( - [ - html_i(className="bi bi-play-fill"), - ], - id="button-play", outline=true, color="primary", size="sg", class_name="d-flex align-items-center" - ), - dbc_button( - [ - html_i(className="bi bi-skip-end-fill"), - ], - id="button-forward", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - dbc_button( - [ - html_i(className="bi bi-skip-forward-fill"), - ], - id="button-last", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - ], class_name="d-grid gap-2 d-md-flex justify-content-md-center") - return item -end - -""" -Retunrs an empty column. -""" -function make_empty_col() - return dbc_col([]) -end - -""" -Retunrs an empty row. -""" -function make_empty_row() - return dbc_row([]) -end - -""" -Returns a row containing the media buttons, each one in a column. -""" -function make_plot_controls() - item = dbc_row([ - # make_screenshot_button(), - make_empty_col(), - make_media_buttons(), - make_empty_col(), - ]) - return item -end - -""" -Return a row with the id of the current user session. -""" -function make_id_label() - item = dbc_row([dbc_label("", id="label-id", color="secondary")]) - return item -end - -""" -Returns a row containing a card with time information of the simulation. -""" -function make_time_card() - item = dbc_row([ - html_p(), - dbc_card([ - dbc_label(" Time: 0 Myrs", id="label-time"), - dbc_label(" Timestep: 0", id="label-timestep" - )], - color="secondary", - class_name="mx-auto col-11", - outline=true), - html_p()]) - return item -end - -""" -Retunrs a row containing a label, a tooltip and a filling box. -""" -function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::Float64=1.0, min::Float64=1.0e-10, max::Float64=10_000.0) - item = dbc_row([ # domain width - dbc_col([ - dbc_label(label, id=idx*"_label", size="md"), - dbc_tooltip(msg, target=idx*"_label") - ]), - dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=min, size="md")) - ]) - return item -end - -""" -Retunrs a row containing a label, a tooltip and a filling box. -""" -function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::Int64=2, min::Int64=2, max::Int64=10_000) - item = dbc_row([ # domain width - dbc_col([ - dbc_label(label, id=idx*"_label", size="md"), - dbc_tooltip(msg, target=idx*"_label") - ]), - dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=min, size="md")) - ]) - return item -end - - - -""" -Returns an accordion menu containing the plotting parameters. -""" -function make_plotting_parameters() - item = dbc_accordionitem(title="Plotting Parameters", [ - dbc_row([ - dbc_label("Select field to plot: ", size="md"), - dcc_dropdown(id="plot_field", options = ["phase"], value="phase", className="col-12") - ]), - dbc_row(html_p()), - dbc_row([ # color map - dbc_col([ - dbc_label("Colormap:", id="cmap", size="md"), - dbc_tooltip(target="cmap", "Choose the colormap of the plot") - ]), - dbc_col(dcc_dropdown(id="color_map_option", options = String.(keys(cmaps)), value=String.(keys(cmaps))[1])) - ]), - dbc_row(html_p()), - dbc_row(html_hr()), - dbc_row([ - dbc_checklist(options=["Overlap plot with contour:"], - id="switch-contour", - switch=true, - ), - dbc_row(html_p()), - dbc_col(dcc_dropdown(id="contour_option" ,options = ["phase"], value="phase", disabled=true)) - ]), - dbc_row(html_p()), - dbc_row(html_hr()), - dbc_row([ - dbc_checklist(options=["Overlap velocity"], - id="switch-velocity", - switch=true, - ) - ]), - ]) - return item -end - -""" -Return a row containing the menu with the simulation, rheological and plotting parameters. -""" -function make_menu() - item = dbc_row([ - dbc_accordion(always_open=true, [ - make_simulation_parameters(), - make_rheological_parameters(), - make_plotting_parameters(), - ]), - ]) - return item -end - -""" -Returns a row containing the RUN button. -""" -function make_run_button() - item = dbc_row([ - html_p(), - dbc_button("RUN", id="button-run", size="lg", class_name="col-11 mx-auto"), - html_p()]) - return item -end - -""" -Create a new directory named by session-id -""" -function make_new_directory(session_id) - dirname = String(session_id) - if isdir("simulations") - if isdir("simulations/" * dirname) == false - mkdir("simulations/" * dirname) - end - else - mkdir("simulations") - mkdir("simulations/" * dirname) - end - user_dir = "simulations/" * dirname - return user_dir -end - - -=# \ No newline at end of file diff --git a/src/InteractiveGeodynamics.jl b/src/InteractiveGeodynamics.jl index 7f06b7c..f467222 100644 --- a/src/InteractiveGeodynamics.jl +++ b/src/InteractiveGeodynamics.jl @@ -2,17 +2,17 @@ module InteractiveGeodynamics # Rising sphere app -include("../RisingSphere/RisingSphere_Dash.jl") +include("./RisingSphere/RisingSphere_Dash.jl") using .RisingSphereTools export RisingSphere # RayleighTaylor app -include("../RayleighTaylorInstability/RTI_Dash.jl") +include("./RayleighTaylorInstability/RTI_Dash.jl") using .RTITools export RayleighTaylor # Convection app -include("../RayleighBenardConvection/Convection_Dash.jl") +include("./RayleighBenardConvection/Convection_Dash.jl") using .ConvectionTools export Convection diff --git a/RayleighBenardConvection/Convection.dat b/src/RayleighBenardConvection/Convection.dat similarity index 100% rename from RayleighBenardConvection/Convection.dat rename to src/RayleighBenardConvection/Convection.dat diff --git a/RayleighBenardConvection/Convection_Dash.jl b/src/RayleighBenardConvection/Convection_Dash.jl similarity index 98% rename from RayleighBenardConvection/Convection_Dash.jl rename to src/RayleighBenardConvection/Convection_Dash.jl index 68e2b7a..53f5f98 100644 --- a/RayleighBenardConvection/Convection_Dash.jl +++ b/src/RayleighBenardConvection/Convection_Dash.jl @@ -13,7 +13,7 @@ export Convection pkg_dir = Base.pkgdir(ConvectionTools) include(joinpath(pkg_dir,"src/dash_tools.jl")) -include(joinpath(pkg_dir,"RayleighBenardConvection/dash_functions_convection.jl")) +include(joinpath(pkg_dir,"src/RayleighBenardConvection/dash_functions_convection.jl")) """ @@ -112,7 +112,7 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) user_dir = simulation_directory(session_id, clean=false) if trigger == "button-run.n_clicks" cur_dir = pwd() - base_dir = joinpath(pkgdir(ConvectionTools),"RayleighBenardConvection") + base_dir = joinpath(pkgdir(ConvectionTools),"src","RayleighBenardConvection") viscosity = 10.0^viscosity cohesion *= 1.0e6 diff --git a/RayleighBenardConvection/Convection_LaMEM.jl b/src/RayleighBenardConvection/Convection_LaMEM.jl similarity index 100% rename from RayleighBenardConvection/Convection_LaMEM.jl rename to src/RayleighBenardConvection/Convection_LaMEM.jl diff --git a/RayleighBenardConvection/dash_functions_convection.jl b/src/RayleighBenardConvection/dash_functions_convection.jl similarity index 85% rename from RayleighBenardConvection/dash_functions_convection.jl rename to src/RayleighBenardConvection/dash_functions_convection.jl index 9a19452..446d21e 100644 --- a/RayleighBenardConvection/dash_functions_convection.jl +++ b/src/RayleighBenardConvection/dash_functions_convection.jl @@ -40,104 +40,13 @@ function make_rheological_parameters() ]) end -#= -""" -Creates the main figure plot. -""" -function create_main_figure( - OutFile, cur_t, - x=-10:10, y=-10:0, data=rand(10, 20), # heatmap plot - x_con=-10:10, y_con=-10:0, data_con=rand(10, 20), # contour plot - cmaps=read_colormaps() # colormaps - ; colorscale="batlow", field="phase", add_contours=true, add_velocity=false, - contour_field="phase", session_id="") - - cbar_thk = 20 - - # add heatmap - data_plot = [ - heatmap( - x=x, - y=y, - z=data, - colorscale=cmaps[Symbol(colorscale)], - colorbar=attr(thickness=cbar_thk, title=field) - ) - ] - # add contours - if add_contours == true - push!( - data_plot, ( - contour( - x=x_con, - y=y_con, - z=data_con, - colorscale=cmaps[Symbol(colorscale)], - contours_coloring="lines", - line_width=2, - colorbar=attr(thickness=cbar_thk, title=contour_field, x=1.1, yanchor=0.5, contour_label=true), - ) - ) - ) - end - # add velocity - if add_velocity == true - arrowhead, line = calculate_quiver(OutFile, cur_t, cmaps; colorscale="batlow") - push!(data_plot, arrowhead) - push!(data_plot, line) - end - - pl = (id="fig_cross", - data=data_plot, - # colorbar=Dict("orientation" => "v", "len" => 0.5), - - layout=( - - # width="320vw", height="320vh", - xaxis=attr( - title="Width (km)", - tickfont_size=14, - tickfont_color="rgb(100, 100, 100)", - showgrid=false, - # zeroline=false, - # automargin=true, - # constrain="domain", - scaleanchor="y", - scaleratio=1.0, - showline=true, linewidth=2, linecolor="black", mirror=true, - ), - yaxis=attr( - title="Depth (km)", - # domain=[0,100], - tickfont_size=14, - tickfont_color="rgb(10, 10, 10)", - showgrid=false, - showline=true, linewidth=2, linecolor="black", mirror=true, - # range=[-10,0], - # zeroline=false, - # scaleanchor="x", - # scaleratio=1.0, - # constrain="domain", - # constrain="range", - ), margin=Dict([("l", 50), ("r", 50)])#), margin=Dict([("l", 350), ("r", 350)]) - ), - config=(edits = (shapePosition=true,)), scaleratio=1.0 - - - ) - - return pl -end -=# - """ Creates a setup with noisy temperature and one phase """ function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100; args) Grid = ReadLaMEM_InputFile(ParamFile, args=args) Phases = zeros(Int64, size(Grid.X)) - Temp = ones(Float64, size(Grid.X)) * ΔT / 2 - Temp = Temp + rand(size(Temp)...) .* ampl_noise + Temp = [ΔT / 2 + rand()*ampl_noise for _ in axes(Grid.X,1), _ in axes(Grid.X,2), _ in axes(Grid.X,3)] Phases[Grid.Z.>0.0] .= 1 Temp[Grid.Z.>0.0] .= 0.0 diff --git a/RayleighTaylorInstability/RTI.dat b/src/RayleighTaylorInstability/RTI.dat similarity index 100% rename from RayleighTaylorInstability/RTI.dat rename to src/RayleighTaylorInstability/RTI.dat diff --git a/RayleighTaylorInstability/RTI_Dash.jl b/src/RayleighTaylorInstability/RTI_Dash.jl similarity index 98% rename from RayleighTaylorInstability/RTI_Dash.jl rename to src/RayleighTaylorInstability/RTI_Dash.jl index a080dc0..2f87c9f 100644 --- a/RayleighTaylorInstability/RTI_Dash.jl +++ b/src/RayleighTaylorInstability/RTI_Dash.jl @@ -13,7 +13,7 @@ export RayleighTaylor pkg_dir = Base.pkgdir(RTITools) include(joinpath(pkg_dir,"src/dash_tools.jl")) -include(joinpath(pkg_dir,"RayleighTaylorInstability/dash_functions_RTI.jl")) +include(joinpath(pkg_dir,"src/RayleighTaylorInstability/dash_functions_RTI.jl")) """ RayleighTaylor(; host=HTTP.Sockets.localhost, port=8050) @@ -113,7 +113,7 @@ function RayleighTaylor(; host = HTTP.Sockets.localhost, port=8050) disable_interval = true if trigger == "button-run.n_clicks" cur_dir = pwd() - base_dir = joinpath(pkgdir(RTITools),"RayleighTaylorInstability") + base_dir = joinpath(pkgdir(RTITools),"src","RayleighTaylorInstability") η_up = 10.0^η_up diff --git a/RayleighTaylorInstability/RTI_LaMEM.jl b/src/RayleighTaylorInstability/RTI_LaMEM.jl similarity index 100% rename from RayleighTaylorInstability/RTI_LaMEM.jl rename to src/RayleighTaylorInstability/RTI_LaMEM.jl diff --git a/src/RayleighTaylorInstability/dash_functions_RTI.jl b/src/RayleighTaylorInstability/dash_functions_RTI.jl new file mode 100644 index 0000000..82b8c06 --- /dev/null +++ b/src/RayleighTaylorInstability/dash_functions_RTI.jl @@ -0,0 +1,85 @@ +using DelimitedFiles + + +""" +Returns an accordion menu containing the rheological parameters. +""" +function make_rheological_parameters() + return dbc_accordionitem(title="Rheological Parameters", [ + make_accordion_item("η_up(log₁₀(Pa⋅s)):", "viscosity_upper", "Logarithm of the viscosity of the upper layers.", 21.0, 16.0, 23.0), + dbc_row(html_p()), + make_accordion_item("η_lo(log₁₀(Pa⋅s)):", "viscosity_lower", "Logarithm of the viscosity of the lower layer", 20.0, 16.0, 23.0), + dbc_row(html_p()), + make_accordion_item("ρ_up:", "density_upper", "Density of the upper layers.", 2800.0, 2.0, 5000.0), + dbc_row(html_p()), + make_accordion_item("ρ_lo:", "density_lower", "Density of the lower layer.", 2200.0, 2.0, 5000.0), + ]) +end + +""" +Returns an accordion menu containing the simulation parameters. +""" +function make_simulation_parameters() + return dbc_accordionitem(title="Simulation Parameters", [ + make_accordion_item("Width (km):", "domain_width", "Width of the domain, given in kilometers.", 10.0, 1.0e-10), + dbc_row(html_p()), + make_accordion_item("Depth of the interface (km):", "depth", "Depth of the interface, given in kilometers.", -2.5, -50.0), + dbc_row(html_p()), + make_accordion_item("nx:", "nel_x", "Number of elements in the x-direction. Must be an integer greater than 2.", 64, 2), + dbc_row(html_p()), + make_accordion_item("nz:", "nel_z", "Number of elements in the z-direction. Must be an integer greater than 2.", 32, 2), + dbc_row(html_p()), + make_accordion_item("nt:", "n_timesteps", "Maximum number of timesteps. Must be an integer greater than 1.", 50, 1), + dbc_row(html_p()), + dbc_row([ + dbc_checklist(options=["FreeSurf"], + id="switch-FreeSurf", + switch=true, + ) + ]), + dbc_row(html_p()), + dbc_row([ + dbc_checklist(options=["Layers"], + id="switch-Layers", + switch=true, + ) + ]) + ]) +end + +""" +Creates a setup with noisy temperature and one phase +""" +function CreateSetup(ParamFile, layered_overburden=false, Hi=-5.0, ampl_noise=0.1, ; args) + Grid = ReadLaMEM_InputFile(ParamFile, args=args) + Phases = zeros(Int64, size(Grid.X)); + Temp = zeros(Float64,size(Grid.X)); + + + if layered_overburden + H_layer = 0.25; + for z_low = minimum(Grid.Z):2*H_layer:maximum(Grid.Z) + # print(z_low) + # z_low = -z_low + iz = (Grid.Z[1,1,:] .> z_low) .& (Grid.Z[1,1,:] .<= (z_low+H_layer) ) + Phases[:,:,iz] .= 1; + end + end + + z_int = [Hi + rand()*ampl_noise for _ in 1:Grid.nump_x] + # print(z_int) + # z_int = -z_int + for ix=1:Grid.nump_x, iy=1:Grid.nump_y + iz = Grid.Z[ix,iy,:] .< z_int[ix] + Phases[ix,iy,iz] .= 2; + end + + # print(z_int) + + Model3D = CartData(Grid, (Phases=Phases,Temp=Temp)) # Create LaMEM model + Write_Paraview(Model3D,"LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) + + Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core + + return nothing +end \ No newline at end of file diff --git a/RisingSphere/.gitignore b/src/RisingSphere/.gitignore similarity index 100% rename from RisingSphere/.gitignore rename to src/RisingSphere/.gitignore diff --git a/RisingSphere/RisingSphere.dat b/src/RisingSphere/RisingSphere.dat similarity index 100% rename from RisingSphere/RisingSphere.dat rename to src/RisingSphere/RisingSphere.dat diff --git a/RisingSphere/RisingSphere_Dash.jl b/src/RisingSphere/RisingSphere_Dash.jl similarity index 98% rename from RisingSphere/RisingSphere_Dash.jl rename to src/RisingSphere/RisingSphere_Dash.jl index a0ba204..fb30a9b 100644 --- a/RisingSphere/RisingSphere_Dash.jl +++ b/src/RisingSphere/RisingSphere_Dash.jl @@ -11,7 +11,7 @@ export RisingSphere pkg_dir = pkgdir(RisingSphereTools) include(joinpath(pkg_dir,"src/dash_tools.jl")) -include(joinpath(pkg_dir,"RisingSphere/dash_functions_RisingSphere.jl")) +include(joinpath(pkg_dir,"src/RisingSphere/dash_functions_RisingSphere.jl")) """ RisingSphere(; host=HTTP.Sockets.localhost, port=8050) @@ -126,7 +126,7 @@ function RisingSphere(; host=HTTP.Sockets.localhost, port=8050) disable_interval = true if trigger == "button-run.n_clicks" cur_dir = pwd() - base_dir = joinpath(pkgdir(RisingSphereTools),"RisingSphere") + base_dir = joinpath(pkgdir(RisingSphereTools),"src","RisingSphere") args = "-nstep_max $(n_timesteps) -radius[0] $sphere_radius -rho[0] $matrix_density -rho[1] $sphere_density -nel_x $nel_x -nel_z $nel_z -coord_x $(-domain_width/2),$(domain_width/2) -coord_z $(-domain_width/2),$(domain_width/2)" diff --git a/RisingSphere/RisingSphere_LaMEM.jl b/src/RisingSphere/RisingSphere_LaMEM.jl similarity index 100% rename from RisingSphere/RisingSphere_LaMEM.jl rename to src/RisingSphere/RisingSphere_LaMEM.jl diff --git a/RisingSphere/dash_functions_RisingSphere.jl b/src/RisingSphere/dash_functions_RisingSphere.jl similarity index 95% rename from RisingSphere/dash_functions_RisingSphere.jl rename to src/RisingSphere/dash_functions_RisingSphere.jl index e589bf3..7c99594 100644 --- a/RisingSphere/dash_functions_RisingSphere.jl +++ b/src/RisingSphere/dash_functions_RisingSphere.jl @@ -36,8 +36,8 @@ Creates a setup with noisy temperature and one phase function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100; args) Grid = ReadLaMEM_InputFile(ParamFile, args=args) Phases = zeros(Int64, size(Grid.X)) - Temp = ones(Float64, size(Grid.X)) * ΔT / 2 - Temp = Temp + rand(size(Temp)...) .* ampl_noise + Temp = [ΔT / 2 + rand()*ampl_noise for _ in axes(Grid.X,1), _ in axes(Grid.X,2)] + Phases[Grid.Z.>0.0] .= 1 Temp[Grid.Z.>0.0] .= 0.0 diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 43278e5..7f35730 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -405,34 +405,31 @@ end """ Returns a row containing a label, a tooltip and a filling box. """ -function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::_T=1*one(_T), min=nothing, max=nothing) where _T <: Number +function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::_T=1*one(_T), low=nothing, high=nothing) where _T <: Number - if isa(_T, Float64) - if isnothing(min) - min = 1e-10 - end - if isnothing(max) - max = 10000 - end - elseif isa(_T, Int64) - if isnothing(min) - min = 2 - end - if isnothing(max) - max = 10_000 - end - end + low = _check_min(_T, low) + high = _check_max(_T, high) item = dbc_row([ # domain width dbc_col([ dbc_label(label, id=idx*"_label", size="md"), dbc_tooltip(msg, target=idx*"_label") ]), - dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=min, size="md")) + dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=low, size="md")) ]) return item end + +@inline _check_min(::Float64, ::Nothing) = 1e-10 +@inline _check_min(::Int64, ::Nothing) = 2 +@inline _check_min(::T, x) where T = x + +@inline _check_max(::Float64, ::Nothing) = 10000 +@inline _check_max(::Int64, ::Nothing) = 10_000 +@inline _check_max(::T, x) where T = x + + #= """ Returns a row containing a label, a tooltip and a filling box. From cd58584625ab6c7dee5feefb5c0418356205fa22 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Sun, 1 Oct 2023 11:54:32 +0200 Subject: [PATCH 12/14] change size of plot --- src/dash_tools.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 7f35730..2dca39d 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -60,13 +60,20 @@ function create_main_figure(OutFile, cur_t, x=1:10, y=1:10, data=rand(10, 10), title="Width", tickfont_size=14, tickfont_color="rgb(100, 100, 100)", - automargin=true,), + scaleanchor="y", scaleratio=1, + autorange="true", automargin=true, + range=[-1,4], + ), yaxis=attr( title="Depth", tickfont_size=14, tickfont_color="rgb(10, 10, 10)", - scaleanchor="x", scaleratio=1 - ), margin=Dict([("l", 350), ("r", 350)]) + autorange="true", automargin=true, + range=[-1,4], + ), + #margin=attr(l=20, r=20, b=20, t=20, pad=1), + margin=attr(autoexpand="true"), + autosize=true ), config=(edits = (shapePosition=true,)), ) From e84a3e2a0e376e6ec803a94838c3c19345c9bf87 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Sun, 1 Oct 2023 12:45:28 +0200 Subject: [PATCH 13/14] remove old Makie files tweak plots --- src/Basic_LaMEM_GUI.jl | 425 ---------------- .../Convection_Dash.jl | 6 +- .../Convection_LaMEM.jl | 182 ------- .../dash_functions_convection.jl | 459 ------------------ src/RayleighTaylorInstability/RTI_LaMEM.jl | 117 ----- src/RisingSphere/RisingSphere_LaMEM.jl | 168 ------- src/dash_tools.jl | 33 +- src/utils.jl | 51 -- src/widgets.jl | 191 -------- 9 files changed, 23 insertions(+), 1609 deletions(-) delete mode 100644 src/Basic_LaMEM_GUI.jl delete mode 100644 src/RayleighBenardConvection/Convection_LaMEM.jl delete mode 100644 src/RayleighTaylorInstability/RTI_LaMEM.jl delete mode 100644 src/RisingSphere/RisingSphere_LaMEM.jl delete mode 100644 src/utils.jl delete mode 100644 src/widgets.jl diff --git a/src/Basic_LaMEM_GUI.jl b/src/Basic_LaMEM_GUI.jl deleted file mode 100644 index da3dfb5..0000000 --- a/src/Basic_LaMEM_GUI.jl +++ /dev/null @@ -1,425 +0,0 @@ -using LaMEM, Revise, FileWatching, Interpolations -using GLMakie -using GLMakie: to_native -using GLMakie.GLFW - -using LaMEM -export LaMEM # export all LaMEM routines - - -GLMakie.activate!() - -include("./utils.jl") -include("./widgets.jl") - -""" - update_info(gui::NamedTuple, values::NamedTuple) - -This updates the info window on the GUI. If you wish, you can overwrite this in your custom routine. -Parameters: -- `gui`: NamedTuple with various labels on the GUI -- `values`: NamedTuple with update data that can be used -""" -function update_info(gui::NamedTuple, values::NamedTuple) - pad_space = 15 - gui.time.displayed_string[] = rpad(string(round(values.time[1]; digits=3)),pad_space) - gui.timestep.displayed_string[] = rpad(string(values.t_step),pad_space) - - return nothing -end - - -""" - Read_data_field(ifield, data, component=1) -Reads a certain datafield from the LaMEM data structure (and optionally, a component if it is a vector or tensor field) -""" -function Read_data_field(ifield, data, component=1) - # Read the field - data_field = data.fields[ifield] - if length(size(data_field))==3 - data_field = data_field[:,1,:] - elseif length(size(data_field))>3 - if component <= size(data_field,1) - data_field = data_field[component,:,1,:] - end - else - error("unknown size of data field") - end - - return data_field -end - -""" - update_plot_info(OutFile, gui::NamedTuple, t_step::Int64; last=false) - -This updates the main plot within the GUI -""" -function update_plot_info(OutFile, gui::NamedTuple, t_step::Int64; last=false) - - t_step,_ = update_plot_info_basic(OutFile, gui, t_step; last=last) - - return t_step, gui -end - - -# Basic code -function update_plot_info_basic(OutFile, gui::NamedTuple, t_step::Int64; last=false) - - # Load LaMEM result - if last - Timestep, _, _ = Read_LaMEM_simulation(OutFile) - t_step = Timestep[end] - end - - data, time = Read_LaMEM_timestep(OutFile, t_step, last=last); - - # update info window - values = (t_step=t_step, time=time); - update_info(gui, values) - - # Read the field from the LaMEM dataset - ifield = gui.menu.i_selected[] - component = parse(Int,gui.menu_comp.stored_string[]) - data_field = Read_data_field(ifield, data, component) - - # set label of colorbar - gui.cb.label= Read_LaMEM_fieldnames(OutFile)[ifield] - - lim = Float64.(extrema(data_field)) - try # this deals with a bug that sometimes occurs - gui.cb.limits = lim - catch - gui.cb.limits = lim .+ (-1e-3,1e-3) - end - - # plot the field that is selected in the dropdown menu - gui.hm[1] = data.x.val[:,1,1]; - gui.hm[2] = data.z.val[1,1,:]; - gui.hm[3] = data_field - - aspect_ratio = (data.x.val[end]- data.x.val[1]) / (data.z.val[end]- data.z.val[1]) - # ax.aspect = aspect_ratio - # gui.cb.height[] = Relative(1/aspect_ratio*0.9) - - # plot velocity arrows if requested - if gui.velocity_toggle.active[] - num_z = 20; - num_x = round(Int64,num_z*aspect_ratio); - - x,z = data.x.val[:,1,1], data.z.val[1,1,:]; - Vx,Vz = data.fields.velocity[1,:,1,:], data.fields.velocity[3,:,1,:]; - - x_low = range(x[1], x[end], num_x); - z_low = range(z[1], z[end], num_z) - Vx_itp = linear_interpolation((x,z), Vx; extrapolation_bc=Throw()) - Vz_itp = linear_interpolation((x,z), Vz; extrapolation_bc=Throw()) - pt_arrow = []; - vel_arrow = [] - for x in x_low, z in z_low - push!(pt_arrow, Point2f(x,z)) - push!(vel_arrow, Vec2f(Vx_itp(x, z),Vz_itp(x, z))) - end - gui.pt_arrow[]= pt_arrow - gui.vel_arrow[]= vel_arrow - - xlims!(ax,x[1],x[end]) - ylims!(ax,z[1],z[end]) - - gui.arrows.visible[]=true - - else - gui.arrows.visible[]=false - - end - - display(fig) - sleep(1/60) - - return t_step, data -end - - -""" - fig, ax, gui = Create_Basic_LaMEM_GUI(OutFile, ParamFile; resolution = nothing, fontsize=30, colormap=:viridis, size_total=(1:20, 1:7), size_ax=(1:20, 1:4), show_velocity_toggle=true) - -Creates a basic LaMEM GUI that has a "run" and "play" button and the option to change the max. number of timesteps. - -Input arguments: -- `OutFile`: the LaMEM output files (without pvd extension) -- `ParamFile`: the LaMEM input file (incluidng `*.dat`) - -Optional arguments: -- `resolution`: resolution of the screen. by default this is set to `nothing` which produces a small figure tat require resizing -- `fontsize`: fontsize -- `colormap`: colormap used -- `width`: width of last row -- `size_total`: total size of the GUI - bottons etc. will be put @ the end -- `size_ax`: size of the axis - -Output arguments: -- `fig`: the main figure window -- `ax`: the main axis -- `gui`: A named tuple with all GUI elements - - -""" -function Create_Basic_LaMEM_GUI(OutFile, ParamFile; resolution = nothing, fontsize=nothing, colormap=:viridis, width=160, height=Auto(), size_total=(1:18, 1:7), size_ax=(1,1), - show_velocity_toggle=true) - - # Generate general layout - if isnothing(resolution) & isnothing(fontsize) - fig = Figure() # default figure size (requires resizing) - elseif isnothing(resolution) & !isnothing(fontsize) - fig = Figure(fontsize=fontsize) - - elseif !isnothing(resolution) & isnothing(fontsize) - fig = Figure(resolution=resolution) - - else - - fig = Figure( resolution=resolution, fontsize=fontsize) - end - - # main figure - ax = Axis(fig[2,1][size_ax...], xlabel="Width [km]", ylabel="Depth [km]") - - menu_file = Menu(fig[1, 1][1,1], options = ["File","Save animation", "Save plot", "Close window"], default = "File", selection_cell_color_inactive = GLMakie.RGB(1,1,1), height=height) - rowsize!(fig.layout, 1, 30) - - # info window - lb_time,txt_time = Textbox_with_label_left(fig[2,2][1,1:2], "time [Myr]: ", 0.0, bordercolor_hover=:white, bordercolor=:white, boxcolor_hover=:white, width=width, height=height) - lb_timestep,txt_timestep = Textbox_with_label_left(fig[2,2][2,1:2], "timestep: ", 0, bordercolor_hover=:white, bordercolor=:white, boxcolor_hover=:white, width=width, height=height) - - # retrieve maximum # of timestep - nstep_max = keyword_LaMEM_inputfile(ParamFile,"nstep_max", Int64); - nstep_max_tb,_ = Textbox_with_label_left(fig[2,2][3,1:2], "max. # timesteps: ", nstep_max, width=width, height=height); - - # Grid resolution - nel_z = keyword_LaMEM_inputfile(ParamFile,"nel_z", Int64); - nel_z_tb,_ = Textbox_with_label_left(fig[2,2][4,1:2], "# gridpoints [z]: ", nel_z, width=width, height=height); - - # Add buttons - fig[2,2][size_total[1][end-1], 1] = buttonrun = Button(fig, label = "Run", width=Relative(1/1), height=height) #GridLayout(tellwidth = false) - fig[2,2][size_total[1][end-1], 2] = buttonplay = Button(fig, label = " ", width=Relative(1/1), height=height) #GridLayout(tellwidth = false) - - # Add velocity toggle - if show_velocity_toggle - velocity_toggle,txt_velocity_toggle = Toggle_with_label_left(fig[2,2][size_total[1][end-3], 1:2], "Show velocity", false, height=height); - else - velocity_toggle,txt_velocity_toggle = nothing, nothing - end - # add Menu with fields to show: - menu = Menu(fig[2,2][size_total[1][end-2], 1], options = ["phase","temperature"], default = "phase", height=height) - if !isfile(OutFile*".pvd") - # Create empty input file (as we are monitoring this) - io = open(OutFile*".pvd", "w"); println(io, " "); close(io) - else - # input file exists (previous sim); read it - update_fields_menu(OutFile, menu) - buttonplay.label="Play" - end - menu_comp = Textbox(fig[2,2][size_total[1][end-2], 2], placeholder = "1", stored_string="1", height=height) - - # Create initial heatmap - dat = rand(11, 11) - hm = heatmap!(ax, Vector(0.0:20.0),Vector(0.0:10.0),dat, colormap=colormap) - cb = Colorbar(fig[2,1][size_ax[1]+1,size_ax[2]], colormap=colormap, width = Relative(1/2), limits = (-1.0, 1.0), vertical=false) # colorbar - - hm[3][] = zeros(11,11) - - # add arrows - pt_arrow = Observable( [Makie.Point2f(0,0)]) - vel_arrow = Observable([Makie.Vec2f(0,0)]) - arr = arrows!(ax,pt_arrow, vel_arrow, color=:gray50, lengthscale = 2.0) - - # Store all GUI elements in a NamedTuple - gui = ( timestep=lb_timestep, time=lb_time, hm=hm, cb=cb, menu_comp=menu_comp, menu=menu, - nstep_max_tb=nstep_max_tb, buttonplay=buttonplay, buttonrun=buttonrun, velocity_toggle=velocity_toggle, - pt_arrow=pt_arrow, vel_arrow=vel_arrow, arrows=arr, menu_file=menu_file, nel_z=nel_z_tb, - txt_time=txt_time, txt_timestep = txt_timestep, txt_velocity_toggle = txt_velocity_toggle); - - # Read LaMEM results & update the plots - function start_anim(OutFile, gui, hm, ax, fig) - gui.buttonplay.label=" " - t_step=0 - it = 0 - nstep_max = parse(Int,gui.nstep_max_tb.stored_string[]) - while t_step0) - sleep(0.5) - t_step, gui = update_plot_info(OutFile, gui, t_step, last=true) - end - - it += 1 - println("Timestep $t_step") - end - buttonplay.label="Play" - buttonanim.label="Save animation" - - println("Simulation finished") - - end - - # Run LaMEM - on(buttonrun.clicks) do n - @info "Running LaMEM simulation" - - # Start the LaMEM simulation: - run_code(ParamFile, gui; wait=false) # run LaMEM in background - - # Update the plot & info windows - @async start_anim(OutFile, gui, hm, ax, fig) - - end - - # Play animation - on(buttonplay.clicks) do n - Timestep, _, _ = Read_LaMEM_simulation(OutFile) # read all timesteps - @async for it in Timestep - gui.buttonplay.label="Play" - # Update the plots etc. - _,gui = update_plot_info(OutFile, gui, it, last=false) - end - end - - screen = display(GLMakie.Screen(),fig) - glfw_window_main = to_native(screen) - gui = (gui..., screen=screen) - - on(menu_file.selection) do select - @info select - if select=="Close window" - GLFW.SetWindowShouldClose(glfw_window_main, true) - - elseif select=="Save plot" - plot_name, res = SavePlot_GUI(;fontsize=30, resolution=resolution) - - if !isnothing(plot_name) - @show plot_name - gui.menu_file.is_open=false - save(plot_name, fig, resolution=res) - display(fig) - end - - elseif select=="Save animation" - # open GUI that has animation parametere - anim_data = SaveAnimation_GUI(;fontsize=30) - - Timestep, _, _ = Read_LaMEM_simulation(OutFile) # read all timesteps - if !isnothing(anim_data) - record(ax.scene, anim_data.Name, Timestep; framerate = anim_data.fps) do it - println("Creating animation; frame=$it") - _,gui =update_plot_info(OutFile, gui, it, last=false) - end - end - - else - - end - gui.menu_file.i_selected=1 - - end - - return fig, ax, gui -end - -struct AnimationData - fps::Int64 - Name::String -end - - - -""" - out = SaveAnimation_GUI(;fontsize=30) - -This opens a GUI where you can specify animation info. Once you are done with it you either cancel the window (`out=nothing`), or save it -""" -function SaveAnimation_GUI(;fontsize=30) - - fig_anim = Figure(fontsize=fontsize) - - fps_tb,_ = Textbox_with_label_left(fig_anim[1, 1:2], "Frames/second: ", 10) - filename_tb,_ = Textbox_with_label_left(fig_anim[2, 1:2], "FileName: ", "Animation_1") - Label(fig_anim[3, 1],text="FileType:") - men_type = Menu(fig_anim[3, 2], options = ["mp4","gif"], default = "mp4") - - buttoncancel = Button(fig_anim[4, 1], label = "Cancel", width=Relative(1/1)) #GridLayout(tellwidth = false) - buttonsave = Button(fig_anim[4, 2], label = "Save", width=Relative(1/1)) #GridLayout(tellwidth = false) - - screen_anim = display(GLMakie.Screen(),fig_anim) - glfw_window_anim = to_native(screen_anim) - - out = nothing - on(buttoncancel.clicks) do n - # close window, do nothing - GLFW.SetWindowShouldClose(glfw_window_anim, true) - end - - on(buttonsave.clicks) do n - ending = men_type.options[][men_type.i_selected[]] - filename = filename_tb.displayed_string[]*"."*ending - fps = parse(Int64,fps_tb.displayed_string[]) - - anim_dat = AnimationData(fps, filename) - out= anim_dat - GLFW.SetWindowShouldClose(glfw_window_anim, true) - end - - wait(screen_anim) - return out -end - - -""" - out = SavePlot_GUI(;fontsize=30) - -This opens a GUI where you can specify plot info. Once you are done with it you either cancel the window (`out=nothing`), or save it -""" -function SavePlot_GUI(;fontsize=30, resolution=(1000,1000)) - - fig_plot = Figure(fontsize=fontsize) - - res_string = String("$(resolution)")[2:end-1] - @show res_string - res_tb,_ = Textbox_with_label_left(fig_plot[1, 1:2], "Resolution (dpi): ", res_string) - filename_tb,_ = Textbox_with_label_left(fig_plot[2, 1:2], "FileName: ", "Plot_1") - Label(fig_plot[3, 1],text="FileType:") - men_type = Menu(fig_plot[3, 2], options = ["png","jpeg","bmp"], default = "png") - - buttoncancel = Button(fig_plot[4, 1], label = "Cancel", width=Relative(1/1)) #GridLayout(tellwidth = false) - buttonsave = Button(fig_plot[4, 2], label = "Save", width=Relative(1/1)) #GridLayout(tellwidth = false) - - screen_plot = display(GLMakie.Screen(),fig_plot) - glfw_window_plot = to_native(screen_plot) - - out = nothing - on(buttoncancel.clicks) do n - # close window, do nothing - GLFW.SetWindowShouldClose(glfw_window_plot, true) - end - - on(buttonsave.clicks) do n - ending = men_type.options[][men_type.i_selected[]] - filename = filename_tb.displayed_string[]*"."*ending - resolution = Tuple(parse.(Int,split(res_tb.stored_string[],","))) - - out = filename - GLFW.SetWindowShouldClose(glfw_window_plot, true) - end - - wait(screen_plot) - return out, resolution -end - diff --git a/src/RayleighBenardConvection/Convection_Dash.jl b/src/RayleighBenardConvection/Convection_Dash.jl index 53f5f98..f7c02af 100644 --- a/src/RayleighBenardConvection/Convection_Dash.jl +++ b/src/RayleighBenardConvection/Convection_Dash.jl @@ -49,9 +49,9 @@ function Convection(; host=HTTP.Sockets.localhost, port=8050) make_id_label(), # show user id ]), dbc_col([ - make_time_card(), # show simulation time info - make_menu(cmaps), # show menu with simulation parameters, rheological parameters, and plotting parameters - make_run_button() # show the run simulation button + make_time_card(), # show simulation time info + make_menu(cmaps, show_field="temperature"), # show menu with simulation parameters, rheological parameters, and plotting parameters + make_run_button() # show the run simulation button ]) ]), diff --git a/src/RayleighBenardConvection/Convection_LaMEM.jl b/src/RayleighBenardConvection/Convection_LaMEM.jl deleted file mode 100644 index 147240b..0000000 --- a/src/RayleighBenardConvection/Convection_LaMEM.jl +++ /dev/null @@ -1,182 +0,0 @@ -using GLMakie -using GeophysicalModelGenerator, Statistics - -Makie.inline!(true) - - -include("../src/widgets.jl") -include("../src/Basic_LaMEM_GUI.jl") - -clean_directory() - -# Define the simulation name & the output files: -OutFile = "Convection" -ParamFile = "Convection.dat" -FreeSurface = false -if FreeSurface - ParamFile = "Convection_FreeSurf.dat" -end -resolution = primary_resolution() -width = round(Int,resolution[1]/11); -width=160 - -if Sys.isapple() - resolution = (2500,1500) - - fontsize = 30 - height_widgets = Auto(); - -elseif Sys.iswindows() - fontsize = 15 - height_widgets = 25; - resolution=(1500,900) - -else - resolution = nothing - fontsize = nothing -end - - -# Create Basic GUI -fig, ax, gui = Create_Basic_LaMEM_GUI(OutFile, ParamFile, resolution=resolution, fontsize=fontsize, width=width, colormap=Reverse(:roma), - size_total=(1:17, 1:7), size_ax=(2, 1), height=Auto()); -ax.title = "" -gui.menu.i_selected=2 # T -gui.menu.selection="temperature" - -# add left & top plots -ax_T = Axis(fig[2,1][2,2], xlabel=L"T[^o\mathrm{C}]", ylabel="Depth[km]", width=100, xaxisposition=:top) - -linkyaxes!(ax,ax_T) -hideydecorations!(ax_T, grid = false) -colgap!(fig.layout, 10) -rowgap!(fig.layout, 10); - -ax_Vel = Axis(fig[2,1][1,1], title="Rayleigh Benard Convection", ylabel=L"v_x[\mathrm{cm yr}^{-1}]", xlabel="Width[km]") -ax_Vel.height = 100 -linkxaxes!(ax,ax_Vel) -hidexdecorations!(ax_Vel, grid = false) - -# Add textboxes: -Height,_ = Textbox_with_label_left(fig[2,2][5, 1:2], L"\mathrm{Height [km]}", "1000", width=width, height=height_widgets); -AspectR,_ = Textbox_with_label_left(fig[2,2][6, 1:2], L"\mathrm{AspectRatio}", "3", width=width, height=height_widgets); -Tbot,_ = Textbox_with_label_left(fig[2,2][7, 1:2], L"T_\mathrm{bottom} [^o\mathrm{C}]", "2000", width=width, height=height_widgets); -Yield,_ = Textbox_with_label_left(fig[2,2][8, 1:2], L"\mathrm{YieldStress[MPa]}", "500", width=width, height=height_widgets); - -# Add sliders: -gamma_sl, _, _ = Slider_with_text_above(fig[2,2][9:10,1:2], L"\eta=\eta_\mathrm{0}\exp\left(-\gamma T \right), \hspace \gamma=", 0:.001:.01, 0.01, height=height_widgets) -eta_sl, _, _ = Slider_with_text_above(fig[2,2][11:12,1:2], L"\log_{10}(\eta_{\mathrm{0}} \mathrm{ [Pas]})", 15:.25:25, 21); - -# Add toggle: -temp_toggle,_ = Toggle_with_label_left(fig[2,2][13, 1:2], "Temperature isocontours", true, height=height_widgets); - -if FreeSurface - gui.nel_z.displayed_string[]="64" -end - - -# Create setup with random noise -function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100 ; args) - Grid = ReadLaMEM_InputFile(ParamFile, args=args) - Phases = zeros(Int64, size(Grid.X)); - Temp = ones(Float64,size(Grid.X))*ΔT/2 ; - Temp = Temp + rand(size(Temp)...).*ampl_noise - Phases[Grid.Z.>0.0] .= 1 - Temp[Grid.Z.>0.0] .= 0.0 - - Model3D = CartData(Grid, (Phases=Phases,Temp=Temp)) # Create LaMEM model - Write_Paraview(Model3D,"LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) - - Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core - - return nothing -end - - -# Update plot info to include contours -function update_plot_info(OutFile, gui::NamedTuple, t_step::Int64; last=false) - t_step, data = update_plot_info_basic(OutFile, gui, t_step; last=last) - - ifield = findall(contains.(gui.menu.options[],"temperature"))[] - x,z = data.x.val[:,1,1], data.z.val[1,1,:]; - T_field = Read_data_field(ifield, data, 1) - - ifield = findall(contains.(gui.menu.options[],"velocity"))[] - Vx_field = Read_data_field(ifield, data, 1) - - temp_toggle.active[] ? iso_con = true : iso_con = false - - # optionally plot isocontours for T - if isa(ax.scene.plots[end], Combined{Makie.contour, Tuple{Vector{Float32}, Vector{Float32}, Matrix{Float32}}}) - delete!(ax.scene,ax.scene.plots[end]) - end - if iso_con - contour!(ax, x,z,T_field, levels=20, color=:black) - end - - # Average T - if length(ax_T.scene.plots)>0 - delete!(ax_T.scene,ax_T.scene.plots[end]) - end - lines!(ax_T,mean(T_field, dims=1)[:],z, color=:blue) - ylims!(ax_T,minimum(z),0) - - ΔT = get_values_textboxes((Tbot, )) - ax_T.xticks[] = [0, ΔT[1]] - - # Top Vx - if length(ax_Vel.scene.plots)>0 - delete!(ax_Vel.scene,ax_Vel.scene.plots[end]) - end - - - if FreeSurface - iz = findmin(abs.(z .- 0.0))[2] # close to zero - else - iz = length(z) - end - - lines!(ax_Vel,x,Vx_field[:,iz], color=:blue) # velocity around z=0 - xlims!(ax_Vel,minimum(x),maximum(x)) - - return t_step, gui -end - - -# Run the LaMEM simulation (modify some parameters if you want) -function run_code(ParamFile, gui; wait=true) - - nel_x,nel_z = retrieve_resolution(ParamFile, gui) - - # Retrieve various parameters from the GUI: - H, AR, ΔT, nstep_max, σy = get_values_textboxes((Height,AspectR, Tbot, gui.nstep_max_tb, Yield)) - η0 = 10.0^eta_sl.value[] - gam = gamma_sl.value[] - if gam==0.0 - gam = 1e-9 - end - ch = σy*1e6 # cohesion (in Pa) - - W = H*AR; # width - nel_x = round(Int64,nel_z*AR) - Δx = ceil(W/nel_x); # spacing in x - - # Retrieve some parameters from the GUI - nstep_max_val = Int64(nstep_max) - - # command-line arguments - args = "-nstep_max $(nstep_max_val) -eta_fk[0] $η0 -gamma_fk[0] $gam -TRef_fk[0] $(ΔT/2) -ch[0] $ch -nel_x $nel_x -nel_z $nel_z -coord_x $(-W/2),$(W/2) -coord_z $(-H),0 -coord_y $(-Δx/2),$(Δx/2) -temp_bot $ΔT" - - if FreeSurface - args = "-nstep_max $(nstep_max_val) -eta_fk[0] $η0 -gamma_fk[0] $gam -TRef_fk[0] $(ΔT/2) -ch[0] $ch -nel_x $nel_x -coord_x $(-W/2),$(W/2) -coord_y $(-Δx/2),$(Δx/2) -temp_bot $ΔT" - end - - @show args - # Create the setup - CreateSetup(ParamFile, ΔT, args=args) - @info "created marker setup" - - # Run LaMEM with these parameters - run_lamem(ParamFile, 1, args, wait=wait) - #run_lamem(ParamFile, 1, args) -end diff --git a/src/RayleighBenardConvection/dash_functions_convection.jl b/src/RayleighBenardConvection/dash_functions_convection.jl index 446d21e..4f00353 100644 --- a/src/RayleighBenardConvection/dash_functions_convection.jl +++ b/src/RayleighBenardConvection/dash_functions_convection.jl @@ -58,462 +58,3 @@ function CreateSetup(ParamFile, ΔT=1000, ampl_noise=100; args) return nothing end - -#= -""" - x, z, data = get_data(OutFile::String, tstep::Int64=0, field::String="phase") - -This loads the timestep `tstep` from a LaMEM simulation with field `field`. -""" -function get_data(OutFile::String, tstep::Int64=0, field::String="phase") - - data,time = Read_LaMEM_timestep(OutFile, tstep) - - value = extract_data_fields(data, field) # get field; can handle tensors & vectors as well - - - fields= String.(keys(data.fields)) - fields_available = get_fields(fields) - - x = data.x.val[:,1,1] - z = data.z.val[1,1,:] - - data2D = value[:,1,:]' - - return x, z, data2D, time[1], fields_available -end - -""" -Returns the trigger callback (simplifies code). -""" -function get_trigger() - - tr = callback_context().triggered; - trigger = [] - if !isempty(tr) - trigger = callback_context().triggered[1] - trigger = trigger[1] - end - return trigger -end - -""" -Add-ons to names for vector & tensors (used in dropdown menu). -""" -function vector_tensor() - vector = [ "_$a" for a in ["x","y","z"]] - tensor = [ "_$(b)$(a)" for a in ["x","y","z"], b in ["x","y","z"] ][:] - scalar = [""] - return scalar, vector, tensor -end - -""" -This extracts a LaMEM datafield and in case it is a tensor or scalar (and has _x, _z or so at the end). -""" -function extract_data_fields(data, field) - - _, vector, tensor = vector_tensor() - if hasfield(typeof(data.fields),Symbol(field)) # scalar - value = data.fields[Symbol(field)] - else # vector/tensor - extension = split(field,"_")[end] - n = length(extension) - name = field[1:end-n-1] - - if n==1 - id = findall(vector.=="_"*extension)[1] - else - id = findall(tensor.=="_"*extension)[1] - end - value = data.fields[Symbol(name)][id,:,:,:] - end - return value -end - -""" -Returns a list with fields. In case the LaMEM field is a vector field, it adds _x, _y etc; im case of tensor, _xx, _xy etc. -""" -function get_fields(fields) - - scalar, vector, tensor = vector_tensor() - - fields_available= [] - for f in fields - if f=="velocity" - add = vector - elseif f=="strain_rate" || f=="stress" - add = tensor - else - add = scalar - end - for a in add - push!(fields_available, f*a) - end - end - return fields_available -end - -""" -Functions building up to quiver plot -""" -function extract_velocity(OutFile, cur_t) - - data, _ = Read_LaMEM_timestep(OutFile, cur_t) - Vx = data.fields.velocity[1,:,1,:] - Vz = data.fields.velocity[3,:,1,:] - x_vel = data.x.val[:,1,1] - z_vel = data.z.val[1,1,:] - - return Vx, Vz, x_vel, z_vel -end - -""" -Interpolate velocities. -""" -function interpolate_velocities(x, z, Vx, Vz) - - # interpolate velocities to a quarter of original grid density - itp_Vx = interpolate((x, z), Vx, Gridded(Linear())) - itp_Vz = interpolate((x, z), Vz, Gridded(Linear())) - - interpolation_coords_x = LinRange(x[1], x[end], 15) - interpolation_coords_z = LinRange(z[1], z[end], 15) - - Vx_interpolated = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - Vz_interpolated = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - - itp_coords_x = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - itp_coords_z = zeros(length(interpolation_coords_x) * length(interpolation_coords_z)) - - itp_coords_x = repeat(interpolation_coords_x, outer=length(interpolation_coords_z)) - itp_coords_z = repeat(interpolation_coords_z, inner=length(interpolation_coords_x)) - - for i in eachindex(itp_coords_x) - Vx_interpolated[i] = itp_Vx(itp_coords_x[i], itp_coords_z[i]) - Vz_interpolated[i] = itp_Vz(itp_coords_x[i], itp_coords_z[i]) - end - - return Vx_interpolated, Vz_interpolated, itp_coords_x, itp_coords_z -end - -""" -Calculate angle between two vectors. -""" -function calculate_angle(Vx_interpolated, Vz_interpolated) - angle = zeros(size(Vx_interpolated)) - north = [1, 0] - for i in eachindex(angle) - angle[i] = asind((north[1] * Vx_interpolated[i] + north[2] * Vz_interpolated[i]) / (sqrt(north[1]^2 + north[2]^2) * sqrt(Vx_interpolated[i]^2 + Vz_interpolated[i]^2))) - if isnan(angle[i]) == true - angle[i] = 180.0 - end - if angle[i] < 90 && angle[i] > -90 && Vz_interpolated[i] < 0 - angle[i] = 180.0 - angle[i] - end - end - return angle -end - -""" -Calculate quiver. -""" -function calculate_quiver(OutFile, cur_t, cmaps; colorscale="batlow") - - Vx, Vz, x, z = extract_velocity(OutFile, cur_t) - Vx_interpolated, Vy_interpolated, interpolation_coords_x, interpolation_coords_z = interpolate_velocities(x, z, Vx, Vz) - angle = calculate_angle(Vx_interpolated, Vy_interpolated) - magnitude = sqrt.(Vx_interpolated .^ 2 .+ Vy_interpolated .^ 2) - - arrow_head = scatter( - x=interpolation_coords_x, - y=interpolation_coords_z, - mode="markers", - colorscale=cmaps[Symbol(colorscale)], - marker=attr(size=15, color=magnitude, angle=angle, symbol="triangle-up"), - colorbar=attr(title="Velocity", thickness=5, x=1.4), - ) - - line = scatter( - x=interpolation_coords_x, - y=interpolation_coords_z, - mode="markers", - colorscale=cmaps[Symbol(colorscale)], - marker=attr(size=10, color=magnitude, angle=angle, symbol="line-ns", line=attr(width=2, color=magnitude)), - ) - return arrow_head, line -end - -""" -This reads colormaps and transfers them into plotly format. The colormaps are supposed to be provided in ascii text format -""" -function read_colormaps(; dir_colormaps="../src/assets/colormaps/" , scaling=256) - # Read all colormaps - colormaps = NamedTuple(); - for map in readdir(dir_colormaps) - data = readdlm(dir_colormaps*map) - name_str = map[1:end-4] - - if contains(name_str,"reverse") - reverse=true - data = data[end:-1:1,:] - else - reverse=false - end - - name = Symbol(name_str) - - # apply scaling - data_rgb = Int64.(round.(data*scaling)) - - # Create the format that plotly wants: - n = size(data,1) - fac = range(0,1,n) - data_col = [ [fac[i], "rgb($(data_rgb[i,1]),$(data_rgb[i,2]),$(data_rgb[i,3]))"] for i=1:n] - - col = NamedTuple{(name,)}((data_col,)) - colormaps = merge(colormaps, col) - end - - return colormaps -end - -""" -Returns a row containing the title of the page. -""" -function make_title(title_app::String) - item = dbc_row(html_h1(title_app), style=Dict("margin-top" => 0, "textAlign" => "center")) - return item -end - -""" -Returns a row containing the main plot. -""" -function make_plot() - # w = - # h = - item = dbc_row([ - dcc_graph(id="figure_main", - figure=create_main_figure(OutFile, 0), - #animate = false, - # responsive=true, - #clickData = true, - #config = PlotConfig(displayModeBar=false, scrollZoom = false), - style=attr(width="80vw", height="80vh"), - # style=attr(width="80vw"), - ) - ]) - return item -end - -""" -Returns a column containing a screenshot button. -""" -function make_screenshot_button() - item = dbc_col([ - dbc_button("Save figure", id="button-save-fig", color="secondary", size="sg", class_name="col-4") - ], class_name="d-grid gap-2 d-md-flex justify-content-md-center") - return item -end - -""" -Returns a column containing all the media control buttons. -""" -function make_media_buttons() - item = dbc_col([ - dbc_button( - [ - html_i(className="bi bi-skip-backward-fill"), - ], - id="button-start", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - dbc_button( - [ - html_i(className="bi bi-skip-start-fill"), - ], - id="button-back", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - dbc_button( - [ - html_i(className="bi bi-play-fill"), - ], - id="button-play", outline=true, color="primary", size="sg", class_name="d-flex align-items-center" - ), - dbc_button( - [ - html_i(className="bi bi-skip-end-fill"), - ], - id="button-forward", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - dbc_button( - [ - html_i(className="bi bi-skip-forward-fill"), - ], - id="button-last", outline=true, color="primary", size="sg", class_name="d-flex align-items-center"), - ], class_name="d-grid gap-2 d-md-flex justify-content-md-center") - return item -end - -""" -Retunrs an empty column. -""" -function make_empty_col() - return dbc_col([]) -end - -""" -Retunrs an empty row. -""" -function make_empty_row() - return dbc_row([]) -end - -""" -Returns a row containing the media buttons, each one in a column. -""" -function make_plot_controls() - item = dbc_row([ - # make_screenshot_button(), - make_empty_col(), - make_media_buttons(), - make_empty_col(), - ]) - return item -end - -""" -Return a row with the id of the current user session. -""" -function make_id_label() - item = dbc_row([dbc_label("", id="label-id", color="secondary")]) - return item -end - -""" -Returns a row containing a card with time information of the simulation. -""" -function make_time_card() - item = dbc_row([ - html_p(), - dbc_card([ - dbc_label(" Time: 0 Myrs", id="label-time"), - dbc_label(" Timestep: 0", id="label-timestep" - )], - color="secondary", - class_name="mx-auto col-11", - outline=true), - html_p()]) - return item -end - -""" -Retunrs a row containing a label, a tooltip and a filling box. -""" -function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::Float64=1.0, min::Float64=1.0e-10, max::Float64=10_000.0) - item = dbc_row([ # domain width - dbc_col([ - dbc_label(label, id=idx*"_label", size="md"), - dbc_tooltip(msg, target=idx*"_label") - ]), - dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=min, size="md")) - ]) - return item -end - -""" -Retunrs a row containing a label, a tooltip and a filling box. -""" -function make_accordion_item(label::String="param", idx::String="id", msg::String="Message", value::Int64=2, min::Int64=2, max::Int64=10_000) - item = dbc_row([ # domain width - dbc_col([ - dbc_label(label, id=idx*"_label", size="md"), - dbc_tooltip(msg, target=idx*"_label") - ]), - dbc_col(dbc_input(id=idx, placeholder=string(value), value=value, type="number", min=min, size="md")) - ]) - return item -end - - - - - -""" -Returns an accordion menu containing the plotting parameters. -""" -function make_plotting_parameters() - item = dbc_accordionitem(title="Plotting Parameters", [ - dbc_row([ - dbc_label("Select field to plot: ", size="md"), - dcc_dropdown(id="plot_field", options = ["phase"], value="phase", className="col-12") - ]), - dbc_row(html_p()), - dbc_row([ # color map - dbc_col([ - dbc_label("Colormap:", id="cmap", size="md"), - dbc_tooltip(target="cmap", "Choose the colormap of the plot") - ]), - dbc_col(dcc_dropdown(id="color_map_option", options = String.(keys(cmaps)), value=String.(keys(cmaps))[1])) - ]), - dbc_row(html_p()), - dbc_row(html_hr()), - dbc_row([ - dbc_checklist(options=["Overlap plot with contour:"], - id="switch-contour", - switch=true, - ), - dbc_row(html_p()), - dbc_col(dcc_dropdown(id="contour_option" ,options = ["phase"], value="phase", disabled=true)) - ]), - dbc_row(html_p()), - dbc_row(html_hr()), - dbc_row([ - dbc_checklist(options=["Overlap velocity"], - id="switch-velocity", - switch=true, - ) - ]), - ]) - return item -end - -""" -Return a row containing the menu with the simulation, rheological and plotting parameters. -""" -function make_menu() - item = dbc_row([ - dbc_accordion(always_open=true, [ - make_simulation_parameters(), - make_rheological_parameters(), - make_plotting_parameters(), - ]), - ]) - return item -end - -""" -Returns a row containing the RUN button. -""" -function make_run_button() - item = dbc_row([ - html_p(), - dbc_button("RUN", id="button-run", size="lg", class_name="col-11 mx-auto"), - html_p()]) - return item -end - -""" -Create a new directory named by session-id -""" -function make_new_directory(session_id) - dirname = String(session_id) - if isdir("simulations") - if isdir("simulations/" * dirname) == false - mkdir("simulations/" * dirname) - end - else - mkdir("simulations") - mkdir("simulations/" * dirname) - end - user_dir = "simulations/" * dirname - return user_dir -end - - -=# \ No newline at end of file diff --git a/src/RayleighTaylorInstability/RTI_LaMEM.jl b/src/RayleighTaylorInstability/RTI_LaMEM.jl deleted file mode 100644 index 8d5002d..0000000 --- a/src/RayleighTaylorInstability/RTI_LaMEM.jl +++ /dev/null @@ -1,117 +0,0 @@ -using GLMakie -using GeophysicalModelGenerator - -Makie.inline!(true) - - -include("../src/widgets.jl") -include("../src/Basic_LaMEM_GUI.jl") - -clean_directory() - -# Define the simulation name & the output files: -ParamFile = "RTI.dat" -OutFile = "RTI" -resolution = primary_resolution() -width = round(Int,resolution[1]/11); - -if Sys.isapple() - resolution = (1900,1400) - fontsize = 30 - height_widgets = Auto(); -elseif Sys.iswindows() - fontsize = 10 - height_widgets = 25; - resolution=(1300,900) - -else - # resolution = (1200,800) - fontsize = 10 - height_widgets = Auto(); - resolution=nothing - -end - -# Create Basic GUI -fig, ax, gui = Create_Basic_LaMEM_GUI(OutFile, ParamFile, resolution=resolution, fontsize=fontsize, width=width, height=height_widgets); -ax.title = "Rayleigh Taylor Instability" - -# Add textboxes: -rho_up,_ = Textbox_with_label_left(fig[2,2][5, 1:2], L"ρ_{\mathrm{upper}} \mathrm{ [kg/m³]}", "2800", width=width, height=height_widgets); -rho_lo,_ = Textbox_with_label_left(fig[2,2][6, 1:2], L"ρ_{\mathrm{lower}} \mathrm{ [kg/m³]}", "2200", width=width, height=height_widgets); -Hi,_ = Textbox_with_label_left(fig[2,2][7, 1:2], L"H_{\mathrm{interface}} \mathrm{ [km]}", "-3.5", width=width, height=height_widgets); -Width,_ = Textbox_with_label_left(fig[2,2][8, 1:2], L"\mathrm{Width [km]}", "10", width=width, height=height_widgets); - -# Add sliders: -eta_up_sl, _, _ = Slider_with_text_above(fig[2,2][9:10,1:2], L"\log_{10}(\eta_{\mathrm{upper}} \mathrm{ [Pas]})", 18:.1:22, 20, height=height_widgets); -eta_lo_sl, _, _ = Slider_with_text_above(fig[2,2][11:12,1:2], L"\log_{10}(\eta_{\mathrm{lower}} \mathrm{ [Pas]})", 18:.1:22, 18, height=height_widgets); - -# Toggle -FreeSurf,_ = Toggle_with_label_left(fig[2,2][13, 1:2], L"\mathrm{FastErosionUpperBoundary}", false, height=height_widgets); -Layers,_ = Toggle_with_label_left(fig[2,2][14, 1:2], L"\mathrm{LayeredOverburden}", true, height=height_widgets); - - -# Create setup -function CreateSetup(ParamFile, layered_overburden=false, Hi=-5.0, ampl_noise=0.1, ; args) - Grid = ReadLaMEM_InputFile(ParamFile, args=args) - Phases = zeros(Int64, size(Grid.X)); - Temp = zeros(Float64,size(Grid.X)); - - if layered_overburden - H_layer = 0.25; - for z_low = minimum(Grid.Z):2*H_layer:maximum(Grid.Z) - iz = findall( (Grid.Z[1,1,:] .> z_low) .& (Grid.Z[1,1,:] .<= (z_low+H_layer) )) - Phases[:,:,iz] .= 1; - end - end - - z_int = ones(Grid.nump_x)*Hi + rand(Grid.nump_x)*ampl_noise - for ix=1:Grid.nump_x, iy=1:Grid.nump_y - iz = findall(Grid.Z[ix,iy,:] .< z_int[ix] ) - Phases[ix,iy,iz] .= 2; - end - - Model3D = CartData(Grid, (Phases=Phases,Temp=Temp)) # Create LaMEM model - Write_Paraview(Model3D,"LaMEM_ModelSetup", verbose=false) # Save model to paraview (load with opening LaMEM_ModelSetup.vts in paraview) - - Save_LaMEMMarkersParallel(Model3D, directory="./markers", verbose=false) # save markers on one core - - return nothing -end - -# Run the LaMEM simulation (modify some parameters if you want) -function run_code(ParamFile, gui; wait=false) - - nel_x,nel_z = retrieve_resolution(ParamFile, gui) - - Hi_value = parse(Float64,Hi.displayed_string[]) - W = parse(Float64,Width.displayed_string[]) - - η_up = 10.0^eta_up_sl.value[] - η_lo = 10.0^eta_lo_sl.value[] - ρ_up = parse(Float64,rho_up.displayed_string[]) - ρ_lo = parse(Float64,rho_lo.displayed_string[]) - FreeSurf.active[] ? open_top = 1 : open_top = 0 - Layers.active[] ? layers = true : layers = false - - - # Retrieve some parameters from the GUI - nstep_max_val = parse(Int64,gui.nstep_max_tb.displayed_string[]) - - # command-line arguments - args = "-nstep_max $(nstep_max_val) -eta[0] $η_up -eta[1] $η_up -eta[2] $η_lo -rho[0] $ρ_up -rho[1] $ρ_up -rho[2] $ρ_lo -open_top_bound $open_top -nel_x $nel_x -nel_z $nel_z -coord_x $(-W/2),$(W/2) " - - # Create the setup - CreateSetup(ParamFile, layers, Hi_value, args=args) - @info "created marker setup" - - # Run LaMEM with these parameters - @show args - run_lamem(ParamFile, 1, args, wait=wait) -end - -#screen = display(GLMakie.Screen(), fig) -#gui = (gui..., screen=screen) - - -#SaveAnimation_GUI(;fontsize=30) diff --git a/src/RisingSphere/RisingSphere_LaMEM.jl b/src/RisingSphere/RisingSphere_LaMEM.jl deleted file mode 100644 index 3ac62f2..0000000 --- a/src/RisingSphere/RisingSphere_LaMEM.jl +++ /dev/null @@ -1,168 +0,0 @@ -using GLMakie -using GeophysicalModelGenerator - -Makie.inline!(true) - - -include("../src/widgets.jl") -include("../src/Basic_LaMEM_GUI.jl") - -clean_directory() - -# Define the simulation name & the output files: -ParamFile = "RisingSphere.dat" -OutFile = "RiseSphere" -resolution = primary_resolution() -width = round(Int,resolution[1]/11); - -if Sys.isapple() - resolution = (1900,1400) - fontsize = 30 - height_widgets = Auto(); -elseif Sys.iswindows() - fontsize = 10 - height_widgets = 25; - resolution=(1300,900) - -else - # resolution = (1200,800) - fontsize = 10 - height_widgets = Auto(); - resolution=nothing - -end - -# Create Basic GUI -fig, ax, gui = Create_Basic_LaMEM_GUI(OutFile, ParamFile, resolution=resolution, fontsize=fontsize, width=width, height=height_widgets, show_velocity_toggle=false); -ax.title = "Rising Sphere Setup" -ax.aspect =1 # fix aspect ratio -gui.txt_time.text[]="maximum z velocity [cm/yr]: " - - -# Add textboxes: -rho_m,_ = Textbox_with_label_left(fig[2,2][5, 1:2], L"ρ_{\mathrm{matrix}} \mathrm{ [kg/m³]}", "3000", width=width, height=height_widgets); -rho_s,_ = Textbox_with_label_left(fig[2,2][6, 1:2], L"ρ_{\mathrm{sphere}} \mathrm{ [kg/m³]}", "2800", width=width, height=height_widgets); -Radius,_ = Textbox_with_label_left(fig[2,2][7, 1:2], L"\mathrm{Radius [km]}", "0.1", width=width, height=height_widgets); -Width,_ = Textbox_with_label_left(fig[2,2][8, 1:2], L"\mathrm{Width [km]}", "2", width=width, height=height_widgets); - -# Add sliders: -eta_m_sl, _, _ = Slider_with_text_above(fig[2,2][9:10,1:2], L"\log_{10}(\eta_{\mathrm{matrix}} \mathrm{ [Pas]})", 16:.5:20, 18, height=height_widgets); -eta_s_sl, _, _ = Slider_with_text_above(fig[2,2][11:12,1:2], L"\log_{10}(\eta_{\mathrm{sphere}} \mathrm{ [Pas]})", 17:.5:25, 22, height=height_widgets); - -# Toggle -vel_sl, _, _ = Slider_with_text_above(fig[2,2][14:15,1:2], "Arrow length", 0.1:1:50, 10, height=height_widgets); - -#FreeSurf,_ = Toggle_with_label_left(fig[2,2][13, 1:2], L"\mathrm{FastErosionUpperBoundary}", false, height=height_widgets); -#Layers,_ = Toggle_with_label_left(fig[2,2][14, 1:2], L"\mathrm{LayeredOverburden}", true, height=height_widgets); - - -function update_info(gui::NamedTuple, values::NamedTuple) - pad_space = 15 - gui.time.displayed_string[] = rpad(string(round(values.maxVz[1]; digits=6)),pad_space) - gui.timestep.displayed_string[] = rpad(string(values.t_step),pad_space) - - return nothing -end - -# Basic code -function update_plot_info_basic(OutFile, gui::NamedTuple, t_step::Int64; last=false) - - # Load LaMEM result - if last - Timestep, _, _ = Read_LaMEM_simulation(OutFile) - t_step = Timestep[end] - end - - data, time = Read_LaMEM_timestep(OutFile, t_step, last=last); - - vel = data.fields.velocity; #velocity - Vz = vel[3,:,:,:] # Vz - - # update info window - values = (t_step=t_step, time=time, maxVz=maximum(Vz)); - @info "Max. vertical velocity [cm/yr] = $(maximum(Vz))" - update_info(gui, values) - - # Read the field from the LaMEM dataset - ifield = gui.menu.i_selected[] - component = parse(Int,gui.menu_comp.stored_string[]) - data_field = Read_data_field(ifield, data, component) - - # set label of colorbar - gui.cb.label= Read_LaMEM_fieldnames(OutFile)[ifield] - - lim = Float64.(extrema(data_field)) - try # this deals with a bug that sometimes occurs - gui.cb.limits = lim - catch - gui.cb.limits = lim .+ (-1e-3,1e-3) - end - - # plot the field that is selected in the dropdown menu - gui.hm[1] = data.x.val[:,1,1]; - gui.hm[2] = data.z.val[1,1,:]; - gui.hm[3] = data_field - - aspect_ratio = (data.x.val[end]- data.x.val[1]) / (data.z.val[end]- data.z.val[1]) - - # plot velocity arrows if requested - num_z = 50; - num_x = round(Int64,num_z*aspect_ratio); - x,z = data.x.val[:,1,1], data.z.val[1,1,:]; - Vx,Vz = data.fields.velocity[1,:,1,:], data.fields.velocity[3,:,1,:]; - x_low = range(x[1], x[end], num_x); - z_low = range(z[1], z[end], num_z) - Vx_itp = linear_interpolation((x,z), Vx; extrapolation_bc=Throw()) - Vz_itp = linear_interpolation((x,z), Vz; extrapolation_bc=Throw()) - pt_arrow = []; - vel_arrow = [] - for x in x_low, z in z_low - push!(pt_arrow, Point2f(x,z)) - push!(vel_arrow, Vec2f(Vx_itp(x, z),Vz_itp(x, z))) - end - gui.pt_arrow[]= pt_arrow - gui.vel_arrow[]= vel_arrow - xlims!(ax,x[1],x[end]) - ylims!(ax,z[1],z[end]) - - # scale length of arrow - gui.arrows.visible[]=true - gui.arrows.lengthscale= vel_sl.value[] - - display(fig) - sleep(1/60) - - return t_step, data -end - -# Run the LaMEM simulation (modify some parameters if you want) -function run_code(ParamFile, gui; wait=true) - - nel_x,nel_z = retrieve_resolution(ParamFile, gui) - - W = parse(Float64,Width.displayed_string[]) - R = parse(Float64, Radius.displayed_string[]) - η_m = 10.0^eta_m_sl.value[] - η_s = 10.0^eta_s_sl.value[] - ρ_m = parse(Float64,rho_m.displayed_string[]) - ρ_s = parse(Float64,rho_s.displayed_string[]) - # FreeSurf.active[] ? open_top = 1 : open_top = 0 - # Layers.active[] ? layers = true : layers = false - - # Retrieve some parameters from the GUI - nstep_max_val = parse(Int64,gui.nstep_max_tb.displayed_string[]) - - # command-line arguments - args = "-nstep_max $(nstep_max_val) -radius[0] $R -eta[0] $η_m -eta[1] $η_s -rho[0] $ρ_m -rho[1] $ρ_s -nel_x $nel_x -nel_z $nel_z -coord_x $(-W/2),$(W/2) -coord_z $(-W/2),$(W/2)" - - # Run LaMEM with these parameters - @show args - wait=false; - run_lamem(ParamFile, 1, args, wait=wait) -end - -#screen = display(GLMakie.Screen(), fig) -#gui = (gui..., screen=screen) - - -#SaveAnimation_GUI(;fontsize=30) diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 2dca39d..3aa37dd 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -27,7 +27,7 @@ function create_main_figure(OutFile, cur_t, x=1:10, y=1:10, data=rand(10, 10), y=y, z=data, colorscale=cmaps[Symbol(colorscale)], - colorbar=attr(thickness=5, title=field), + colorbar=attr(thickness=5, title=field, len=0.75), #zmin=zmin, zmax=zmax ) ] @@ -39,7 +39,7 @@ function create_main_figure(OutFile, cur_t, x=1:10, y=1:10, data=rand(10, 10), colorscale=cmaps[Symbol(colorscale)], contours_coloring="lines", line_width=2, - colorbar=attr(thickness=5, title=contour_field, x=1.2, yanchor=0.5), + colorbar=attr(thickness=5, title=contour_field, x=1.2, yanchor=0.5, len=0.75), #zmin=zmin, zmax=zmax ))) end @@ -61,18 +61,24 @@ function create_main_figure(OutFile, cur_t, x=1:10, y=1:10, data=rand(10, 10), tickfont_size=14, tickfont_color="rgb(100, 100, 100)", scaleanchor="y", scaleratio=1, - autorange="true", automargin=true, - range=[-1,4], + autorange=false, automargin="top", + range=[x[1],x[end]], + showgrid=false, + zeroline=false ), yaxis=attr( title="Depth", tickfont_size=14, tickfont_color="rgb(10, 10, 10)", - autorange="true", automargin=true, - range=[-1,4], - ), - #margin=attr(l=20, r=20, b=20, t=20, pad=1), - margin=attr(autoexpand="true"), + autorange=false, automargin="top", + autorangeoptions=attr(clipmax=0), + range=[minimum(y),maximum(y)], + showgrid=false, + zeroline=false + ), + + margin=attr(l=10, r=0, b=10, t=0), + #margin=attr(autoexpand="true", pad=1), autosize=true ), config=(edits = (shapePosition=true,)), @@ -456,11 +462,11 @@ end """ Returns an accordion menu containing the plotting parameters. """ -function make_plotting_parameters(cmaps) +function make_plotting_parameters(cmaps; show_field="phase") item = dbc_accordionitem(title="Plotting Parameters", [ dbc_row([ dbc_label("Select field to plot: ", size="md"), - dcc_dropdown(id="plot_field", options = ["phase"], value="phase", className="col-12") + dcc_dropdown(id="plot_field", options = [show_field], value=show_field, className="col-12") ]), dbc_row(html_p()), dbc_row([ # color map @@ -493,14 +499,15 @@ function make_plotting_parameters(cmaps) end """ + make_menu(cmaps; show_field="phase") Return a row containing the menu with the simulation, rheological and plotting parameters. """ -function make_menu(cmaps) +function make_menu(cmaps; show_field="phase") item = dbc_row([ dbc_accordion(always_open=true, [ make_simulation_parameters(), make_rheological_parameters(), - make_plotting_parameters(cmaps), + make_plotting_parameters(cmaps, show_field=show_field), ]), ]) return item diff --git a/src/utils.jl b/src/utils.jl deleted file mode 100644 index 0ccbd31..0000000 --- a/src/utils.jl +++ /dev/null @@ -1,51 +0,0 @@ -using GLMakie - -function primary_resolution() - monitor = GLMakie.GLFW.GetPrimaryMonitor() - videomode = GLMakie.MonitorProperties(monitor).videomode - return (videomode.width, videomode.height) -end - - -""" - nel_x,nel_z = retrieve_resolution(ParamFile, gui) - -Read the resolution from the GUI and the parameter file -""" -function retrieve_resolution(ParamFile, gui) - - nel_x_file = GeophysicalModelGenerator.ParseValue_LaMEM_InputFile(ParamFile,"nel_x", Int64); - nel_z_file = GeophysicalModelGenerator.ParseValue_LaMEM_InputFile(ParamFile,"nel_z", Int64); - Aspect = nel_x_file/sum(nel_z_file) - nel_z = parse(Int64,gui.nel_z.displayed_string[]) - - if length(nel_z_file)==1 - nel_x = round(Int64,nel_z*Aspect) - else - nel_x = round(Int64,nel_z*Aspect) - end - - #nel_z = round(Int64,nel_z_file/nel_x_file*nel_x) - - return nel_x, nel_z -end - - -""" - values = get_values_textboxes(tb::NTuple) - -Returns values as floats from textboxes -""" -function get_values_textboxes(tb::NTuple) - - values=() - for textb in tb - - val = parse(Float64,textb.displayed_string[]) - values = (values...,val) - - end - - return values -end - diff --git a/src/widgets.jl b/src/widgets.jl deleted file mode 100644 index b3ab416..0000000 --- a/src/widgets.jl +++ /dev/null @@ -1,191 +0,0 @@ -# This contains a number of widgets to make it easier to setup a GUI for LaMEM -using GridLayoutBase - -""" - Slider_with_text_above(pos::GridPosition, text::String, val_range::StepRangeLen, start_val) -Create a slider with text above it, along with changing values. `pos` is the position of the slider + text above - -Example -=== -```julia -julia> eta_up_sl, _, _ = Slider_with_text_above(fig[6:7,6:7], "log₁₀(ηᵤₚₚₑᵣ [Pas])", 18:.1:22, 20) -``` -""" -function Slider_with_text_above(pos::GridPosition, text, val_range::StepRangeLen, start_val; height=Auto()) - span_top_left = GridLayoutBase.Span(pos.span.rows[1]:pos.span.rows[1], pos.span.cols[1]:pos.span.cols[1] ); - span_top_right = GridLayoutBase.Span(pos.span.rows[1]:pos.span.rows[1], pos.span.cols[2]:pos.span.cols[2] ); - span_bot = GridLayoutBase.Span(pos.span.rows[2]:pos.span.rows[2], pos.span.cols ); - - pos_tl = GridPosition(pos.layout, span_top_left, pos.side) - pos_tr = GridPosition(pos.layout, span_top_right, pos.side) - pos_bt = GridPosition(pos.layout, span_bot, pos.side) - - text1 = Label(pos_tl, text, height=height) - text2 = Label(pos_tr, "1", width=Relative(0.5), height=height) - sl = Slider(pos_bt, range = val_range, startvalue = start_val, height=height) - lift(sl.value) do x - text2.text[] = "$x" - end - - return sl, text1, text2 -end - - -function Slider_with_text_above(pos::GridSubposition, text, val_range::StepRangeLen, start_val; height=Auto()) - pos_tl = GridSubposition(pos.parent, pos.rows[1], pos.cols[1], pos.side) - pos_tr = GridSubposition(pos.parent, pos.rows[1], pos.cols[2], pos.side) - pos_bt = GridSubposition(pos.parent, pos.rows[2], pos.cols , pos.side) - - - - text1 = Label(pos_tl, text, height=height) - text2 = Label(pos_tr, "1", width=Relative(0.5), height=height) - sl = Slider(pos_bt, range = val_range, startvalue = start_val, height=height) - lift(sl.value) do x - text2.text[] = "$x" - end - - return sl, text1, text2 -end - -""" - Textbox_with_label_left(pos::GridPosition, text::String, start_val) -Creates a textbox with a label to the left. Here `pos` is the full position (label + textbox) -""" -function Textbox_with_label_left(pos::GridPosition, text, start_val; - boxcolor_hover=:grey90, - bordercolor=GLMakie.RGB{Float32}(0.8f0,0.8f0,0.8f0), - bordercolor_hover=GLMakie.RGB{Float32}(0.68235296f0,0.7529412f0,0.9019608f0), - textcolor_placeholder= :black, - width = GLMakie.Auto(true, 1.0f0), - height = Auto() - ) - span_left = GridLayoutBase.Span(pos.span.rows, pos.span.cols[1]:pos.span.cols[1] ); - span_right = GridLayoutBase.Span(pos.span.rows, pos.span.cols[2]:pos.span.cols[2] ); - pos_l = GridPosition(pos.layout, span_left, pos.side) - pos_r = GridPosition(pos.layout, span_right, pos.side) - - text = Label(pos_l, text) - tb = Textbox(pos_r, placeholder = start_val, stored_string=string(start_val), - boxcolor_hover=boxcolor_hover, - bordercolor=bordercolor, - bordercolor_hover=bordercolor_hover, - textcolor_placeholder=textcolor_placeholder, - width=width, height=height) - - return tb, text -end - - -function Textbox_with_label_left(pos::GridSubposition, text, start_val; - boxcolor_hover=:grey90, - bordercolor=GLMakie.RGB{Float32}(0.8f0,0.8f0,0.8f0), - bordercolor_hover=GLMakie.RGB{Float32}(0.68235296f0,0.7529412f0,0.9019608f0), - textcolor_placeholder= :black, - width = GLMakie.Auto(true, 1.0f0), - height = Auto() - ) - pos_l = GridSubposition(pos.parent, pos.rows[1], pos.cols[1], pos.side) - pos_r = GridSubposition(pos.parent, pos.rows[1], pos.cols[2], pos.side) - - text = Label(pos_l, text) - tb = Textbox(pos_r, placeholder = start_val, stored_string=string(start_val), - boxcolor_hover=boxcolor_hover, - bordercolor=bordercolor, - bordercolor_hover=bordercolor_hover, - textcolor_placeholder=textcolor_placeholder, - width=width, height=height) - - return tb, text -end - - -""" - Toggle_with_label_left(pos::GridPosition, text::NTuple, active::Bool) -Creates a toggle with a label to the left. Here `pos` is the full position (label + textbox) -""" -function Toggle_with_label_left(pos::GridPosition, text_in, active::Bool; height=Auto()) - span_left = GridLayoutBase.Span(pos.span.rows, pos.span.cols[1]:pos.span.cols[1] ); - span_right = GridLayoutBase.Span(pos.span.rows, pos.span.cols[2]:pos.span.cols[2] ); - pos_l = GridPosition(pos.layout, span_left, pos.side) - pos_r = GridPosition(pos.layout, span_right, pos.side) - - text1 = Label(pos_l, text_in, height=height) - tog = Toggle(pos_r, active = active, height=height) - - return tog, text1 -end - -function Toggle_with_label_left(pos::GridSubposition, text_in, active::Bool; height=Auto()) - pos_l = GridSubposition(pos.parent, pos.rows[1], pos.cols[1], pos.side) - pos_r = GridSubposition(pos.parent, pos.rows[1], pos.cols[2], pos.side) - - text1 = Label(pos_l, text_in, height=height) - tog = Toggle(pos_r, active = active, height=height) - - return tog, text1 -end - -""" - Add_info_label(pos::GridPosition, text::String, start_val; width=100) -Creates label with a text label to the left and a numeric value (e.g. time) on the right. -Here `pos` is the full position (label + textbox) -""" -function Add_info_label(pos::GridPosition, text, start_val; width=100, height=Auto()) - span_left = GridLayoutBase.Span(pos.span.rows, pos.span.cols[1]:pos.span.cols[1] ); - span_right = GridLayoutBase.Span(pos.span.rows, pos.span.cols[2]:pos.span.cols[2] ); - pos_l = GridPosition(pos.layout, span_left, pos.side) - pos_r = GridPosition(pos.layout, span_right, pos.side) - - text = Label(pos_l, text, justification = :right, width=width, height=height) - tb = Label(pos_r, rpad(string(start_val),15), justification = :left, width=width, height=height) - - return tb, text -end - - -""" - update_fields_menu(OutFile, menu) -Updates the dropdown menu -""" -function update_fields_menu(OutFile, menu) - data,_ = Read_LaMEM_timestep(OutFile); # read a filename - names = string.(keys(data.fields)); # names - menu.options[] = [names...] - menu.i_selected[] = 1 - return Nothing -end - - - -function keyword_LaMEM_inputfile(file,keyword,type) - value = nothing - for line in eachline(file) - line_strip = lstrip(line) # strip leading tabs/spaces - - # Strip comments - ind = findfirst("#", line) - if isnothing(ind) - # no comments - else - line_strip = line_strip[1:ind[1]-2]; - end - line_strip = rstrip(line_strip) # strip last tabs/spaces - - if startswith(line_strip, keyword) - ind = findfirst("=", line_strip) - if type==String - value = split(line_strip)[3:end] - else - value = parse.(type,split(line_strip)[3:end]) - - if length(value)==1 - value=value[1]; - end - end - end - - end - - return value -end From 2753c6520dabc11a01231173bc7a13c4d8dc60e2 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Sun, 1 Oct 2023 12:46:34 +0200 Subject: [PATCH 14/14] slightly nicer, but still too much space between plot & axes --- src/dash_tools.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dash_tools.jl b/src/dash_tools.jl index 3aa37dd..b31936f 100644 --- a/src/dash_tools.jl +++ b/src/dash_tools.jl @@ -77,8 +77,8 @@ function create_main_figure(OutFile, cur_t, x=1:10, y=1:10, data=rand(10, 10), zeroline=false ), - margin=attr(l=10, r=0, b=10, t=0), - #margin=attr(autoexpand="true", pad=1), + #margin=attr(l=10, r=0, b=10, t=0), + margin=attr(autoexpand="true", pad=1), autosize=true ), config=(edits = (shapePosition=true,)),