Example #1
0
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)
Example #2
0
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
Example #4
0
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,
    )
Example #5
0
    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)}"
)