Skip to content

Commit 6be9e50

Browse files
jcgraciosaJuan Carlos Graciosa
andauthored
Some simple Navier-Stokes examples (#3)
* Added lid driven flow example with mesh manipulation option * Adding simpler Navier-Stokes examples * Added simple Navier-Stokes examples * Delete Notebooks/Examples-NavierStokes/Ex_NS_PipeFlow_Flow.py --------- Co-authored-by: Juan Carlos Graciosa <[email protected]>
1 parent ad9c62b commit 6be9e50

File tree

5 files changed

+1560
-0
lines changed

5 files changed

+1560
-0
lines changed
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# %% [markdown]
2+
# # Navier Stokes benchmark: Couette flow
3+
# By: Juan Carlos Graciosa
4+
#
5+
6+
# %%
7+
import os
8+
9+
import petsc4py
10+
import underworld3 as uw
11+
12+
import numpy as np
13+
import sympy
14+
import argparse
15+
import pickle
16+
17+
#parser = argparse.ArgumentParser()
18+
#parser.add_argument('-i', "--idx", type=int, required=True)
19+
#parser.add_argument('-p', "--prev", type=int, required=True) # set to 0 if no prev_res, 1 if there is
20+
#args = parser.parse_args()
21+
22+
#idx = args.idx
23+
#prev = args.prev
24+
25+
idx = 0
26+
prev = 0
27+
28+
# %%
29+
resolution = 16
30+
refinement = 0
31+
save_every = 200
32+
maxsteps = 1
33+
Cmax = 1 # target Courant number
34+
35+
order = 1 # solver order
36+
tol = 1e-12 # solver tolerance (sets atol and rtol)
37+
38+
mesh_type = "Pirr" # or Preg, Pirr, Quad
39+
qdeg = 3
40+
Vdeg = 3
41+
Pdeg = Vdeg - 1
42+
Pcont = False
43+
44+
# %%
45+
expt_name = f"Couette-res{resolution}-order{order}-{mesh_type}"
46+
47+
outfile = f"{expt_name}_run{idx}"
48+
outdir = f"./{expt_name}"
49+
50+
# %%
51+
if prev == 0:
52+
prev_idx = 0
53+
infile = None
54+
else:
55+
prev_idx = int(idx) - 1
56+
infile = f"{expt_name}_run{prev_idx}"
57+
58+
if uw.mpi.rank == 0 and uw.mpi.size > 1:
59+
os.makedirs(f"{outdir}", exist_ok=True)
60+
61+
# %%
62+
width = 4.
63+
height = 1.
64+
vel = 1.
65+
66+
fluid_rho = 1.
67+
kin_visc = 1.
68+
dyn_visc = fluid_rho * kin_visc
69+
70+
# %%
71+
minX, maxX = -0.5 * width, 0.5 * width
72+
minY, maxY = -0.5 * height, 0.5 * height
73+
74+
if uw.mpi.rank == 0:
75+
print("min X, max X:", minX, maxX)
76+
print("min Y, max Y:", minY, maxY)
77+
print("kinematic viscosity: ", kin_visc)
78+
print("fluid density: ", fluid_rho)
79+
print("dynamic viscosity: ", kin_visc * fluid_rho)
80+
81+
# %%
82+
# cell size calculation
83+
if mesh_type == "Preg":
84+
meshbox = uw.meshing.UnstructuredSimplexBox( minCoords=(minX, minY), maxCoords=(maxX, maxY), cellSize = 1 / resolution, qdegree = qdeg, regular = True)
85+
elif mesh_type == "Pirr":
86+
meshbox = uw.meshing.UnstructuredSimplexBox( minCoords=(minX, minY), maxCoords=(maxX, maxY), cellSize = 1 / resolution, qdegree = qdeg, regular = False)
87+
elif mesh_type == "Quad":
88+
meshbox = uw.meshing.StructuredQuadBox( minCoords=(minX, minY), maxCoords=(maxX, maxY), elementRes = (width * resolution, height * resolution), qdegree = qdeg, regular = False)
89+
90+
# %%
91+
meshbox.dm.view()
92+
93+
# %%
94+
v_soln = uw.discretisation.MeshVariable("U", meshbox, meshbox.dim, degree = Vdeg)
95+
p_soln = uw.discretisation.MeshVariable("P", meshbox, 1, degree = Pdeg, continuous = Pcont)
96+
97+
# %%
98+
if infile is None:
99+
pass
100+
else:
101+
if uw.mpi.rank == 0:
102+
print(f"Reading: {infile}")
103+
104+
v_soln.read_timestep(data_filename = infile, data_name = "U", index = maxsteps, outputPath = outdir)
105+
p_soln.read_timestep(data_filename = infile, data_name = "P", index = maxsteps, outputPath = outdir)
106+
107+
# %%
108+
# Set solve options here (or remove default values
109+
# stokes.petsc_options.getAll()
110+
111+
navier_stokes = uw.systems.NavierStokesSLCN(
112+
meshbox,
113+
velocityField = v_soln,
114+
pressureField = p_soln,
115+
rho = fluid_rho,
116+
verbose = False,
117+
order = order,
118+
)
119+
120+
navier_stokes.constitutive_model = uw.constitutive_models.ViscousFlowModel
121+
# Constant visc
122+
navier_stokes.constitutive_model.Parameters.viscosity = dyn_visc
123+
124+
navier_stokes.penalty = 0
125+
navier_stokes.bodyforce = sympy.Matrix([0, 0])
126+
127+
# Velocity boundary conditions
128+
navier_stokes.add_dirichlet_bc((vel, 0.0), "Top")
129+
navier_stokes.add_dirichlet_bc((0.0, 0.0), "Bottom")
130+
# left and right are open
131+
132+
navier_stokes.tolerance = tol
133+
134+
# %%
135+
# navier_stokes.petsc_options["snes_monitor"] = None
136+
# navier_stokes.petsc_options["snes_converged_reason"] = None
137+
# navier_stokes.petsc_options["snes_monitor_short"] = None
138+
# navier_stokes.petsc_options["ksp_monitor"] = None
139+
140+
# navier_stokes.petsc_options["snes_type"] = "newtonls"
141+
# navier_stokes.petsc_options["ksp_type"] = "fgmres"
142+
143+
# navier_stokes.petsc_options["snes_max_it"] = 50
144+
# navier_stokes.petsc_options["ksp_max_it"] = 50
145+
146+
navier_stokes.petsc_options["snes_monitor"] = None
147+
navier_stokes.petsc_options["ksp_monitor"] = None
148+
149+
navier_stokes.petsc_options["snes_type"] = "newtonls"
150+
navier_stokes.petsc_options["ksp_type"] = "fgmres"
151+
152+
navier_stokes.petsc_options.setValue("fieldsplit_velocity_pc_type", "mg")
153+
navier_stokes.petsc_options.setValue("fieldsplit_velocity_pc_mg_type", "kaskade")
154+
navier_stokes.petsc_options.setValue("fieldsplit_velocity_pc_mg_cycle_type", "w")
155+
156+
navier_stokes.petsc_options["fieldsplit_velocity_mg_coarse_pc_type"] = "svd"
157+
navier_stokes.petsc_options["fieldsplit_velocity_ksp_type"] = "fcg"
158+
navier_stokes.petsc_options["fieldsplit_velocity_mg_levels_ksp_type"] = "chebyshev"
159+
navier_stokes.petsc_options["fieldsplit_velocity_mg_levels_ksp_max_it"] = 5
160+
navier_stokes.petsc_options["fieldsplit_velocity_mg_levels_ksp_converged_maxits"] = None
161+
162+
# # gasm is super-fast ... but mg seems to be bulletproof
163+
# # gamg is toughest wrt viscosity
164+
165+
# navier_stokes.petsc_options.setValue("fieldsplit_pressure_pc_type", "gamg")
166+
# navier_stokes.petsc_options.setValue("fieldsplit_pressure_pc_mg_type", "additive")
167+
# navier_stokes.petsc_options.setValue("fieldsplit_pressure_pc_mg_cycle_type", "v")
168+
169+
# # # mg, multiplicative - very robust ... similar to gamg, additive
170+
171+
navier_stokes.petsc_options.setValue("fieldsplit_pressure_pc_type", "mg")
172+
navier_stokes.petsc_options.setValue("fieldsplit_pressure_pc_mg_type", "multiplicative")
173+
navier_stokes.petsc_options.setValue("fieldsplit_pressure_pc_mg_cycle_type", "v")
174+
175+
# %%
176+
# set the timestep
177+
# for now, set it to be constant
178+
delta_x = meshbox.get_min_radius()
179+
max_vel = vel
180+
181+
delta_t = Cmax*delta_x/max_vel
182+
183+
if uw.mpi.rank == 0:
184+
print(f"Min radius: {delta_x}")
185+
print("Timestep used:", delta_t)
186+
187+
# %%
188+
ts = 0
189+
timeVal = np.zeros(maxsteps + 1) * np.nan # time values
190+
elapsed_time = 0.0
191+
192+
# %%
193+
for step in range(0, maxsteps):
194+
195+
if uw.mpi.rank == 0:
196+
print(f"Timestep: {step}")
197+
198+
navier_stokes.solve(timestep = delta_t, zero_init_guess=True)
199+
200+
elapsed_time += delta_t
201+
timeVal[step] = elapsed_time
202+
203+
if uw.mpi.rank == 0:
204+
print("Timestep {}, t {}, dt {}".format(ts, elapsed_time, delta_t))
205+
206+
if ts % save_every == 0 and ts > 0:
207+
meshbox.write_timestep(
208+
outfile,
209+
meshUpdates=True,
210+
meshVars=[p_soln, v_soln],
211+
outputPath=outdir,
212+
index =ts,
213+
)
214+
215+
with open(outdir + f"/{outfile}.pkl", "wb") as f:
216+
pickle.dump([timeVal], f)
217+
218+
# update timestep
219+
ts += 1
220+
221+
# save after all iterations
222+
meshbox.write_timestep(
223+
outfile,
224+
meshUpdates=True,
225+
meshVars=[p_soln, v_soln],
226+
outputPath=outdir,
227+
index =maxsteps,
228+
)
229+
230+
with open(outdir + f"/{outfile}.pkl", "wb") as f:
231+
pickle.dump([timeVal], f)
232+
233+

0 commit comments

Comments
 (0)