From e263128dc1b03fd0cb864ee2cf3a24232986aeb3 Mon Sep 17 00:00:00 2001 From: Pascal Aellig Date: Tue, 24 Sep 2024 16:14:07 +0200 Subject: [PATCH] update --- SillModelSetup.jl | 140 +++++++++++++++++++++++++++++++++++++++++++ Sill_2D_OM.jl | 148 ++++++++++++++++++++++------------------------ Sill_rheology.jl | 68 +++++++++++++++++---- 3 files changed, 268 insertions(+), 88 deletions(-) create mode 100644 SillModelSetup.jl diff --git a/SillModelSetup.jl b/SillModelSetup.jl new file mode 100644 index 000000000..cb148f419 --- /dev/null +++ b/SillModelSetup.jl @@ -0,0 +1,140 @@ +## Model Setup + +function SillSetup(nx, ny, nz; sticky_air=5) + Lx = Ly = 50 + x = range(0.0, Lx, nx) + y = range(0.0, Ly, 2) + z = range(-25, sticky_air, nz) + Grid = CartData(xyz_grid(x, y, z)) + + # Now we create an integer array that will hold the `Phases` information (which usually refers to the material or rock type in the simulation) + Phases = fill(4, nx, 2, nz) + + # In many (geodynamic) models, one also has to define the temperature, so lets define it as well + Temp = fill(0.0, nx, 2, nz) + + add_box!( + Phases, + Temp, + Grid; + xlim=(minimum(Grid.x.val), maximum(Grid.x.val)), + ylim=(minimum(Grid.y.val), maximum(Grid.y.val)), + zlim=(minimum(Grid.z.val), 0.0), + phase=LithosphericPhases(; Layers=[30], Phases=[1]), + T=HalfspaceCoolingTemp(; Age=20), + ) + + # add_volcano!(Phases, Temp, Grid; + # volcanic_phase = 1, + # center = (mean(Grid.x.val), 0.0), + # height = 3, + # radius = 5, + # crater = 0.5, + # base = 0.0, + # background = nothing, + # T = HalfspaceCoolingTemp(Age=20) + # ) + + add_ellipsoid!( + Phases, + Temp, + Grid; + cen=(mean(Grid.x.val), 0, -5.0), + axes=(3.5, 2.5, 2.0), + phase=ConstantPhase(2), + T=ConstantTemp(; T=1000), + ) + # add_sphere!(Phases, Temp, Grid; + # cen = (mean(Grid.x.val), 0,-5.0), + # radius = 0.5, + # phase = ConstantPhase(3), + # T = ConstantTemp(T=1100) + # ) + # add_cylinder!(Phases, Temp, Grid; + # base = (mean(Grid.x.val), 0, -3.25), + # cap = (mean(Grid.x.val), 0, 3.00), + # radius = 0.05, + # phase = ConstantPhase(2), + # # T = LinearTemp(Ttop=20, Tbot=1000), + # # T = ConstantTemp(T=800), + # T = ConstantTemp(T=1000), + # ) + + Grid = addfield(Grid, (; Phases, Temp)) + + li = (abs(last(x) - first(x)), abs(last(z) - first(z))) + origin = (x[1], z[1]) + + ph = Phases[:, 1, :] + T = Temp[:, 1, :] + # write_paraview(Grid, "Volcano2D") + return li, origin, ph, T, Grid +end + +function simple_setup_no_FS2D(nx, ny, nz) + Lx = Ly = 40 + + x = range(-Lx / 2, Lx / 2, nx) + z = range(-20, 0, nz) + Grid = CartData(xyz_grid(x, 0, z)) + + # Now we create an integer array that will hold the `Phases` information (which usually refers to the material or rock type in the simulation) + Phases = fill(4, nx, 1, nz) + + # In many (geodynamic) models, one also has to define the temperature, so lets define it as well + Temp = fill(20.0, nx, 1, nz) + + add_box!( + Phases, + Temp, + Grid; + xlim=(minimum(Grid.x.val), maximum(Grid.x.val)), + zlim=(minimum(Grid.z.val), maximum(Grid.z.val)), + phase=LithosphericPhases(; Layers=[30], Phases=[1]), + T=HalfspaceCoolingTemp(; Age=20), + ) + + add_ellipsoid!( + Phases, + Temp, + Grid; + cen=(0, 0, -5), + axes=(2.5, 2.5, 2.5 / 2), + phase=ConstantPhase(2), + T=ConstantTemp(; T=1000), + ) + add_sphere!( + Phases, + Temp, + Grid; + cen=(0, 0, -5.0), + radius=0.5, + phase=ConstantPhase(3), + T=ConstantTemp(; T=1200), + ) + add_cylinder!( + Phases, + Temp, + Grid; + base=(0, 0, -4.0), + cap=(0, 0, 4.0), + radius=0.5, + phase=ConstantPhase(2), + T=LinearTemp(; Ttop=20, Tbot=1000), + ) + + surf = Grid.z.val .> 0.0 + Temp[surf] .= 20.0 + Phases[surf] .= 4 + @. Temp[Phases == 4] = 20 + @. Temp = max(Temp, 20) + Grid = addfield(Grid, (; Phases, Temp)) + + li = (abs(last(x) - first(x)), abs(last(z) - first(z))) .* 1e3 + origin = (x[1], z[1]) .* 1e3 + + ph = Phases + T = Temp + write_paraview(Grid, "Volcano2D") + return li, origin, ph, T +end diff --git a/Sill_2D_OM.jl b/Sill_2D_OM.jl index 22828b005..7bc9f709e 100644 --- a/Sill_2D_OM.jl +++ b/Sill_2D_OM.jl @@ -1,23 +1,40 @@ -using CUDA -# CUDA.allowscalar(false) -using JustRelax, JustRelax.DataIO -import JustRelax.@cell -using ParallelStencil -@init_parallel_stencil(CUDA, Float64, 2) #or (CUDA, Float64, 2) or (AMDGPU, Float64, 2) - -using JustPIC -using JustPIC._2D +const isCUDA = false + +@static if isCUDA + using CUDA + CUDA.allowscalar(true) +end + +using JustRelax, JustRelax.JustRelax2D, JustRelax.DataIO + + +const backend_JR = @static if isCUDA + CUDABackend # Options: CPUBackend, CUDABackend, AMDGPUBackend +else + JustRelax.CPUBackend # Options: CPUBackend, CUDABackend, AMDGPUBackend +end + +using ParallelStencil, ParallelStencil.FiniteDifferences2D + +@static if isCUDA + @init_parallel_stencil(CUDA, Float64, 2) +else + @init_parallel_stencil(Threads, Float64, 2) +end + +using JustPIC, JustPIC._2D # Threads is the default backend, # to run on a CUDA GPU load CUDA.jl (i.e. "using CUDA") at the beginning of the script, # and to run on an AMD GPU load AMDGPU.jl (i.e. "using AMDGPU") at the beginning of the script. -const backend = CUDABackend # Options: CPUBackend, CUDABackend, AMDGPUBackend - -# setup ParallelStencil.jl environment -model = PS_Setup(:CUDA, Float64, 2) #or (:CUDA, Float64, 2) or (:AMDGPU, Float64, 2) -environment!(model) +const backend = @static if isCUDA + CUDABackend # Options: CPUBackend, CUDABackend, AMDGPUBackend +else + JustPIC.CPUBackend # Options: CPUBackend, CUDABackend, AMDGPUBackend +end -# Load script dependencies -using Printf, LinearAlgebra, GeoParams, CairoMakie, CellArrays, WriteVTK +using Printf, Statistics, LinearAlgebra, GeoParams, CairoMakie, CellArrays +import GeoParams.Dislocation +using StaticArrays, WriteVTK, JLD2, Dates # Load file with all the rheology configurations include("Sill_rheology.jl") @@ -65,25 +82,10 @@ end return nothing end -@parallel_indices (i, j) function compute_melt_fraction!(ϕ, rheology, args) - ϕ[i, j] = compute_meltfraction(rheology, ntuple_idx(args, i, j)) - return nothing -end - -@parallel_indices (I...) function compute_melt_fraction!(ϕ, phase_ratios, rheology, args) -args_ijk = ntuple_idx(args, I...) -ϕ[I...] = compute_melt_frac(rheology, args_ijk, phase_ratios[I...]) -return nothing -end - -@inline function compute_melt_frac(rheology, args, phase_ratios) - return GeoParams.compute_meltfraction_ratio(phase_ratios, rheology, args) -end - ## END OF HELPER FUNCTION ------------------------------------------------------------ ## BEGIN OF MAIN SCRIPT -------------------------------------------------------------- -function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_save_vtk =false) +# function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_vtk =false) # Physical domain ------------------------------------ lx = 0.5e3 # domain length in x @@ -98,6 +100,7 @@ function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_save_vtk =false) # Physical properties using GeoParams ---------------- rheology = init_rheologies(; is_plastic = false) + cutoff_visc = (-Inf,Inf) # κ = (4 / (compute_heatcapacity(rheology[1].HeatCapacity[1].Cp) * 2900.0)) κ = (4 / (compute_heatcapacity(rheology[1].HeatCapacity[1].Cp) * rheology[1].Density[1].ρ)) # κ = (4 / (rheology[1].HeatCapacity[1].Cp * rheology[1].Density[1].ρ)) @@ -108,10 +111,8 @@ function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_save_vtk =false) # ---------------------------------------------------- # Initialize particles ------------------------------- - nxcell, max_xcell, min_xcell = 20, 40, 1 - particles = init_particles( - backend, nxcell, max_xcell, min_xcell, xvi..., di..., ni... - ) + nxcell, max_xcell, min_xcell = 30, 40, 20 + particles = init_particles(backend, nxcell, max_xcell, min_xcell, xvi...); subgrid_arrays = SubgridDiffusionCellArrays(particles) @@ -123,48 +124,43 @@ function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_save_vtk =false) # initialize phases init_phases!(pPhases, particles) - phase_ratios = PhaseRatio(ni, length(rheology)) - @parallel (@idx ni) phase_ratios_center(phase_ratios.center, pPhases) + phase_ratios = PhaseRatios(backend, length(rheology), ni); + JustPIC._2D.phase_ratios_center!(phase_ratios, particles, xci, pPhases) # ---------------------------------------------------- # STOKES --------------------------------------------- # Allocate arrays needed for every Stokes problem - stokes = StokesArrays(ni, ViscoElastic) - pt_stokes = PTStokesCoeffs(li, di; ϵ=5e-5, CFL = 0.95 / √2.1) + stokes = StokesArrays(backend_JR, ni) + pt_stokes = PTStokesCoeffs(li, di; ϵ=1e-4, CFL=0.9 / √2.1) #ϵ=1e-4, CFL=1 / √2.1 CFL=0.27 / √2.1 # ---------------------------------------------------- # TEMPERATURE PROFILE -------------------------------- - thermal = ThermalArrays(ni) - thermal_bc = TemperatureBoundaryConditions(; - no_flux = (left = true, right = true, top = false, bot = false), - periodicity = (left = false, right = false, top = false, bot = false), + thermal = ThermalArrays(backend_JR, ni) + thermal_bc = TemperatureBoundaryConditions(; + no_flux = (left = true, right = true, top = false, bot = false), ) # initialize thermal profile - Half space cooling @parallel (@idx ni .+ 1) init_T!(thermal.T, xvi[2], xvi[1]) - thermal_bcs!(thermal.T, thermal_bc) - - @parallel (JustRelax.@idx size(thermal.Tc)...) temperature2center!(thermal.Tc, thermal.T) + thermal_bcs!(thermal, thermal_bc) + temperature2center!(thermal) # ---------------------------------------------------- #melt fraction - ϕ = @zeros(ni...) - @parallel (@idx ni) compute_melt_fraction!( - ϕ, phase_ratios.center, rheology, (T=thermal.Tc, P=stokes.P) - ) - + ϕ = @zeros(ni...) + args = (; ϕ=ϕ, T=thermal.Tc, P=stokes.P, dt=dt)#, ΔTc=thermal.ΔTc) # Buoyancy forces ρg = @zeros(ni...), @zeros(ni...) - for _ in 1:1 - @parallel (JustRelax.@idx ni) compute_ρg!(ρg[2], phase_ratios.center, rheology, (T=thermal.Tc, P=stokes.P, ϕ= ϕ)) + for _ in 1:5 + compute_ρg!(ρg[end], phase_ratios, rheology, (T=thermal.Tc, P=stokes.P)) @parallel init_P!(stokes.P, ρg[2], xci[2]) end # Rheology - η = @ones(ni...) - args = (; T = thermal.Tc, P = stokes.P, dt = dt, ϕ=ϕ) - @parallel (@idx ni) compute_viscosity!( - η, 1.0, phase_ratios.center, @strain(stokes)..., args, rheology, (-Inf, Inf) + compute_melt_fraction!( + ϕ, phase_ratios.center, rheology, (T=thermal.Tc, P=stokes.P) ) - η_vep = copy(η) - # ϕ = similar(η) + compute_viscosity!(stokes, phase_ratios, args, rheology, cutoff_visc) + + @copy stokes.P0 stokes.P + @copy thermal.Told thermal.T # PT coefficients for thermal diffusion pt_thermal = PTThermalCoeffs( @@ -172,16 +168,15 @@ function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_save_vtk =false) ) # Boundary conditions - flow_bcs = FlowBoundaryConditions(; + flow_bcs = VelocityBoundaryConditions(; free_slip = (left = true, right=true, top=true, bot=true), - periodicity = (left = false, right = false, top = false, bot = false), ) flow_bcs!(stokes, flow_bcs) # apply boundary conditions - update_halo!(stokes.V.Vx, stokes.V.Vy) + update_halo!(@velocity(stokes)...) # IO ----- ------------------------------------------- # if it does not exist, make folder where figures are stored - if do_save_vtk + if do_vtk vtk_dir = joinpath(figdir,"vtk") take(vtk_dir) end @@ -211,9 +206,10 @@ function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_save_vtk =false) copyinn_x!(dst, src) end grid2particle!(pT, xvi, T_buffer, particles) + pT0.data .= pT.data local Vx_v, Vy_v - if do_save_vtk + if do_vtk Vx_v = @zeros(ni.+1...) Vy_v = @zeros(ni.+1...) end @@ -324,7 +320,7 @@ function main2D(igg; ar=8, ny=16, nx=ny*8, figdir="figs2D", do_save_vtk =false) if it == 1 || rem(it, 100) == 0 checkpointing(figdir, stokes, thermal.T, η, t) - if do_save_vtk + if do_vtk JustRelax.velocity2vertex!(Vx_v, Vy_v, @velocity(stokes)...) data_v = (; @@ -469,18 +465,18 @@ end # (Path)/folder where output data and figures are stored -figdir = "240325_OM_Geometry_bas1e5_rhy1e3" -# figdir = "test_JP" -do_save_vtk = true # set to true to generate VTK files for ParaView -ar = 2 # aspect ratio -n = 512 -nx = n*ar - 2 -ny = n - 2 -igg = if !(JustRelax.MPI.Initialized()) # initialize (or not) MPI grid - IGG(init_global_grid(nx, ny, 1; init_MPI= true)...) +figdir = "$(today())_OM_Geometry_bas1e5_rhy1e3" +do_vtk = false +ar = 1 # aspect ratio +n = 64 +nx = n * ar +ny = n +nz = n +igg = if !(JustRelax.MPI.Initialized()) + IGG(init_global_grid(nx, ny, 1; init_MPI=true)...) else igg end # run main script -main2D(igg; figdir = figdir, ar = ar, nx = nx, ny = ny, do_save_vtk = do_save_vtk); +main2D(igg; figdir = figdir, ar = ar, nx = nx, ny = ny, do_vtk = do_vtk); diff --git a/Sill_rheology.jl b/Sill_rheology.jl index e2d3e895f..11c977e7d 100644 --- a/Sill_rheology.jl +++ b/Sill_rheology.jl @@ -88,25 +88,69 @@ function init_rheologies(; is_plastic = true) end -function init_phases!(phases, particles) +# function init_phases!(phases, particles) +# ni = size(phases) + +# @parallel_indices (i, j) function init_phases!(phases, px, py, index) +# @inbounds for ip in JustPIC._2D.cellaxes(phases) +# # quick escape +# @index(index[ip, i, j]) == 0 && continue + +# x = @index px[ip, i, j] +# depth = -(@index py[ip, i, j]) +# @index phases[ip, i, j] = 1.0 + +# if 0.1e3 < depth ≤ 0.2e3 +# @index phases[ip, i, j] = 2.0 + +# end +# end +# return nothing +# end + +# @parallel (@idx ni) init_phases!(phases, particles.coords..., particles.index) +# end +function init_phases2D!(phases, phase_grid, particles, xvi) + ni = size(phases) + @parallel (@idx ni) _init_phases2D!( + phases, phase_grid, particles.coords, particles.index, xvi + ) +end + +@parallel_indices (I...) function _init_phases2D!( + phases, phase_grid, pcoords::NTuple{N,T}, index, xvi +) where {N,T} ni = size(phases) - @parallel_indices (i, j) function init_phases!(phases, px, py, index) - @inbounds for ip in JustRelax.cellaxes(phases) - # quick escape - JustRelax.@cell(index[ip, i, j]) == 0 && continue + for ip in JustRelax.cellaxes(phases) + # quick escape + @index(index[ip, I...]) == 0 && continue + + pᵢ = ntuple(Val(N)) do i + @index pcoords[i][ip, I...] + end - x = JustRelax.@cell px[ip, i, j] - depth = -(JustRelax.@cell py[ip, i, j]) - @cell phases[ip, i, j] = 1.0 + d = Inf # distance to the nearest particle + particle_phase = -1 + for offi in 0:1, offj in 0:1 + ii = I[1] + offi + jj = I[2] + offj - if 0.1e3 < depth ≤ 0.2e3 - @cell phases[ip, i, j] = 2.0 + !(ii ≤ ni[1]) && continue + !(jj ≤ ni[2]) && continue + xvᵢ = (xvi[1][ii], xvi[2][jj]) + d_ijk = √(sum((pᵢ[i] - xvᵢ[i])^2 for i in 1:N)) + if d_ijk < d + d = d_ijk + particle_phase = phase_grid[ii, jj] end + # if pᵢ[end] > 0.0 && phase_grid[ii, jj] > 1.0 + # particle_phase = 4.0 + # end end - return nothing + @index phases[ip, I...] = Float64(particle_phase) end - @parallel (JustRelax.@idx ni) init_phases!(phases, particles.coords..., particles.index) + return nothing end