-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.jl
276 lines (225 loc) · 9.27 KB
/
main.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
using Printf
# Logging in terminal and file
# https://julialogging.github.io/how-to/tee/#Send-messages-to-multiple-locations
using Logging, LoggingExtras
# Include all modules that is used in main.jl and in imported modules
include("./SimpleLA.jl")
include("./Strains.jl");
include("./EquationsOfState.jl")
# include("./Hyperelasticity.jl")
include("./HyperelasticityMPh.jl")
include("./NumFluxes.jl")
# Только то, что нужно в main.jl
using .EquationsOfState: EoS, Barton2009
# using .Hyperelasticity: prim2cons, cons2prim, initial_states, postproc_arrays
using .HyperelasticityMPh: initial_states, cons2prim_mph, prim2cons_mph, get_eigvals#, postproc_arrays
using .NumFluxes: lxf, hll
"""
update_cell(Q::Array{<:Any,2}, flux_num::Function, lambda, eos::T) where {T <: EoS}
Returns the value of quantity in the cell to the next time layer using
`flux_num` numerical flux method and `eos` equation of state
`lambda` is the value of `Δx/Δt`
"""
# ### Old Lax-Friedrichs method
function update_cell(Q::Array{<:Any,2}, flux_num::Function, lambda, eos::Tuple{T,T}) where {T<:EoS}
Q_l, Q, Q_r = Q[:, 1], Q[:, 2], Q[:, 3]
# For onephase
# F_l = flux_num(eos, Q_l, Q, lambda)
# F_r = flux_num(eos, Q, Q_r, lambda)
# return Q - 1.0 / lambda * (F_r - F_l)
F_l, _, NF_l = flux_num(eos, Q_l, Q, lambda)
F_r, NF_r, _ = flux_num(eos, Q, Q_r, lambda)
return Q - 1.0 / lambda * ((F_r - F_l) + (NF_r + NF_l))
end
###
function update_cell(Q::Array{<:Any,2}, flux_num::Function, eigvals::Array{<:Any,1}, dtdx, eos::Tuple{T,T}) where {T<:EoS}
Q_l, Q, Q_r = Q[:, 1], Q[:, 2], Q[:, 3]
# # For Rusanov method
# lambda = maximum(abs.(eigvals))
# lambda = [maximum(abs.(eigvals[i])) for i in 1:length(eigvals)]
# lambda_l, lambda_r = max(lambda[1], lambda[2]), max(lambda[2], lambda[3])
# # For Lax-Friedrichs method
# lambda_l, lambda_r = 1 / dtdx, 1 / dtdx
#
# F_l, _, NF_l = flux_num(eos, Q_l, Q, lambda_l)
# F_r, NF_r, _ = flux_num(eos, Q, Q_r, lambda_r)
# For HLL method
F_l, _, NF_l = flux_num(eos, Q_l, Q, eigvals[1:2])
F_r, NF_r, _ = flux_num(eos, Q, Q_r, eigvals[2:3])
return Q - dtdx * ((F_r - F_l) + (NF_r + NF_l))
end
"""
save_data(fname::String, Q::Array{<:Any,2})
Save the solution array `Q` to a `fname` file.
"""
function save_data(fname::String, Q::Array{<:Any,2})
io = open(fname, "w")
# write(io, "$t\n")
nx = size(Q)[2]
write(io, "a1\tr1\tu11\tu21\tu31\tS1\tF111\tF211\tF311\tF121\tF221\tF321\tF131\tF231\tF331\ta2\tr2\tu12\tu22\tu32\tS2\tF112\tF212\tF312\tF122\tF222\tF322\tF132\tF232\tF332", "\n")
for i in 1:nx
P = cons2prim_mph(eos, Q[:, i])
write(io, join(P, "\t"), "\n")
end
close(io)
end
"""
read_data(fname::String)
Read the solution array from a `fname` file.
"""
function read_data(fname::String)
data = readlines(fname)
nx = length(data) - 1
P = Array{Float64}(undef, 30, nx)
for (indx, line) in enumerate(data[2:end])
P[:, indx] = parse.(Float64, split(line))
end
return P, nx
end
"""
initial_condition(Ql, Qr, nx)
Sets the initial condition with two states for the Riemann problem with `nx` cells.
"""
function initial_condition(Ql, Qr, nx)
# Эта функция ничего не знает про физику, но знает про сетку.
Q = Array{Float64}(undef, 30, nx)
for i in 1:nx
Q[:, i] = (i - 1) < nx / 2 ? Ql : Qr
end
return Q
end
get_filename(step_num) = @sprintf("sol_%06i.csv", step_num) # Padded with zeros
function initial_condition_tanh(eos, Ql, Qr, nx, eps)
Q = Array{Float64}(undef, 30, nx)
Pl = cons2prim_mph(eos, Ql)
Pr = cons2prim_mph(eos, Qr)
for i in 1:nx
x = (i - 0.5) / nx
P = x < 0.5 ? Pl : Pr
P[1] = 0.2 / 2 * (tanh(4 * (x - 0.5) / eps) + 1) + 0.4
P[16] = 1 - P[1]
Q[:, i] = prim2cons_mph(eos, P)
end
return Q
end
# ##############################################################################
# ### Main driver ##############################################################
# ##############################################################################
# Выносим сюда, в одно место, постепенно, все основные параметры расчета.
# Потом завернуть в структуру?
# Set equation of state for each phase
# eos = (Barton2009(), Barton2009(_rho0=8.93, _c0=6.22, _cv=9.0e-4, _t0=300, _b0=3.16, _alpha=1, _beta=3.577, _gamma=2.088))
eos = (Barton2009(), Barton2009())
testcase = 6 # Select the test case
log_freq = 100 # Log frequency
X = 1.0 # Coordinate boundary [m]
T = 0.06 # Time boundary [1e-5 s]
nx = 1000 # Number of steps on dimension coordinate
cfl = 0.6 # Courant-Friedrichs-Levy number
dt = 5 * 1e-6
dx = X / nx # Coordinate step
eps = 0.2
t = 0.0 # Initilization of time
step_num = 0 # Initilization of timestep counter
# ##############################################################################
# Logging settings
log_filename = "solution.log"
@info @sprintf("Starting log at: %s", log_filename)
logger = TeeLogger(
global_logger(), # Current global logger (stderr)
FileLogger(log_filename) # FileLogger writing to logfile.log
)
global_logger(logger) # Set logger as global logger
# Prepare the directory where data files will be saved
cd(@__DIR__)
dir_name = "barton_data/"
dir_name = mkpath(dir_name)
@info @sprintf("Data directory: %s", dir_name)
# Initialize initial conditions
if ("result.csv" in readdir(dir_name) || readdir(dir_name) == [])
foreach(rm, readdir(dir_name, join=true)) # Remove all files in the directory
@info @sprintf("Cleaning data directory: %s\n", dir_name)
Ql, Qr = initial_states(eos, testcase)
global Q0 = initial_condition(Ql, Qr, nx)
# Q0 = initial_condition_tanh(eos, Ql, Qr, nx, eps)
else
# Find the last file
last_file = sort(readdir(dir_name, join=true))[end]
@info @sprintf("Found file: %s\n", last_file)
global step_num = parse(Int, split(split(basename(last_file), ".")[1], "_")[2]) # Initilization of step counter
global t = step_num * dt
P0 = Array{Float64}(undef, 30, nx)
global Q0 = similar(P0)
P0, nx = read_data(last_file) # Read the last file
for i in 1:nx
Q0[:, i] = prim2cons_mph(eos, P0[:, i])
end
end
fname = joinpath(dir_name, get_filename(step_num))
save_data(fname, Q0)
@info @sprintf("Initial state saved to: %s\n", fname)
# ##############################################################################
# Timestepping
while t < T
# Computing the time step using CFL condition
lambda = Array{Float64}(undef, nx)
eigvals = Array{Array{Float64}}(undef, nx)
Threads.@threads for i = 1:nx
Q = Q0[:, i]
n = [1, 0, 0]
eigvals[i] = get_eigvals(eos, Q, n)
lambda[i] = maximum(abs.(eigvals[i]))
end
global dt = cfl * dx / maximum(lambda)
global t += dt # Updating the time
global step_num += 1 # Updating the step counter
# Computing the next time layer
Q1 = similar(Q0)
Q1[:, begin] = Q0[:, begin]
Q1[:, end] = Q0[:, end]
Threads.@threads for i in 2:nx-1
# Old LxF method call
# Q1[:, i] = update_cell(Q0[:, i-1:i+1], lxf, dx / dt, eos)
# Q1[:, i] = update_cell(Q0[:, i-1:i+1], lxf, eigvals[i-1:i+1], dx / dt, eos)
Q1[:, i] = update_cell(Q0[:, i-1:i+1], hll, eigvals[i-1:i+1], dt / dx, eos)
end
global Q0 = copy(Q1)
# Saving the solution array to a file
msg = @sprintf("Step = %d,\t t = %.6f / %.6f,\t Δt = %.6f\n",
step_num, t, T, dt)
if step_num % log_freq == 0
global fname = joinpath(dir_name, get_filename(step_num))
save_data(fname, Q0)
msg *= @sprintf("Solution saved to: %s\n", fname)
end
@info msg
end # while t < T
fname = joinpath(dir_name, "result.csv")
save_data(fname, Q0)
@info @sprintf("Result solution saved to: %s\n", fname)
# ##############################################################################
# ### Plotting #################################################################
# ##############################################################################
#
# Этот кусок ниже знает про сетку и про физику (по значениям переменных).
# Для разных моделей он разный.
# Проще всего включать сюда какой-нибудь файл, который специфичен для модели,
# видит весь контекст, не ограничивает область видимости. Пользователь
# делает в нем все, что хочет, под свою ответственность.
#
# Можно как то параметризовать модели (в каждом "физическом" модуле определить
# значение переменной model или тит или еще что, и сделать соответствующий
# switch/if/...) --- но смысла нет пока особо.
#
# Поэтому кусок ниже засовываем в файл с говорящим названием
# и включаем его "как есть".
# Стандартное название фиксируем ---
# [название модуля с физикой маленькими буквами]_postproc.jl.
#
# Сейчас это:
# hyperelasticity_postproc.jl
# hyperelasticitymph_postproc.jl
#
# include("hyperelasticitymph_postproc.jl")
@info @sprintf("Done!")
# EOF