assert (b is not b_forces) solve(A, u_np1.vector(), b_forces) dt = Constant(np.min([precice_dt, fenics_dt])) # Write new displacements to preCICE precice.write_data(u_np1) # Call to advance coupling, also returns the optimum time step value precice_dt = precice.advance(dt(0)) # Either revert to old step if timestep has not converged or move to next timestep 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: u_n.assign(u_np1) t += float(dt) n += 1 if precice.is_time_window_complete(): update_fields(u_np1, saved_u_old, v_n, a_n) if n % 10 == 0: displacement_out << (u_n, t) # Plot tip displacement evolution displacement_out << u_n
n = 0 print('output u^%d and u_ref^%d' % (n, n)) solution_out << u_n ranks << mesh_rank while precice.is_coupling_ongoing(): # write checkpoint if precice.is_action_required(precice.action_write_iteration_checkpoint()): precice.store_checkpoint(u_n, t, n) read_data = precice.read_data() # Update the coupling expression with the new read data precice.update_coupling_expression(volume_term, read_data) f.assign(interpolate(volume_term, V)) dt_inv.assign(1 / dt) # Compute solution u^n+1, use bcs u^n and coupling bcs a, L = lhs(F), rhs(F) solve(a == L, u_np1, bc) # Write data to preCICE according to which problem is being solved precice.write_data(u_np1) dt = precice.advance(dt) # roll back to checkpoint if precice.is_action_required(precice.action_read_iteration_checkpoint()): u_cp, t_cp, n_cp = precice.retrieve_checkpoint()
def step(*, time: float, dt: float, p_prev: Function, p: Function, a: Form, l: Form) -> Tuple[float, Function, Function]: time += dt solve(a == l, p) p_prev.assign(p) return time, p_prev, p
def relaxation( displacement_fluid: Initial, velocity_fluid: Initial, displacement_solid: Initial, velocity_solid: Initial, functional_fluid_initial, functional_solid_initial, bilinear_form_fluid, functional_fluid, bilinear_form_solid, functional_solid, first_time_step, fluid: Space, solid: Space, interface: Space, param: Parameters, fluid_macrotimestep: MacroTimeStep, solid_macrotimestep: MacroTimeStep, adjoint, ): # Define initial values for relaxation method displacement_solid_new = Function(solid.function_space_split[0]) velocity_displacement_new = Function(solid.function_space_split[1]) number_of_iterations = 0 stop = False while not stop: number_of_iterations += 1 print( f"Current iteration of relaxation method: {number_of_iterations}") # Save old values displacement_solid_new.assign(displacement_solid.new) velocity_displacement_new.assign(velocity_solid.new) # Perform one iteration solve_problem( displacement_fluid, velocity_fluid, displacement_solid, velocity_solid, fluid, solid, solid_to_fluid, functional_fluid_initial, bilinear_form_fluid, functional_fluid, first_time_step, param, fluid_macrotimestep, adjoint, ) solve_problem( displacement_solid, velocity_solid, displacement_fluid, velocity_fluid, solid, fluid, fluid_to_solid, functional_solid_initial, bilinear_form_solid, functional_solid, first_time_step, param, solid_macrotimestep, adjoint, ) # Perform relaxation displacement_solid.new.assign( project( param.TAU * displacement_solid.new + (1.0 - param.TAU) * displacement_solid_new, solid.function_space_split[0], )) velocity_solid.new.assign( project( param.TAU * velocity_solid.new + (1.0 - param.TAU) * velocity_displacement_new, solid.function_space_split[1], )) # Define errors on the interface displacement_error = interpolate( project( displacement_solid_new - displacement_solid.new, solid.function_space_split[0], ), interface.function_space_split[0], ) displacement_error_linf = norm(displacement_error.vector(), "linf") velocity_error = interpolate( project( velocity_displacement_new - velocity_solid.new, solid.function_space_split[1], ), interface.function_space_split[1], ) velocity_error_linf = norm(velocity_error.vector(), "linf") error_linf = max(displacement_error_linf, velocity_error_linf) if number_of_iterations == 1: error_initial_linf = error_linf print(f"Absolute error on the interface: {error_linf}") print( f"Relative error on the interface: {error_linf / error_initial_linf}" ) # Check stop conditions if (error_linf < param.ABSOLUTE_TOLERANCE_RELAXATION or error_linf / error_initial_linf < param.RELATIVE_TOLERANCE_RELAXATION): print(f"Algorithm converged successfully after " f"{number_of_iterations} iterations") stop = True elif number_of_iterations == param.MAX_ITERATIONS_RELAXATION: print("Maximal number of iterations was reached.") stop = True number_of_iterations = -1 displacement_fluid.iterations.append(number_of_iterations) velocity_fluid.iterations.append(number_of_iterations) displacement_solid.iterations.append(number_of_iterations) displacement_solid.iterations.append(number_of_iterations) return
def shooting_function( displacement_fluid: Initial, velocity_fluid: Initial, displacement_solid: Initial, velocity_solid: Initial, functional_fluid_initial, functional_solid_initial, bilinear_form_fluid, functional_fluid, bilinear_form_solid, functional_solid, first_time_step, fluid: Space, solid: Space, interface: Space, param: Parameters, fluid_macrotimestep: MacroTimeStep, solid_macrotimestep: MacroTimeStep, adjoint, ): # Save old values displacement_solid_new = Function(solid.function_space_split[0]) displacement_solid_new.assign(displacement_solid.new) velocity_solid_new = Function(solid.function_space_split[1]) velocity_solid_new.assign(velocity_solid.new) # Perform one iteration solve_problem( displacement_fluid, velocity_fluid, displacement_solid, velocity_solid, fluid, solid, solid_to_fluid, functional_fluid_initial, bilinear_form_fluid, functional_fluid, first_time_step, param, fluid_macrotimestep, adjoint, ) solve_problem( displacement_solid, velocity_solid, displacement_fluid, velocity_fluid, solid, fluid, fluid_to_solid, functional_solid_initial, bilinear_form_solid, functional_solid, first_time_step, param, solid_macrotimestep, adjoint, ) # Define shooting function shooting_function_1 = interpolate( project( displacement_solid_new - displacement_solid.new, solid.function_space_split[0], ), interface.function_space_split[0], ) shooting_function_2 = interpolate( project( velocity_solid_new - velocity_solid.new, solid.function_space_split[1], ), interface.function_space_split[1], ) # Represent shooting function as an array shooting_function_1_array = shooting_function_1.vector().get_local() shooting_function_2_array = shooting_function_2.vector().get_local() shooting_function_array = np.concatenate( (shooting_function_1_array, shooting_function_2_array), axis=None) return shooting_function_array
def shooting( displacement_fluid: Initial, velocity_fluid: Initial, displacement_solid: Initial, velocity_solid: Initial, functional_fluid_initial, functional_solid_initial, bilinear_form_fluid, functional_fluid, bilinear_form_solid, functional_solid, first_time_step, fluid: Space, solid: Space, interface: Space, param: Parameters, fluid_macrotimestep: MacroTimeStep, solid_macrotimestep: MacroTimeStep, adjoint, ): # Define initial values for Newton's method displacement_solid_new = Function(solid.function_space_split[0]) velocity_solid_new = Function(solid.function_space_split[1]) displacement_solid_new.assign(displacement_solid.old) velocity_solid_new.assign(velocity_solid.old) number_of_iterations = 0 number_of_linear_systems = 0 stop = False # Define Newton's method while not stop: number_of_iterations += 1 number_of_linear_systems += 1 print(f"Current iteration of Newton's method: {number_of_iterations}") # Define right hand side displacement_solid.new.assign(displacement_solid_new) velocity_solid.new.assign(velocity_solid_new) shooting_function_value = shooting_function( displacement_fluid, velocity_fluid, displacement_solid, velocity_solid, functional_fluid_initial, functional_solid_initial, bilinear_form_fluid, functional_fluid, bilinear_form_solid, functional_solid, first_time_step, fluid, solid, interface, param, fluid_macrotimestep, solid_macrotimestep, adjoint, ) shooting_function_value_linf = np.max(np.abs(shooting_function_value)) if number_of_iterations == 1: shooting_function_value_initial_linf = shooting_function_value_linf print(f"Absolute error on the interface: " f"{shooting_function_value_linf}") print( f"Relative error on the interface: " f"{shooting_function_value_linf / shooting_function_value_initial_linf}" ) # Define linear operator displacement_solid_interface = interpolate( displacement_solid_new, interface.function_space_split[0]) velocity_solid_interface = interpolate( velocity_solid_new, interface.function_space_split[1]) displacement_solid_interface_array = ( displacement_solid_interface.vector().get_local()) velocity_solid_interface_array = ( velocity_solid_interface.vector().get_local()) linear_operator_newton = shooting_newton( displacement_fluid, velocity_fluid, displacement_solid, velocity_solid, functional_fluid_initial, functional_solid_initial, bilinear_form_fluid, functional_fluid, bilinear_form_solid, functional_solid, first_time_step, fluid, solid, interface, param, fluid_macrotimestep, solid_macrotimestep, adjoint, displacement_solid_interface_array, velocity_solid_interface_array, shooting_function_value, ) shooting_gmres = LinearOperator( ( 2 * param.NUMBER_ELEMENTS_HORIZONTAL + 2, 2 * param.NUMBER_ELEMENTS_HORIZONTAL + 2, ), matvec=linear_operator_newton, ) # Solve linear system number_of_iterations_gmres = 0 def callback(vector): nonlocal number_of_iterations_gmres global residual_norm_gmres number_of_iterations_gmres += 1 print( f"Current iteration of GMRES method: {number_of_iterations_gmres}" ) residual_norm_gmres = np.linalg.norm(vector) direction, exit_code = gmres( shooting_gmres, -shooting_function_value, tol=param.TOLERANCE_GMRES, maxiter=param.MAX_ITERATIONS_GMRES, callback=callback, ) number_of_linear_systems += number_of_iterations_gmres if exit_code == 0: print(f"GMRES method converged successfully after " f"{number_of_iterations_gmres} iterations") else: print("GMRES method failed to converge.") print(f"Norm of residual: {residual_norm_gmres}") # Advance solution direction_split = np.split(direction, 2) displacement_solid_interface_array += direction_split[0] velocity_solid_interface_array += direction_split[1] displacement_solid_interface.vector().set_local( displacement_solid_interface_array) velocity_solid_interface.vector().set_local( velocity_solid_interface_array) displacement_solid_new.assign( interpolate(displacement_solid_interface, solid.function_space_split[0])) velocity_solid_new.assign( interpolate(velocity_solid_interface, solid.function_space_split[1])) # Check stop conditions if (shooting_function_value_linf < param.ABSOLUTE_TOLERANCE_NEWTON or shooting_function_value_linf / shooting_function_value_initial_linf < param.RELATIVE_TOLERANCE_NEWTON): print(f"Newton's method converged successfully after " f"{number_of_iterations} iterations and solving " f"{number_of_linear_systems} linear systems.") stop = True elif number_of_iterations == param.MAX_ITERATIONS_NEWTON: print("Newton's method failed to converge.") stop = True number_of_linear_systems = -1 displacement_fluid.iterations.append(number_of_linear_systems) velocity_fluid.iterations.append(number_of_linear_systems) displacement_solid.iterations.append(number_of_linear_systems) displacement_solid.iterations.append(number_of_linear_systems) return
def step(*, time: float, dt: float, t_prev: Function, t: Function, a: Form, l: Form, bc) -> Tuple[float, Function, Function]: time += dt solve(a == l, t, bc) t_prev.assign(t) return time, t_prev, t
def solid_problem(u_f, v_f, u_s, v_s, fluid, solid, param, save = False): # Store old solutions u_s_n_K = Function(solid.V_split[0]) v_s_n_K = Function(solid.V_split[1]) u_s_n_K.assign(u_s.old) v_s_n_K.assign(v_s.old) # Store old boundary values v_s_n_i_K = Function(solid.V_split[1]) v_s_n_i_K.assign(v_s.i_old) # Initialize interface values v_s_i = Function(solid.V_split[1]) # Define Dirichlet boundary conditions bc_u_s_0 = DirichletBC(solid.V.sub(0), Constant(0.0), boundary) bc_v_s_0 = DirichletBC(solid.V.sub(1), Constant(0.0), boundary) bcs_s = [bc_u_s_0, bc_v_s_0] # Compute fractional steps for solid problem for k in range(param.K): # Update boundary values v_s_i.assign(project((param.K - k - 1.0)/param.K*v_s.i_old + + (k + 1.0)/param.K*fluid_to_solid(v_f.new, fluid, solid, param, 1), solid.V_split[1])) # Define trial and test functions U_s_new = TrialFunction(solid.V) (u_s_new, v_s_new) = split(U_s_new) Phi_s = TestFunction(solid.V) (phi_s, psi_s) = split(Phi_s) # Define scheme A_s = (v_s_new*phi_s*solid.dx + u_s_new*psi_s*solid.dx + 0.5*param.dt/param.K*a_s(u_s_new, v_s_new, phi_s, psi_s, solid, param)) L_s = (v_s_n_K*phi_s*solid.dx + u_s_n_K*psi_s*solid.dx - 0.5*param.dt/param.K*a_s(u_s_n_K, v_s_n_K, phi_s, psi_s, solid, param) + 0.5*param.dt/param.K*param.nu*dot(grad(v_s_i), solid.n)*phi_s*solid.ds + 0.5*param.dt/param.K*param.nu*dot(grad(v_s_n_i_K), solid.n)*phi_s*solid.ds) # Solve solid problem U_s_new = Function(solid.V) solve(A_s == L_s, U_s_new, bcs_s) (u_s_new, v_s_new) = U_s_new.split(U_s_new) # Append solutions to the arrays if save: u_s.array.append(u_s_new.copy(deepcopy = True)) v_s.array.append(v_s_new.copy(deepcopy = True)) # Update solid solution u_s_n_K.assign(u_s_new) v_s_n_K.assign(v_s_new) # Update boundary condition v_s_n_i_K.assign(project(v_s_i, solid.V_split[1])) # Save final values u_s.new.assign(u_s_new) v_s.new.assign(v_s_new) v_s.i_new.assign(v_s_i) return
def fluid_problem(u_f, v_f, u_s, v_s, fluid, solid, param, t, save=False): # Store old solutions u_f_n_M = Function(fluid.V_split[0]) v_f_n_M = Function(fluid.V_split[1]) u_f_n_M.assign(u_f.old) v_f_n_M.assign(v_f.old) # Store old boundary values u_f_n_i_M = Function(fluid.V_split[0]) v_f_n_i_M = Function(fluid.V_split[1]) u_f_n_i_M.assign(u_f.i_old) v_f_n_i_M.assign(v_f.i_old) # Initialize interface values u_f_i = Function(fluid.V_split[0]) v_f_i = Function(fluid.V_split[1]) # Define Dirichlet boundary conditions bc_u_f_0 = DirichletBC(fluid.V.sub(0), Constant(0.0), boundary) bc_v_f_0 = DirichletBC(fluid.V.sub(1), Constant(0.0), boundary) bcs_f = [bc_u_f_0, bc_v_f_0] # Compute fractional steps for fluid problem for m in range(param.M): # Update boundary values u_f_i.assign( project((param.M - m - 1.0) / param.M * u_f.i_old + (m + 1.0) / param.M * solid_to_fluid(u_s.new, fluid, solid, param, 0), fluid.V_split[0])) v_f_i.assign( project((param.M - m - 1.0) / param.M * v_f.i_old + (m + 1.0) / param.M * solid_to_fluid(v_s.new, fluid, solid, param, 1), fluid.V_split[1])) # Define trial and test functions U_f_new = TrialFunction(fluid.V) (u_f_new, v_f_new) = split(U_f_new) Phi_f = TestFunction(fluid.V) (phi_f, psi_f) = split(Phi_f) # Define scheme A_f = (v_f_new * phi_f * fluid.dx + 0.5 * param.dt / param.M * a_f(u_f_new, v_f_new, phi_f, psi_f, fluid, param)) L_f = (v_f_n_M * phi_f * fluid.dx - 0.5 * param.dt / param.M * a_f(u_f_n_M, v_f_n_M, phi_f, psi_f, fluid, param) + 0.5 * param.dt / param.M * param.gamma / fluid.h * u_f_i * psi_f * fluid.ds + 0.5 * param.dt / param.M * param.gamma / fluid.h * v_f_i * phi_f * fluid.ds + 0.5 * param.dt / param.M * param.gamma / fluid.h * u_f_n_i_M * psi_f * fluid.ds + 0.5 * param.dt / param.M * param.gamma / fluid.h * v_f_n_i_M * phi_f * fluid.ds + param.dt / param.M * f(t) * phi_f * fluid.dx) # Solve fluid problem U_f_new = Function(fluid.V) solve(A_f == L_f, U_f_new, bcs_f) (u_f_new, v_f_new) = U_f_new.split(U_f_new) # Append solutions to the arrays if save: u_f.array.append(u_f_new.copy(deepcopy=True)) v_f.array.append(v_f_new.copy(deepcopy=True)) # Update fluid solution u_f_n_M.assign(u_f_new) v_f_n_M.assign(v_f_new) # Update boundary conditions u_f_n_i_M.assign(project(u_f_i, fluid.V_split[0])) v_f_n_i_M.assign(project(v_f_i, fluid.V_split[1])) # Save final values u_f.new.assign(u_f_new) v_f.new.assign(v_f_new) u_f.i_new.assign(u_f_i) v_f.i_new.assign(v_f_i) return
def compute_conv_diff_reac_video(self, initial_condition=None, video_ref=None, video_size=None): names = {'Cl', 'K'} P1 = FiniteElement('P', fe.triangle, 1) element = fe.MixedElement([P1, P1]) V_single = FunctionSpace(self.mesh, P1) V = FunctionSpace(self.mesh, element) self.V_conc = V # load video video = VideoData(element=P1) video.load_video(self.video_filename) if( video_ref is not None and video_size is not None): video.set_reference_frame(video_ref, video_size) print(video) dt = 0.05 t = 0. t_end = 20. u_init = Function(V) (u_cl, u_k) = TrialFunction(V) (v_cl, v_k) = TestFunction(V) #u_na = video if initial_condition is None: #initial_condition = Expression(("f*exp(-0.5*((x[0]-a)*(x[0]-a)+(x[1]-b)*(x[1]-b))/var)/(sqrt(2*pi)*var)", # "0."), a = 80, b= 55, var=10, f=10, pi=fe.pi, element=element) initial_condition = Expression(("f", "0."), a=80, b=55, var=0.1, f=0.1, pi=fe.pi, element=element) u_init = fe.interpolate(initial_condition, V) u_init_cl = u_init[0] u_init_k = u_init[1] u_init_na : VideoData= video assert (self.flow is not None) n = fe.FacetNormal(self.mesh) dx, ds = self.dx, self.ds flow = 5. * self.flow f_in = fe.Constant(0.00) f_in_cl = fe.Constant(-0.05) D = fe.Constant(0.1) C_na = fe.Constant(0.1) k1 = fe.Constant(0.2) k_1 = fe.Constant(0.00001) # explicit F = ( (u_cl - u_init_cl) * v_cl * dx + dt * D * inner(grad(u_cl), grad(v_cl)) * dx + dt * inner(flow, grad(u_cl)) * v_cl * dx #+ (u_na - u_init_na) * v_na * dx #+ dt * D * inner(grad(u_na), grad(v_na)) * dx #+ dt * inner(flow, grad(u_na)) * v_na * dx + (u_k - u_init_k) * v_k * dx + dt * D * inner(grad(u_k), grad(v_k)) * dx + dt * inner(flow, grad(u_k)) * v_k * dx + f_in_cl * v_cl * dx #+ f_in * v_na * dx + f_in * v_k * dx + dt * k1 * u_init_cl * C_na * u_init_na * v_cl * dx #+ dt * k1 * u_init_cl * u_init_na * v_na * dx - dt * k1 * u_init_cl * C_na * u_init_na * v_k * dx - dt * k_1 * u_init_k * v_cl * dx #- dt * k_1 * u_init_k * v_na * dx + dt * k_1 * u_init_k * v_k * dx ) # implicit F = ( (u_cl - u_init_cl) * v_cl * dx + dt * D * inner(grad(u_cl), grad(v_cl)) * dx + dt * inner(flow, grad(u_cl)) * v_cl * dx # + (u_na - u_init_na) * v_na * dx # + dt * D * inner(grad(u_na), grad(v_na)) * dx # + dt * inner(flow, grad(u_na)) * v_na * dx + (u_k - u_init_k) * v_k * dx + dt * D * inner(grad(u_k), grad(v_k)) * dx + dt * inner(flow, grad(u_k)) * v_k * dx + f_in_cl * v_cl * dx # + f_in * v_na * dx + f_in * v_k * dx + dt * k1 * u_cl * C_na * u_init_na * v_cl * dx # + dt * k1 * u_init_cl * u_init_na * v_na * dx - dt * k1 * u_cl * C_na * u_init_na * v_k * dx - dt * k_1 * u_k * v_cl * dx # - dt * k_1 * u_init_k * v_na * dx + dt * k_1 * u_k * v_k * dx ) self.F = F a, L = fe.lhs(F), fe.rhs(F) a_mat = fe.assemble(a) L_vec = fe.assemble(L) output1 = fe.File('/tmp/cl_dyn.pvd') output2 = fe.File('/tmp/na_dyn.pvd') output3 = fe.File('/tmp/k_dyn.pvd') output4 = fe.File('/tmp/all_dyn.pvd') # solve self.sol = [] u_na = Function(V_single) u_na = fe.interpolate(u_init_na,V_single) na_inflow = 0 t_plot = 0.5 t_last_plot = 0 while t < t_end: t = t + dt t_last_plot += dt print(t) u = Function(V) u_init_na.set_time(5*t) a_mat = fe.assemble(a) L_vec = fe.assemble(L) fe.solve(a_mat, u.vector(), L_vec) # NonlinearVariationalProblem(F,u) u_init.assign(u) u_cl, u_k = u.split() # u_init_cl.assign(u_cl) # u_init_na.assign(u_na) # u_init_k.assign(u_k) u_na = fe.interpolate(u_init_na, V_single) u_cl.rename("cl", "cl") u_na.rename("na", "na") u_k.rename("k", "k") output1 << u_cl, t output2 << u_na, t output3 << u_k, t self.sol.append((u_cl, u_na, u_k)) print( fe.assemble(u_cl*self.dx)) if t_last_plot > t_plot: t_last_plot = 0 plt.figure(figsize=(8,16)) plt.subplot(211) fe.plot(u_cl) plt.subplot(212) fe.plot(u_k) plt.show() self.u_cl = u_cl #self.u_na = u_na self.u_k = u_k
def compute_conv_diff_reac(self, initial_condition=None): names = {'Cl', 'Na', 'K'} dt = 0.1 t = 0. t_end = 1. P1 = FiniteElement('P', fe.triangle, 3) element = MixedElement([P1, P1, P1]) V = FunctionSpace(self.mesh, element) self.V_conc = V u_init = Function(V) (u_cl, u_na, u_k) = TrialFunction(V) (v_cl, v_na, v_k) = TestFunction(V) if initial_condition is None: initial_condition = Expression(("exp(-((x[0]-0.1)*(x[0]-0.1)+x[1]*x[1])/0.01)", "exp(-((x[0]-0.12)*(x[0]-0.12)+x[1]*x[1])/0.01)", "0."), element=element) u_init = fe.interpolate(initial_condition, V) u_init_cl = u_init[0] u_init_na = u_init[1] u_init_k = u_init[2] assert (self.flow is not None) n = fe.FacetNormal(self.mesh) dx, ds = self.dx, self.ds flow = 10 * self.flow f_in = fe.Constant(0.00) D = fe.Constant(0.01) k1 = fe.Constant(0.1) k_1 = fe.Constant(0.001) F = ( (u_cl - u_init_cl) * v_cl * dx + dt * D * inner(grad(u_cl), grad(v_cl)) * dx + dt * inner(flow, grad(u_cl)) * v_cl * dx + (u_na - u_init_na) * v_na * dx + dt * D * inner(grad(u_na), grad(v_na)) * dx + dt * inner(flow, grad(u_na)) * v_na * dx + (u_k - u_init_k) * v_k * dx + dt * D * inner(grad(u_k), grad(v_k)) * dx + dt * inner(flow, grad(u_k)) * v_k * dx + f_in * v_cl * dx + f_in * v_na * dx + f_in * v_k * dx + dt * k1 * u_init_cl * u_init_na * v_cl * dx + dt * k1 * u_init_cl * u_init_na * v_na * dx - dt * k1 * u_init_cl * u_init_na * v_k * dx - dt * k_1 * u_init_k * v_cl * dx - dt * k_1 * u_init_k * v_na * dx + dt * k_1 * u_init_k * v_k * dx ) self.F = F a, L = fe.lhs(F), fe.rhs(F) a_mat = fe.assemble(a) L_vec = fe.assemble(L) output1 = fe.File('/tmp/cl_dyn.pvd') output2 = fe.File('/tmp/na_dyn.pvd') output3 = fe.File('/tmp/k_dyn.pvd') output4 = fe.File('/tmp/all_dyn.pvd') # solve self.sol = [] while t < t_end: t = t + dt print(t) u = Function(V) a_mat = fe.assemble(a) L_vec = fe.assemble(L) fe.solve(a_mat, u.vector(), L_vec) # NonlinearVariationalProblem(F,u) u_init.assign(u) u_cl, u_na, u_k = u.split() # u_init_cl.assign(u_cl) # u_init_na.assign(u_na) # u_init_k.assign(u_k) u_cl.rename("cl", "cl") u_na.rename("na", "na") u_k.rename("k", "k") output1 << u_cl, t output2 << u_na, t output3 << u_k, t self.sol.append((u_cl, u_na, u_k)) self.u_cl = u_cl self.u_na = u_na self.u_k = u_k