# Compute solution u^n+1, use bcs u_D^n+1, u^n and coupling bcs solve(a == L, u_np1, bcs) # Write data to preCICE according to which problem is being solved if problem is ProblemType.DIRICHLET: # Dirichlet problem reads temperature and writes flux on boundary to Neumann problem determine_gradient(V_g, u_np1, flux) precice.write_data(flux) elif problem is ProblemType.NEUMANN: # Neumann problem reads flux and writes temperature on boundary to Dirichlet problem precice.write_data(u_np1) precice_dt = precice.advance(dt(0)) if precice.is_action_required(precice.action_read_iteration_checkpoint()): # roll back to checkpoint u_cp, t_cp, n_cp = precice.retrieve_checkpoint() u_n.assign(u_cp) t = t_cp n = n_cp else: # update solution u_n.assign(u_np1) t += float(dt) n += 1 if precice.is_time_window_complete(): u_ref = interpolate(u_D, V) u_ref.rename("reference", " ") error, error_pointwise = compute_errors(u_n, u_ref, V, total_error_tol=error_tol) print('n = %d, t = %.2f: L2 error on domain = %.3g' % (n, t, error)) # output solution and reference solution at t_n+1
# Update the coupling expression with the new read data precice.update_coupling_expression(coupling_expression, read_data) dt.assign(np.min([fenics_dt, precice_dt])) # Compute solution solve(a == L, u_np1, bcs) # Dirichlet problem obtains flux from solution and sends flux on boundary to Neumann problem determine_heat_flux(V_g, u_np1, k, fluxes) fluxes_y = fluxes.sub(1) # only exchange y component of flux. precice.write_data(fluxes_y) precice_dt = precice.advance(dt(0)) if precice.is_action_required(precice.action_read_iteration_checkpoint() ): # roll back to checkpoint u_cp, t_cp, n_cp = precice.retrieve_checkpoint() u_n.assign(u_cp) t = t_cp n = n_cp else: # update solution u_n.assign(u_np1) t += float(dt) n += 1 if precice.is_time_window_complete(): tol = 10e-5 # we need some tolerance, since otherwise output might be skipped. if abs((t + tol) % dt_out) < 2 * tol: # output if t is a multiple of dt_out print("output vtk for time = {}".format(float(t)))