op.update(kwargs) # --- Initialise mesh swp = AdaptiveProblem(op) # Refine around equator and/or soliton if initial_monitor is not None: mesh_mover = MeshMover(swp.meshes[0], initial_monitor, method='monge_ampere', op=op) mesh_mover.adapt() mesh = Mesh(mesh_mover.x) op.__init__(mesh=mesh, **kwargs) swp.__init__(op, meshes=[mesh]) # --- Monitor function definitions def elevation_norm_monitor(mesh, alpha=40.0, norm_type='H1', **kwargs): """ Monitor function derived from the elevation `norm_type` norm. :kwarg alpha: controls the amplitude of the monitor function. """ P1DG = FunctionSpace(mesh, "DG", 1) eta = project(swp.fwd_solutions[0].split()[1], P1DG) if norm_type == 'hessian_frobenius': H = recover_hessian(eta, op=op) return 1.0 + alpha * local_frobenius_norm(H)
# NOTE: We use Monge-Ampere with a monitor function indicating the initial condition alpha = 10.0 # Parameter controlling prominance of refined region eps = 1.0e-03 # Parameter controlling width of refined region def monitor(mesh): x, y = SpatialCoordinate(mesh) x0, y0, r = op.source_loc[0] return conditional(le(abs((x - x0)**2 + (y - y0)**2 - r**2), eps), alpha, 1.0) mesh_mover = MeshMover(tp.meshes[0], monitor, method='monge_ampere', op=op) mesh_mover.adapt() tp.__init__(op, meshes=[Mesh(mesh_mover.x)]) # --- Solve the tracer transport problem # Note: # * Pure Lagrangian leads to tangled elements after only a few iterations # * This motivates applying monitor based methods throughout the simulation tp.set_initial_condition() init_vol = assemble(Constant(1.0) * dx(domain=tp.mesh)) init_l1_norm = norm(tp.fwd_solutions_tracer[0], norm_type='L1') init_l2_norm = norm(tp.fwd_solutions_tracer[0], norm_type='L2') init_sol = tp.fwd_solutions_tracer[0].copy(deepcopy=True) tp.solve_forward() # Compare initial and final tracer concentrations