def test_unsteady_stokes(): nx, ny = 15, 15 k = 1 nu = Constant(1.0e-0) dt = Constant(2.5e-2) num_steps = 20 theta0 = 1.0 # Initial theta value theta1 = 0.5 # Theta after 1 step theta = Constant(theta0) mesh = UnitSquareMesh(nx, ny) # The 'unsteady version' of the benchmark in the 2012 paper by Labeur&Wells u_exact = Expression( ( "sin(t) * x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \ -6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])", "-sin(t)* x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \ - 6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])", ), t=0, degree=7, domain=mesh, ) p_exact = Expression("sin(t) * x[0]*(1.0 - x[0])", t=0, degree=7, domain=mesh) du_exact = Expression( ( "cos(t) * x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \ - 6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])", "-cos(t)* x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \ -6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])", ), t=0, degree=7, domain=mesh, ) ux_exact = Expression( ( "x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \ - 6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])", "-x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \ - 6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])", ), degree=7, domain=mesh, ) px_exact = Expression("x[0]*(1.0 - x[0])", degree=7, domain=mesh) sin_ext = Expression("sin(t)", t=0, degree=7, domain=mesh) f = du_exact + sin_ext * div(px_exact * Identity(2) - 2 * sym(grad(ux_exact))) Vhigh = VectorFunctionSpace(mesh, "DG", 7) Phigh = FunctionSpace(mesh, "DG", 7) # New syntax: V = VectorElement("DG", mesh.ufl_cell(), k) Q = FiniteElement("DG", mesh.ufl_cell(), k - 1) Vbar = VectorElement("DGT", mesh.ufl_cell(), k) Qbar = FiniteElement("DGT", mesh.ufl_cell(), k) mixedL = FunctionSpace(mesh, MixedElement([V, Q])) mixedG = FunctionSpace(mesh, MixedElement([Vbar, Qbar])) V2 = FunctionSpace(mesh, V) Uh = Function(mixedL) Uhbar = Function(mixedG) U0 = Function(mixedL) Uhbar0 = Function(mixedG) u0, p0 = split(U0) ubar0, pbar0 = split(Uhbar0) ustar = Function(V2) # Then the boundary conditions bc0 = DirichletBC(mixedG.sub(0), Constant((0, 0)), Gamma) bc1 = DirichletBC(mixedG.sub(1), Constant(0), Corner, "pointwise") bcs = [bc0, bc1] alpha = Constant(6 * k * k) forms_stokes = FormsStokes(mesh, mixedL, mixedG, alpha).forms_unsteady(ustar, dt, nu, f) ssc = StokesStaticCondensation( mesh, forms_stokes["A_S"], forms_stokes["G_S"], forms_stokes["G_ST"], forms_stokes["B_S"], forms_stokes["Q_S"], forms_stokes["S_S"], ) t = 0.0 step = 0 for step in range(num_steps): step += 1 t += float(dt) if comm.Get_rank() == 0: print("Step " + str(step) + " Time " + str(t)) # Set time level in exact solution u_exact.t = t p_exact.t = t du_exact.t = t - (1 - float(theta)) * float(dt) sin_ext.t = t - (1 - float(theta)) * float(dt) ssc.assemble_global_lhs() ssc.assemble_global_rhs() for bc in bcs: ssc.apply_boundary(bc) ssc.solve_problem(Uhbar, Uh, "none", "default") assign(U0, Uh) assign(ustar, U0.sub(0)) assign(Uhbar0, Uhbar) if step == 1: theta.assign(theta1) udiv_e = sqrt(assemble(div(Uh.sub(0)) * div(Uh.sub(0)) * dx)) u_ex_h = interpolate(u_exact, Vhigh) p_ex_h = interpolate(p_exact, Phigh) u_error = sqrt(assemble(dot(Uh.sub(0) - u_ex_h, Uh.sub(0) - u_ex_h) * dx)) p_error = sqrt(assemble(dot(Uh.sub(1) - p_ex_h, Uh.sub(1) - p_ex_h) * dx)) assert udiv_e < 1e-12 assert u_error < 1.5e-4 assert p_error < 1e-2
def test_steady_stokes(k): # Polynomial order and mesh resolution nx_list = [4, 8, 16] nu = Constant(1) if comm.Get_rank() == 0: print('{:=^72}'.format('Computing for polynomial order ' + str(k))) # Error listst error_u, error_p, error_div = [], [], [] for nx in nx_list: if comm.Get_rank() == 0: print('# Resolution ' + str(nx)) mesh = UnitSquareMesh(nx, nx) # Get forcing from exact solutions u_exact, p_exact = exact_solution(mesh) f = div(p_exact * Identity(2) - 2 * nu * sym(grad(u_exact))) # Define FunctionSpaces and functions V = VectorElement("DG", mesh.ufl_cell(), k) Q = FiniteElement("DG", mesh.ufl_cell(), k - 1) Vbar = VectorElement("DGT", mesh.ufl_cell(), k) Qbar = FiniteElement("DGT", mesh.ufl_cell(), k) mixedL = FunctionSpace(mesh, MixedElement([V, Q])) mixedG = FunctionSpace(mesh, MixedElement([Vbar, Qbar])) Uh = Function(mixedL) Uhbar = Function(mixedG) # Set forms alpha = Constant(6 * k * k) forms_stokes = FormsStokes(mesh, mixedL, mixedG, alpha).forms_steady(nu, f) # No-slip boundary conditions, set pressure in one of the corners bc0 = DirichletBC(mixedG.sub(0), Constant((0, 0)), Gamma) bc1 = DirichletBC(mixedG.sub(1), Constant(0), Corner, "pointwise") bcs = [bc0, bc1] # Initialize static condensation class ssc = StokesStaticCondensation(mesh, forms_stokes['A_S'], forms_stokes['G_S'], forms_stokes['B_S'], forms_stokes['Q_S'], forms_stokes['S_S'], bcs) # Assemble global system and incorporates bcs ssc.assemble_global_system(True) # Solve using mumps ssc.solve_problem(Uhbar, Uh, "mumps", "default") # Compute velocity/pressure/local div error uh, ph = Uh.split() e_u = np.sqrt(np.abs(assemble(dot(uh - u_exact, uh - u_exact) * dx))) e_p = np.sqrt(np.abs(assemble((ph - p_exact) * (ph - p_exact) * dx))) e_d = np.sqrt(np.abs(assemble(div(uh) * div(uh) * dx))) if comm.rank == 0: error_u.append(e_u) error_p.append(e_p) error_div.append(e_d) print('Error in velocity ' + str(error_u[-1])) print('Error in pressure ' + str(error_p[-1])) print('Local mass error ' + str(error_div[-1])) if comm.rank == 0: iterator_list = [1. / float(nx) for nx in nx_list] conv_u = compute_convergence(iterator_list, error_u) conv_p = compute_convergence(iterator_list, error_p) assert any(conv > k + 0.75 for conv in conv_u) assert any(conv > (k - 1) + 0.75 for conv in conv_p)
with open(conservation_data, "a") as write_file: data = [ t, total_mass, mass_change_flux, mass_change_noflux, mt_change, mt_change_noflux, rho_min, rho_max ] writer = csv.writer(write_file) writer.writerow(['{:10.7g}'.format(val) for val in data]) del (t1) # Solve Stokes t1 = Timer("[P] Stokes assemble ") ssc.assemble_global() del (t1) t1 = Timer("[P] Stokes solve ") ssc.solve_problem(Uhbar, Uh, solver, "default") del (t1) t1 = Timer("[P] Update mesh fields") # Needed for particle advection assign(Udiv, Uh.sub(0)) assign(rho0, rho) # Needed for constrained map if projection_type == 'PDE': assign(ubar0_a, Uhbar.sub(0)) assign(u0, ustar) assign(duh00, duh0) assign(duh0, project(Uh.sub(0) - ustar, W_2)) del (t1)
def output_data_step(append=False): urms = (1.0 / (lmbdax*lmbdaz) * assemble(dot(u_vec, u_vec) * dx)) ** 0.5 conservation = abs(assemble(phi * dx) - conservation0) entrainment = assemble(1.0 / (lmbdax * lmbdaz * Constant(db)) * phi * dx(de)) output_functionals(data_filename, [float(t), float(dt), urms, conservation, entrainment], append=append) # Initial Stokes solve time = Timer("ZZZ Stokes assemble") ssc.assemble_global_system(True) del time time = Timer("ZZZ Stokes solve") for bc in bcs: ssc.apply_boundary(bc) ssc.solve_problem(Uhbar.cpp_object(), Uh.cpp_object(), "mumps", "default") del time # Transfer the computed velocity function and compute functionals velocity_assigner.assign(u_vec, Uh.sub(0)) output_data_step(append=False) time_snap_shot_interval = 5.0 next_snap_shot_time = time_snap_shot_interval for j in range(50000): max_u_vec = u_vec.vector().norm("linf") dt.assign(C_CFL * hmin / max_u_vec) t.assign(float(t) + float(dt)) if float(t) > 2000.0:
try: pde_u.solve_problem(ustar_bar, ustar, "mumps", "default") except Exception: # FIXME: work-around lstsq_u.project(ustar) del (t1) # Solve Stokes t1 = Timer("[P] Stokes assemble ") ssc.assemble_global() for bc in bcs: ssc.apply_boundary(bc) del (t1) t1 = Timer("[P] Stokes solve ") ssc.solve_problem(Uhbar, Uh, "mumps", "default") del (t1) t1 = Timer("[P] Update mesh fields") # Needed for particle advection assign(Udiv, Uh.sub(0)) # Needed for constrained map assign(rho0, rho) assign(ubar0_a, Uhbar.sub(0)) assign(u0, ustar) assign(duh00, duh0) assign(duh0, project(Uh.sub(0) - ustar, W_2)) del (t1) t1 = Timer("[P] Update particle field")
t1 = Timer("[P] assemble projection") pde_projection.assemble(True, True) del t1 t1 = Timer("[P] solve projection") pde_projection.solve_problem(ubar_a.cpp_object(), ustar.cpp_object(), lamb.cpp_object(), "mumps", "default") del t1 # Solve Stokes t1 = Timer("[P] Stokes assemble ") ssc.assemble_global_system(True) for bc in bcs: ssc.apply_boundary(bc) del t1 t1 = Timer("[P] Stokes solve") ssc.solve_problem(Uhbar.cpp_object(), Uh.cpp_object(), "mumps", "none") del t1 # Needed for particle advection assign(Udiv, Uh.sub(0)) # Needed for constrained map assign(ubar0_a, Uhbar.sub(0)) assign(u0_a, ustar) assign(duh00, duh0) assign(duh0, project(Uh.sub(0) - ustar, W_2)) p.increment(Udiv.cpp_object(), ustar.cpp_object(), np.array([1, 2], dtype=np.uintp), theta_p, step) if step == 2: