import firedrake_ts from firedrake import * mesh = UnitIntervalMesh(10) V = FunctionSpace(mesh, "P", 1) u = Function(V) u_t = Function(V) v = TestFunction(V) F = inner(u_t, v) * dx + inner(grad(u), grad(v)) * dx - 1.0 * v * dx bc = DirichletBC(V, 0.0, "on_boundary") x = SpatialCoordinate(mesh) # gaussian = exp(-30*(x[0]-0.5)**2) bump = conditional(lt(abs(x[0] - 0.5), 0.1), 1.0, 0.0) u.interpolate(bump) problem = firedrake_ts.DAEProblem(F, u, u_t, (0.0, 1.0), bcs=bc) solver = firedrake_ts.DAESolver(problem) solver.solve() print(solver.ts.getTime()) # solver.ts.view() print(u.dat.data)
def HamiltonJacobiCGSolver( V: fd.FunctionSpace, theta: fd.Function, phi: fd.Function, t_end: float = 5000.0, bcs: Union[fd.DirichletBC, List[fd.DirichletBC]] = None, monitor: Callable = None, solver_parameters=None, pre_jacobian_callback=None, post_jacobian_callback=None, pre_function_callback=None, post_function_callback=None, ) -> fdts.DAESolver: """Builds the solver for the advection-diffusion equation (Hamilton-Jacobi in the context of topology optimization) which is used to advect the level set) Args: V (fd.FunctionSpace): Function space of the level set theta (fd.Function): Velocity function phi (fd.Function): Level set t_end (float, optional): Max time of simulation. Defaults to 5000.0. bcs (Union[fd.DirichletBC, List[fd.DirichletBC]], optional): BC for the equation. Defaults to None. monitor (Callable, optional): Monitor function called each time step. Defaults to None. solver_parameters ([type], optional): Solver options. Defaults to None. :kwarg pre_jacobian_callback: A user-defined function that will be called immediately before Jacobian assembly. This can be used, for example, to update a coefficient function that has a complicated dependence on the unknown solution. :kwarg pre_function_callback: As above, but called immediately before residual assembly. :kwarg post_jacobian_callback: As above, but called after the Jacobian has been assembled. :kwarg post_function_callback: As above, but called immediately after residual assembly. Returns: fdts.DAESolver: DAESolver configured to solve the advection-diffusion equation """ default_peclet_inv = 1e-4 if solver_parameters: PeInv = solver_parameters.get("peclet_number", default_peclet_inv) else: PeInv = default_peclet_inv phi_t = fd.Function(V) # Galerkin residual F = AdvectionDiffusionGLS(V, theta, phi, PeInv=PeInv, phi_t=phi_t) problem = fdts.DAEProblem(F, phi, phi_t, (0.0, t_end), bcs=bcs) parameters = { "ts_type": "rosw", "ts_rows_type": "2m", "ts_adapt_type": "dsp", "ts_exact_final_time": "matchstep", "ts_atol": 1e-7, "ts_rtol": 1e-7, "ksp_type": "preonly", "pc_type": "lu", "pc_factor_mat_solver_type": "mumps", } if solver_parameters: parameters.update(solver_parameters) return fdts.DAESolver( problem, solver_parameters=parameters, monitor_callback=monitor, pre_function_callback=pre_function_callback, post_function_callback=post_function_callback, pre_jacobian_callback=pre_jacobian_callback, post_jacobian_callback=post_jacobian_callback, )
F = fd.action(M, u_dot) - R bc = fd.DirichletBC(V, (0.0, 0.0), "on_boundary") t = 0.0 end = 0.1 tspan = (t, end) state_out = fd.File("result/state.pvd") def ts_monitor(ts, steps, time, X): state_out.write(u, time=time) problem = firedrake_ts.DAEProblem(F, u, u_dot, tspan, bcs=bc) solver = firedrake_ts.DAESolver(problem, monitor_callback=ts_monitor) ts = solver.ts ts.setTimeStep(0.01) ts.setExactFinalTime(PETSc.TS.ExactFinalTime.MATCHSTEP) ts.setSaveTrajectory() ts.setType(PETSc.TS.Type.THETA) ts.setTheta(0.99) # adjoint for 1.0 (backward Euler) is currently broken in PETSc solver.solve() J = fd.inner(u, u) * fd.dx # dJ/du at final time
"pc_fieldsplit_type": "schur", "pc_fieldsplit_schur_factorization_type": "lower", "pc_fieldsplit_schur_precondition": "user", "fieldsplit_0_ksp_type": inner_ksp, "fieldsplit_0_ksp_max_it": maxit, "fieldsplit_0_pc_type": "hypre", "fieldsplit_1_ksp_type": inner_ksp, "fieldsplit_1_ksp_max_it": maxit, "fieldsplit_1_pc_type": "mat", } params["snes_monitor"] = None params["ts_monitor"] = None params["ts_view"] = None problem = firedrake_ts.DAEProblem(F, u, u_t, (0.0, 50 * dt)) solver = firedrake_ts.DAESolver(problem, solver_parameters=params) if pc in ["fieldsplit", "ilu"]: sigma = 100 # PC for the Schur complement solve trial = TrialFunction(V) test = TestFunction(V) mass = assemble(inner(trial, test) * dx).M.handle a = 1 c = (dt * lmbda) / (1 + dt * sigma) hats = assemble( sqrt(a) * inner(trial, test) * dx + sqrt(c) * inner(grad(trial), grad(test)) * dx).M.handle from firedrake.petsc import PETSc
PETSc.Sys.Print(f"Problem is set up!") if save_solution: output_file = fd.File("res3/output.pvd") def monitor(ts, steps, time, X): phi, T = w.split() # PETSc.Sys.Print(f'Iteration #{steps}. Current time: {float(time)}, and solution norm is {fd.norm(w)}') if save_solution: output_file.write(phi, T, time=time) problem = firedrake_ts.DAEProblem(F, w, wdot, (0.0, 1500), bcs=bcs) solver = firedrake_ts.DAESolver(problem, monitor_callback=monitor) solver.ts.setMaxSNESFailures( -1 ) # allow an unlimited number of failures (step will be rejected and retried) snes = solver.ts.getSNES() # Nonlinear solver snes.setTolerances( max_it=10 ) # Stop nonlinear solve after 10 iterations (TS will retry with shorter step) # Ensure everything is reset x = fd.SpatialCoordinate(mesh) w_init = create_initial_conditions(x, undercooling) for i in range(len(w_init)):
I2s.append(assemble(I2)) I3s.append(assemble(I3)) print(f"Time: {time} | I1: {I1s[-1]} | I2: {I2s[-1]} | I3: {I3s[-1]}") params = { "mat_type": "aij", "ksp_type": "preonly", "pc_type": "lu", "ts_type": "theta", "ts_theta_theta": 0.5, # implicit midpoint method | the Gauss–Legendre method of order two "ts_exact_final_time": "matchstep", } problem = firedrake_ts.DAEProblem(F, u, u_t, (0.0, 18.0)) solver = firedrake_ts.DAESolver(problem, solver_parameters=params, monitor_callback=ts_monitor) ts = solver.ts ts.setTimeStep(dt) solver.solve() # Update t constant so that uexact is updated t.assign(ts.getTime()) print( f"errornorm(uexact, u) / norm(uexact): {errornorm(uexact, u) / norm(uexact)}" )
w, wt = split(zt) rho = Constant(1.0) F1 = inner(w, q) * dx - inner(ut, q) * dx F2 = rho * inner(wt, v) * dx + inner(sigma(u), eps(v)) * dx - dot( as_vector([0, 1e-2 * cos(t)]), v) * ds(2) F = F1 + F2 outfile = File("output/elastodyn.pvd") outfile.write(project(u, V, name="Disp"), time=0.0) params = {"ts_type": "alpha"} params["ts_adapt_type"] = "basic" params["ts_adapt_monitor"] = None def ts_monitor(ts, steps, time, X): print(time) outfile.write(project(u, V, name="Disp"), time=time) bc = DirichletBC(W.sub(0), Constant((0, 0)), 1) problem = firedrake_ts.DAEProblem(F, z, zt, (0.0, 5), time=t, bcs=bc) solver = firedrake_ts.DAESolver(problem, monitor_callback=ts_monitor, solver_parameters=params) timestep = 1.0 / (n) ts = solver.ts ts.setTimeStep(timestep) solver.solve()
v = TestFunction(V) x = SpatialCoordinate(mesh) ic = project(as_vector([sin(pi * x[0]), 0]), V) u.assign(ic) nu = 0.0001 F = ( inner(u_t, v) + inner(dot(u, nabla_grad(u)), v) + nu * inner(grad(u), grad(v)) ) * dx outfile = File("burgers.pvd") outfile.write(project(u, V_out, name="Velocity"), time=0.0) def ts_monitor(ts, steps, time, X): outfile.write(project(u, V_out, name="Velocity"), time=time) problem = firedrake_ts.DAEProblem(F, u, u_t, (0.0, 0.5)) solver = firedrake_ts.DAESolver(problem, monitor_callback=ts_monitor) timestep = 1.0 / n ts = solver.ts ts.setTimeStep(timestep) solver.solve()