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)
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 dJdu = fd.assemble(fd.derivative(J, u))
"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
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, )
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)}" )