# define coupling domain as complete domain def coupling(x): return True dim = 2 coupling_domain = AutoSubDomain(coupling) # the FEniCS-preCICE adapter is configured via a json file. In there, we also need to specify some arbitrary (unused) read data. # We are currently trying to get rid of this technical restriction. precice = Adapter(adapter_config_filename="precice-adapter-config.json") precice_dt = precice.initialize( coupling_domain, write_object=V) # here we define where the coupling should happen # Define boundary condition on left and right boundary u0 = Constant(0.0) bc = DirichletBC(V, u0, boundary) # Define variational problem, simply copied from FEniCS demo u = TrialFunction(V) v = TestFunction(V) f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)", degree=2) g = Expression("sin(5*x[0])", degree=2) a = inner(grad(u), grad(v)) * dx L = f * v * dx + g * v * ds
beta=beta, gamma=gamma, t=0) u_D_function = interpolate(u_D, V) # Define flux in x direction on coupling interface (grad(u_D) in normal direction) f_N = Expression(("2 * gamma*t*x[0] + 2 * (1-gamma)*x[0]", "2 * alpha*x[1]"), degree=1, gamma=gamma, alpha=alpha, t=0) f_N_function = interpolate(f_N, V_g) # Define initial value u_n = interpolate(u_D, V) u_n.rename("Temperature", "") precice, precice_dt, initial_data = None, 0.0, None # Initialize the adapter according to the specific participant if problem is ProblemType.DIRICHLET: precice = Adapter(adapter_config_filename="precice-adapter-config-D.json") precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=f_N_function) elif problem is ProblemType.NEUMANN: precice = Adapter(adapter_config_filename="precice-adapter-config-N.json") precice_dt = precice.initialize(coupling_boundary, read_function_space=V_g, write_object=u_D_function) boundary_marker = False dt = Constant(0) dt.assign(np.min([fenics_dt, precice_dt])) # Define variational problem u = TrialFunction(V) v = TestFunction(V) f = Expression('beta + gamma*x[0]*x[0] - 2*gamma*t - 2*(1-gamma) - 2*alpha', degree=2, alpha=alpha, beta=beta, gamma=gamma, t=0) F = u * v / dt * dx + dot(grad(u), grad(v)) * dx - (u_n / dt + f) * v * dx
u_D_function = interpolate(u_D, V) # We will only exchange flux in y direction on coupling interface. No initialization necessary. V_flux_y = V_g.sub(1) coupling_boundary = TopBoundary() bottom_boundary = BottomBoundary() # Define initial value u_n = interpolate(u_D, V) u_n.rename("T", "") # Adapter definition and initialization precice = Adapter(adapter_config_filename="precice-adapter-config.json") precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=V_flux_y) # Create a FEniCS Expression to define and control the coupling boundary values coupling_expression = precice.create_coupling_expression() # Assigning appropriate dt dt = Constant(0) dt.assign(np.min([fenics_dt, precice_dt])) # Define variational problem u = TrialFunction(V) v = TestFunction(V) F = u * v / dt * dx + alpha * dot(grad(u), grad(v)) * dx - u_n * v / dt * dx # apply constant Dirichlet boundary condition at bottom edge
u = TrialFunction(V) v = TestFunction(V) u_n = Function(V) if args.source: u_ini = Expression("1", degree=1) bc = DirichletBC(V, u_ini, AllBoundary()) elif args.drain: u_ini = Expression("0", degree=1) bc = DirichletBC(V, u_ini, RightBoundary()) u_n = interpolate(u_ini, V) dt = precice.initialize(AllDomain(), read_function_space=V, write_object=u_n) volume_term = precice.create_coupling_expression() f = Function(V) dt_inv = Constant(1 / dt) diffusion_source = 1 diffusion_drain = 1 if args.source: F = dt_inv * (u - u_n) * v * dx - (f - u_ini) * v * dx + diffusion_source * inner(grad(u), grad(v)) * dx elif args.drain: F = dt_inv * (u - u_n) * v * dx - (f - u) * v * dx + diffusion_drain * inner(grad(u), grad(v)) * dx # Time-stepping u_np1 = Function(V)
f_N_function = interpolate(Expression(("1", "0"), degree=1), V) u_function = interpolate(Expression(("0", "0"), degree=1), V) # define coupling boundary coupling_boundary = AutoSubDomain(remaining_boundary) # create Adapter precice = Adapter(adapter_config_filename="precice-adapter-config-fsi-s.json") # create subdomains used by the adapter clamped_boundary_domain = AutoSubDomain(left_boundary) force_boundary = AutoSubDomain(remaining_boundary) # Initialize the coupling interface # Function space V is passed twice as both read and write functions are defined using the same space precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=V, fixed_boundary=clamped_boundary_domain) fenics_dt = precice_dt # if fenics_dt == precice_dt, no subcycling is applied # fenics_dt = 0.02 # if fenics_dt < precice_dt, subcycling is applied dt = Constant(np.min([precice_dt, fenics_dt])) # generalized alpha method (time stepping) parameters alpha_m = Constant(0.2) alpha_f = Constant(0.4) gamma = Constant(0.5 + alpha_f - alpha_m) beta = Constant((gamma + 0.5) ** 2 * 0.25) # clamp (u == 0) the beam at the left bc = DirichletBC(V, Constant((0, 0)), left_boundary)