def solve(self, parameters): "Solve the FSI problem (main adaptive loop)" # Get parameters tolerance = parameters["tolerance"] w_h = parameters["w_h"] max_num_refinements = parameters["max_num_refinements"] # Set DOLFIN parameters dolfin_parameters["form_compiler"]["cpp_optimize"] = True dolfin_parameters["refinement_algorithm"] = parameters["refinement_algorithm"] # Create empty solution (return value when primal is not solved) U = 5*(None,) # Save initial mesh save_mesh(self.problem.mesh(), parameters) # Adaptive loop cpu_time = python_time() goal_functional = None final = False for level in range(max_num_refinements + 1): # Solve primal problem if parameters["solve_primal"]: begin("Solving primal problem") self.primalsolver = PrimalSolver() goal_functional = self.primalsolver.solve_primal(self.problem, parameters) end() else: info("Not solving primal problem") # Solve dual problem if parameters["solve_dual"]: begin("Solving dual problem") solve_dual(self.problem, parameters) end() else: info("Not solving dual problem") # Estimate error and compute error indicators if parameters["estimate_error"]: begin("Estimating error and computing error indicators") error, indicators, E_h, E_k, E_c = estimate_error(self.problem, parameters) end() # Check if error is small enough begin("Checking error estimate") if error <= tolerance: info_green("Adaptive solver converged on level %d: error = %g <= TOL = %g" % (level, error, tolerance)) break elif final: info_green("Adaptive solver converged on level %d: error = %g (TOL = %g)" % (level, error, tolerance)) info("Error too large but it doesn't get any better than this. ;-)") break else: info_red("Error too large, need to refine: error = %g > TOL = %g" % (error, tolerance)) end() # Check if we reached the maximum number of refinements if level == max_num_refinements: info_blue("Reached maximum number of refinement levels (%d)", max_num_refinements) return goal_functional # Mesh adaptivity begin("Checking space error estimate") mesh_tolerance = w_h * tolerance if parameters["uniform_mesh"]: info_red("Refining mesh uniformly") refined_mesh = refine(self.problem.mesh()) self.problem.init_meshes(refined_mesh, parameters) elif E_h <= mesh_tolerance: info_blue("Freezing current mesh: E_h = %g <= TOL_h = %g" % (E_h, mesh_tolerance)) info_blue("Starting final round!") final = True refined_mesh = self.problem.mesh() else: info_red("Refining mesh adaptively") refined_mesh = refine_mesh(self.problem, self.problem.mesh(), indicators, parameters) self.problem.init_meshes(refined_mesh, parameters) end() # Time step adaptivity if parameters["uniform_timestep"]: info_red("Refining time step uniformly") parameters["initial_timestep"] = 0.5 * parameters["initial_timestep"] else: info_red("Refining time step adaptively") refine_timestep(E_k, parameters) # Update and save mesh mesh = refined_mesh save_mesh(mesh, parameters) else: error = max(1.0, 2*tolerance) info("Not estimating error, setting error to max(1, 2*tolerance) = %g" % error) # Report elapsed time info_blue("Solution computed in %g seconds." % (python_time() - cpu_time)) # Return solution return goal_functional
def solve_dual(problem, parameters): "Solve dual FSI problem" # Get parameters T = problem.end_time() Omega = problem.mesh() save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK files = None level = refinement_level() if save_solution: Z_F_file = File("%s/pvd/level_%d/Z_F.pvd" % (parameters["output_directory"], level)) Y_F_file = File("%s/pvd/level_%d/Y_F.pvd" % (parameters["output_directory"], level)) files = [Z_F_file, Y_F_file] # Create time series for storing solution primal_series = create_primal_series(parameters) dual_series = create_dual_series(parameters) # Record CPU time cpu_time = python_time() # Create mixed function space W = create_dual_space(Omega, parameters) # Create test and trial functions (v_F, q_F) = TestFunctions(W) (Z_F, Y_F) = TrialFunctions(W) # Create dual functions Z0, (Z_F0, Y_F0) = create_dual_functions(Omega, parameters) Z1, (Z_F1, Y_F1) = create_dual_functions(Omega, parameters) # Create primal functions U_F0, P_F0 = U0 = create_primal_functions(Omega, parameters) U_F1, P_F1 = U1 = create_primal_functions(Omega, parameters) # Create time step (value set in each time step) k = Constant(0.0) # Create variational forms for dual problem A, L, cd, efd, ifd = create_dual_forms(Omega, k, problem, v_F, q_F, Z_F, Y_F, Z_F0, Y_F0, U_F0, P_F0, U_F1, P_F1) # Create dual boundary conditions bcs = create_dual_bcs(problem, W) # Write initial value for dual write_dual_data(Z1, T, dual_series) # Time-stepping T = problem.end_time() timestep_range = read_timestep_range(T, primal_series) for i in reversed(range(len(timestep_range) - 1)): # Get current time and time step t0 = timestep_range[i] t1 = timestep_range[i + 1] dt = t1 - t0 k.assign(dt) # Display progress info("") info("-"*80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t0, T, dt)) # Read primal data read_primal_data(U0, t0, Omega, primal_series, parameters) read_primal_data(U1, t1, Omega, primal_series, parameters) # Assemble matrix info("Assembling matrix") matrix = assemble(A, cell_domains=cd, exterior_facet_domains=efd, interior_facet_domains=ifd) # Assemble vector info("Assembling vector") vector = assemble(L, cell_domains=cd, exterior_facet_domains=efd, interior_facet_domains=ifd) # Apply boundary conditions info("Applying boundary conditions") for bc in bcs: bc.apply(matrix, vector) # Remove inactive dofs matrix.ident_zeros() # Solve linear system solve(matrix, Z0.vector(), vector) # Save and plot solution if save_solution: _save_solution(Z0, files) write_dual_data(Z0, t0, dual_series) if plot_solution: _plot_solution(Z_F0, Y_F0) # Copy solution to previous interval (going backwards in time) Z1.assign(Z0) end() # Report elapsed time info_blue("Dual solution computed in %g seconds." % (python_time() - cpu_time))
def solve_dual(problem, parameters): "Solve dual FSI problem" # Get parameters T = problem.end_time() Omega = problem.mesh() save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK files = None level = refinement_level() if save_solution: Z_F_file = File("%s/pvd/level_%d/Z_F.pvd" % (parameters["output_directory"], level)) Y_F_file = File("%s/pvd/level_%d/Y_F.pvd" % (parameters["output_directory"], level)) files = [Z_F_file, Y_F_file] # Create time series for storing solution primal_series = create_primal_series(parameters) dual_series = create_dual_series(parameters) # Record CPU time cpu_time = python_time() # Create mixed function space W = create_dual_space(Omega, parameters) # Create test and trial functions (v_F, q_F) = TestFunctions(W) (Z_F, Y_F) = TrialFunctions(W) # Create dual functions Z0, (Z_F0, Y_F0) = create_dual_functions(Omega, parameters) Z1, (Z_F1, Y_F1) = create_dual_functions(Omega, parameters) # Create primal functions U_F0, P_F0 = U0 = create_primal_functions(Omega, parameters) U_F1, P_F1 = U1 = create_primal_functions(Omega, parameters) # Create time step (value set in each time step) k = Constant(0.0) # Create variational forms for dual problem A, L, cd, efd, ifd = create_dual_forms(Omega, k, problem, v_F, q_F, Z_F, Y_F, Z_F0, Y_F0, U_F0, P_F0, U_F1, P_F1) # Create dual boundary conditions bcs = create_dual_bcs(problem, W) # Write initial value for dual write_dual_data(Z1, T, dual_series) # Time-stepping T = problem.end_time() timestep_range = read_timestep_range(T, primal_series) for i in reversed(range(len(timestep_range) - 1)): # Get current time and time step t0 = timestep_range[i] t1 = timestep_range[i + 1] dt = t1 - t0 k.assign(dt) # Display progress info("") info("-" * 80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t0, T, dt)) # Read primal data read_primal_data(U0, t0, Omega, primal_series, parameters) read_primal_data(U1, t1, Omega, primal_series, parameters) # Assemble matrix info("Assembling matrix") matrix = assemble(A, cell_domains=cd, exterior_facet_domains=efd, interior_facet_domains=ifd) # Assemble vector info("Assembling vector") vector = assemble(L, cell_domains=cd, exterior_facet_domains=efd, interior_facet_domains=ifd) # Apply boundary conditions info("Applying boundary conditions") for bc in bcs: bc.apply(matrix, vector) # Remove inactive dofs matrix.ident_zeros() # Solve linear system solve(matrix, Z0.vector(), vector) # Save and plot solution if save_solution: _save_solution(Z0, files) write_dual_data(Z0, t0, dual_series) if plot_solution: _plot_solution(Z_F0, Y_F0) # Copy solution to previous interval (going backwards in time) Z1.assign(Z0) end() # Report elapsed time info_blue("Dual solution computed in %g seconds." % (python_time() - cpu_time))
def solve_primal(problem, parameters): "Solve primal FSI problem" # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] uniform_timestep = parameters["uniform_timestep"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Define the three subproblems F = FluidProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() # Extract number of dofs num_dofs = u_F0.vector().size() + p_F0.vector().size() # Save initial solution to file and series U = extract_solution(F) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = False # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Time-stepping loop while True: # Display progress info("") info("-"*80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Solve fluid subproblem begin("* Solving fluid subproblem (F)") F.step(dt) end() # Evaluate user goal functional M, cd, efd, ifd = problem.evaluate_functional(u_F1, p_F1) goal_functional = assemble(M, cell_domains=cd, exterior_facet_domains=efd, interior_facet_domains=ifd) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) # Save solution and time series to file U = extract_solution(F) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) # Update time step counter timestep_counter += 1 # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0*DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt end() # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution return goal_functional
def solve(self, parameters): "Solve the FSI problem (main adaptive loop)" # Get parameters tolerance = parameters["tolerance"] w_h = parameters["w_h"] max_num_refinements = parameters["max_num_refinements"] # Set DOLFIN parameters dolfin_parameters["form_compiler"]["cpp_optimize"] = True dolfin_parameters["refinement_algorithm"] = parameters["refinement_algorithm"] # Create empty solution (return value when primal is not solved) U = 5 * (None,) # Save initial mesh save_mesh(self.problem.mesh(), parameters) # Adaptive loop cpu_time = python_time() goal_functional = None final = False for level in range(max_num_refinements + 1): # Solve primal problem if parameters["solve_primal"]: begin("Solving primal problem") self.primalsolver = PrimalSolver() goal_functional = self.primalsolver.solve_primal(self.problem, parameters) end() else: info("Not solving primal problem") # Solve dual problem if parameters["solve_dual"]: begin("Solving dual problem") solve_dual(self.problem, parameters) end() else: info("Not solving dual problem") # Estimate error and compute error indicators if parameters["estimate_error"]: begin("Estimating error and computing error indicators") error, indicators, E_h, E_k, E_c = estimate_error(self.problem, parameters) end() # Check if error is small enough begin("Checking error estimate") if error <= tolerance: info_green( "Adaptive solver converged on level %d: error = %g <= TOL = %g" % (level, error, tolerance) ) break elif final: info_green( "Adaptive solver converged on level %d: error = %g (TOL = %g)" % (level, error, tolerance) ) info("Error too large but it doesn't get any better than this. ;-)") break else: info_red("Error too large, need to refine: error = %g > TOL = %g" % (error, tolerance)) end() # Check if we reached the maximum number of refinements if level == max_num_refinements: info_blue("Reached maximum number of refinement levels (%d)", max_num_refinements) return goal_functional # Mesh adaptivity begin("Checking space error estimate") mesh_tolerance = w_h * tolerance if parameters["uniform_mesh"]: info_red("Refining mesh uniformly") refined_mesh = refine(self.problem.mesh()) self.problem.init_meshes(refined_mesh, parameters) elif E_h <= mesh_tolerance: info_blue("Freezing current mesh: E_h = %g <= TOL_h = %g" % (E_h, mesh_tolerance)) info_blue("Starting final round!") final = True refined_mesh = self.problem.mesh() else: info_red("Refining mesh adaptively") refined_mesh = refine_mesh(self.problem, self.problem.mesh(), indicators, parameters) self.problem.init_meshes(refined_mesh, parameters) end() # Time step adaptivity if parameters["uniform_timestep"]: info_red("Refining time step uniformly") parameters["initial_timestep"] = 0.5 * parameters["initial_timestep"] else: info_red("Refining time step adaptively") refine_timestep(E_k, parameters) # Update and save mesh mesh = refined_mesh save_mesh(mesh, parameters) else: error = max(1.0, 2 * tolerance) info("Not estimating error, setting error to max(1, 2*tolerance) = %g" % error) # Report elapsed time info_blue("Solution computed in %g seconds." % (python_time() - cpu_time)) # Return solution return goal_functional
def solve_primal(problem, parameters): "Solve primal FSI problem" # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] uniform_timestep = parameters["uniform_timestep"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Define the three subproblems F = FluidProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() # Extract number of dofs num_dofs = u_F0.vector().size() + p_F0.vector().size() # Save initial solution to file and series U = extract_solution(F) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = False # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Time-stepping loop while True: # Display progress info("") info("-" * 80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Solve fluid subproblem begin("* Solving fluid subproblem (F)") F.step(dt) end() # Evaluate user goal functional M, cd, efd, ifd = problem.evaluate_functional(u_F1, p_F1) goal_functional = assemble(M, cell_domains=cd, exterior_facet_domains=efd, interior_facet_domains=ifd) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) # Save solution and time series to file U = extract_solution(F) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) # Update time step counter timestep_counter += 1 # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0 * DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt end() # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution return goal_functional
def solve_dual(problem, parameters): "Solve dual FSI problem" # Get parameters T = problem.end_time() Omega = problem.mesh() Omega_F = problem.fluid_mesh() Omega_S = problem.structure_mesh() save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK files = None level = refinement_level() if save_solution: Z_F_file = File("%s/pvd/level_%d/Z_F.pvd" % (parameters["output_directory"], level)) Y_F_file = File("%s/pvd/level_%d/Y_F.pvd" % (parameters["output_directory"], level)) X_F_file = File("%s/pvd/level_%d/X_F.pvd" % (parameters["output_directory"], level)) Z_S_file = File("%s/pvd/level_%d/Z_S.pvd" % (parameters["output_directory"], level)) Y_S_file = File("%s/pvd/level_%d/Y_S.pvd" % (parameters["output_directory"], level)) Z_M_file = File("%s/pvd/level_%d/Z_M.pvd" % (parameters["output_directory"], level)) Y_M_file = File("%s/pvd/level_%d/Y_M.pvd" % (parameters["output_directory"], level)) files = [ Z_F_file, Y_F_file, X_F_file, Z_S_file, Y_S_file, Z_M_file, Y_M_file ] # Create time series for storing solution primal_series = create_primal_series(parameters) dual_series = create_dual_series(parameters) # Record CPU time cpu_time = python_time() # Create mixed function space W = create_dual_space(Omega, parameters) # Create test and trial functions (v_F, q_F, s_F, v_S, q_S, v_M, q_M) = TestFunctions(W) (Z_F, Y_F, X_F, Z_S, Y_S, Z_M, Y_M) = TrialFunctions(W) # Create dual functions #These will effect the forms Z0, (Z_F0, Y_F0, X_F0, Z_S0, Y_S0, Z_M0, Y_M0) = create_dual_functions(Omega, parameters) #These are used for data storage Z1, (Z_F1, Y_F1, X_F1, Z_S1, Y_S1, Z_M1, Y_M1) = create_dual_functions(Omega, parameters) # Create primal functions U_F0, P_F0, U_S0, P_S0, U_M0 = U0 = create_primal_functions( Omega, parameters) U_F1, P_F1, U_S1, P_S1, U_M1 = U1 = create_primal_functions( Omega, parameters) # Create time step (value set in each time step) k = Constant(0.0) # Create variational forms for dual problem A, L = create_dual_forms(Omega_F, Omega_S, k, problem, v_F, q_F, s_F, v_S, q_S, v_M, q_M, Z_F, Y_F, X_F, Z_S, Y_S, Z_M, Y_M, Z_F0, Y_F0, X_F0, Z_S0, Y_S0, Z_M0, Y_M0, U_F0, P_F0, U_S0, P_S0, U_M0, U_F1, P_F1, U_S1, P_S1, U_M1, parameters) # Create dual boundary conditions bcs = create_dual_bcs(problem, W) # Write initial value for dual write_dual_data(Z1, T, dual_series) # Time-stepping T = problem.end_time() timestep_range = read_timestep_range(T, primal_series) for i in reversed(range(len(timestep_range) - 1)): # Get current time and time step t0 = timestep_range[i] t1 = timestep_range[i + 1] dt = t1 - t0 k.assign(dt) # Display progress info("") info("-" * 80) begin("* Starting new time step") info_blue("* t = %g (T = %g, dt = %g)" % (t0, T, dt)) # Read primal data read_primal_data(U0, t0, Omega, Omega_F, Omega_S, primal_series, parameters) read_primal_data(U1, t1, Omega, Omega_F, Omega_S, primal_series, parameters) # GB: In the Analytic problem there are no do nothing fluid boundaries. I am not # this is reflected here in the meshfunctions and their facet numberings. # Assemble matrix info("Assembling matrix") matrix = assemble(A, cell_domains=problem.cell_domains, exterior_facet_domains=problem.fsi_boundary, interior_facet_domains=problem.fsi_boundary) # Assemble vector info("Assembling vector") vector = assemble(L, cell_domains=problem.cell_domains, exterior_facet_domains=problem.fsi_boundary, interior_facet_domains=problem.fsi_boundary) # Remove inactive dofs info("Removing inactive dofs") matrix.ident_zeros() # Apply boundary conditions info("Applying boundary conditions") for bc in bcs: bc.apply(matrix, vector) # Solve linear system solve(matrix, Z0.vector(), vector) info("Solved linear system: ||Z|| = " + str(Z0.vector().norm("l2"))) # Save and plot solution if save_solution: _save_solution(Z0, files) write_dual_data(Z0, t0, dual_series) if plot_solution: _plot_solution(Z_F0, Y_F0, X_F0, Z_S0, Y_S0, Z_M0, Y_M0) # Copy solution to previous interval (going backwards in time) Z1.assign(Z0) end() # Report elapsed time info_blue("Dual solution computed in %g seconds." % (python_time() - cpu_time))
def solve_primal(problem, parameters): "Solve primal FSI problem" # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] uniform_timestep = parameters["uniform_timestep"] maxiter = parameters["maximum_iterations"] num_smoothings = parameters["num_smoothings"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/P_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_M.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Define the three subproblems F = FluidProblem(problem) S = StructureProblem(problem, parameters) M = MeshProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() U_M0, U_M1 = M.solution_values() # Extract number of dofs num_dofs_FSM = extract_num_dofs(F, S, M) # Get initial structure displacement (used for plotting and checking convergence) structure_element_degree = parameters["structure_element_degree"] V_S = VectorFunctionSpace(problem.structure_mesh(), "CG", structure_element_degree) U_S0 = Function(V_S) # Save initial solution to file and series U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = False # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Time-stepping loop while True: # Display progress info("") info("-" * 80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Compute tolerance for FSI iterations itertol = compute_itertol(problem, w_c, TOL, dt, t1, parameters) # Fixed point iteration on FSI problem for iter in range(maxiter): info("") begin("* Starting nonlinear iteration") # Solve fluid subproblem begin("* Solving fluid subproblem (F)") F.step(dt) end() # Transfer fluid stresses to structure begin("* Transferring fluid stresses to structure (F --> S)") Sigma_F = F.compute_fluid_stress(u_F0, u_F1, p_F0, p_F1, U_M0, U_M1) S.update_fluid_stress(Sigma_F) end() # Solve structure subproblem begin("* Solving structure subproblem (S)") U_S1, P_S1 = S.step(dt) end() # Transfer structure displacement to fluid mesh begin( "* Transferring structure displacement to fluid mesh (S --> M)" ) M.update_structure_displacement(U_S1) end() # Solve mesh equation begin("* Solving mesh subproblem (M)") M.step(dt) end() # Transfer mesh displacement to fluid begin("* Transferring mesh displacement to fluid (M --> S)") F.update_mesh_displacement(U_M1, dt, num_smoothings) end() # Compute increment of displacement vector U_S0.vector().axpy(-1, U_S1.vector()) increment = norm(U_S0.vector()) U_S0.vector()[:] = U_S1.vector()[:] # Plot solution if plot_solution: _plot_solution(u_F1, p_F1, U_S1, U_M1) # Check convergence if increment < itertol: info("") info_green( "Increment = %g (tolerance = %g), converged after %d iterations" % (increment, itertol, iter + 1)) info("") end() # Saving number of FSI iterations save_no_FSI_iter(t1, iter + 1, parameters) # Evaluate user goal functional goal_functional = assemble( problem.evaluate_functional(u_F1, p_F1, U_S1, P_S1, U_M1, dx, dx, dx)) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) break # Check if we have reached the maximum number of iterations elif iter == maxiter - 1: raise RuntimeError, "FSI iteration failed to converge after %d iterations." % maxiter # Print size of increment info("") info_red("Increment = %g (tolerance = %g), iteration %d" % (increment, itertol, iter + 1)) end() # Save solution and time series to file U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) S.update() M.update(t1) # Update time step counter timestep_counter += 1 # FIXME: This should be done automatically by the solver F.update_extra() # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs_FSM, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0 * DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution return goal_functional
def solve_primal(self, problem, parameters): "Solve primal FSI problem" #def __init__() # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] uniform_timestep = parameters["uniform_timestep"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/P_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_M.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Update of user problem at t = 0 (important for initial conditions) problem.update(0.0, 0.0, dt) # Define the three subproblems F = FluidProblem(problem, solver_type=parameters["fluid_solver"]) S = StructureProblem(problem, parameters) M = MeshProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() U_M0, U_M1 = M.solution_values() # Extract number of dofs num_dofs_FSM = extract_num_dofs(F, S, M) info("FSI problem has %d dofs (%d + %d + %d)" % \ (num_dofs_FSM, F.num_dofs, S.num_dofs, M.num_dofs)) # Get initial structure displacement (used for plotting and checking convergence) structure_element_degree = parameters["structure_element_degree"] V_S = VectorFunctionSpace(problem.structure_mesh(), "CG", structure_element_degree) U_S0 = Function(V_S) # Save initial solution to file and series U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = abs(t1 - T) / T < 100.0 * DOLFIN_EPS # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Get reference value of goal functional if hasattr(problem, "reference_value"): reference_value = problem.reference_value() else: reference_value = None if parameters["primal_solver"] == "Newton": #If no initial_step function try to generate one if not hasattr(problem, "initial_step"): problem.initial_step = lambda: parameters["initial_timestep"] # Initialize an FSINewtonSolver Object fsinewtonsolver = FSINewtonSolver(problem,\ params = parameters["FSINewtonSolver"].to_dict()) #initialize the solve settings fsinewtonsolver.prepare_solve() #def solve_primal() while True: # Display progress info("") info("-" * 80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Update of user problem problem.update(t0, t1, dt) # Compute tolerance for FSI iterations itertol = compute_itertol(problem, w_c, TOL, dt, t1, parameters) if parameters["primal_solver"] == "Newton": #Newtonsolver has it's own timings assert save_solution, "Parameter save_solution must be true to use the Newton Solver" U_S1, U_S0, P_S1, increment, numiter = newton_solve( F, S, M, U_S0, dt, parameters, itertol, problem, fsinewtonsolver) elif parameters["primal_solver"] == "fixpoint": timings.startnext("FixpointSolve") U_S0, U_S1, P_S1, increment, numiter = fixpoint_solve( F, S, U_S0, M, dt, t1, parameters, itertol, problem) timings.stop("FixpointSolve") else: raise Exception( "Only 'fixpoint' and 'Newton' are possible values \ for the parameter 'primal_solver'") self.g_numiter = numiter ##################################################### #The primal solve worked so now go to post processing ##################################################### #def postprocessing(): # Plot solution if plot_solution: _plot_solution(u_F1, p_F1, U_S0, U_M1) if problem.exact_solution() is not None: update_exactsol(u_F1, p_F1, U_S1, U_M1, F, problem, t1) info("") info_green( "Increment = %g (tolerance = %g), converged after %d iterations" % (increment, itertol, numiter + 1)) info("") end() # Saving number of FSI iterations save_no_FSI_iter(t1, numiter + 1, parameters) # Evaluate user goal functional goal_functional = assemble( problem.evaluate_functional(u_F1, p_F1, U_S1, P_S1, U_M1, dx, dx, dx)) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) # Save solution and time series to file U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) S.update() M.update(t1) # Update time step counter timestep_counter += 1 # FIXME: This should be done automatically by the solver F.update_extra() # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs_FSM, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0 * DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt #End of Time loop #Call post processing for the Newton Solver if necessary. if parameters["primal_solver"] == "Newton": fsinewtonsolver.post_processing() # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, reference_value, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution info(timings.report_str()) return (goal_functional, integrated_goal_functional)
def solve_primal(self,problem, parameters): "Solve primal FSI problem" #def __init__() # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] uniform_timestep = parameters["uniform_timestep"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/P_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_M.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Update of user problem at t = 0 (important for initial conditions) problem.update(0.0, 0.0, dt) # Define the three subproblems F = FluidProblem(problem, solver_type=parameters["fluid_solver"]) S = StructureProblem(problem, parameters) M = MeshProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() U_M0, U_M1 = M.solution_values() # Extract number of dofs num_dofs_FSM = extract_num_dofs(F, S, M) info("FSI problem has %d dofs (%d + %d + %d)" % \ (num_dofs_FSM, F.num_dofs, S.num_dofs, M.num_dofs)) # Get initial structure displacement (used for plotting and checking convergence) structure_element_degree = parameters["structure_element_degree"] V_S = VectorFunctionSpace(problem.structure_mesh(), "CG", structure_element_degree) U_S0 = Function(V_S) # Save initial solution to file and series U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = abs(t1 - T) / T < 100.0*DOLFIN_EPS # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Get reference value of goal functional if hasattr(problem, "reference_value"): reference_value = problem.reference_value() else: reference_value = None if parameters["primal_solver"] == "Newton": #If no initial_step function try to generate one if not hasattr(problem,"initial_step"): problem.initial_step = lambda :parameters["initial_timestep"] # Initialize an FSINewtonSolver Object fsinewtonsolver = FSINewtonSolver(problem,\ params = parameters["FSINewtonSolver"].to_dict()) #initialize the solve settings fsinewtonsolver.prepare_solve() #def solve_primal() while True: # Display progress info("") info("-"*80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Update of user problem problem.update(t0, t1, dt) # Compute tolerance for FSI iterations itertol = compute_itertol(problem, w_c, TOL, dt, t1, parameters) if parameters["primal_solver"] == "Newton": #Newtonsolver has it's own timings assert save_solution,"Parameter save_solution must be true to use the Newton Solver" U_S1,U_S0,P_S1,increment,numiter = newton_solve(F,S,M,U_S0,dt,parameters,itertol,problem,fsinewtonsolver) elif parameters["primal_solver"] == "fixpoint": timings.startnext("FixpointSolve") U_S0,U_S1,P_S1,increment,numiter = fixpoint_solve(F,S,U_S0,M,dt,t1,parameters,itertol,problem) timings.stop("FixpointSolve") else: raise Exception("Only 'fixpoint' and 'Newton' are possible values \ for the parameter 'primal_solver'") self.g_numiter = numiter ##################################################### #The primal solve worked so now go to post processing ##################################################### #def postprocessing(): # Plot solution if plot_solution: _plot_solution(u_F1, p_F1, U_S0, U_M1) if problem.exact_solution() is not None: update_exactsol(u_F1,p_F1,U_S1,U_M1,F,problem,t1) info("") info_green("Increment = %g (tolerance = %g), converged after %d iterations" % (increment, itertol, numiter + 1)) info("") end() # Saving number of FSI iterations save_no_FSI_iter(t1, numiter + 1, parameters) # Evaluate user goal functional goal_functional = assemble(problem.evaluate_functional(u_F1, p_F1, U_S1, P_S1, U_M1, dx, dx, dx)) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) # Save solution and time series to file U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) S.update() M.update(t1) # Update time step counter timestep_counter += 1 # FIXME: This should be done automatically by the solver F.update_extra() # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs_FSM, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0*DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt #End of Time loop #Call post processing for the Newton Solver if necessary. if parameters["primal_solver"] == "Newton": fsinewtonsolver.post_processing() # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, reference_value, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution info(timings.report_str()) return (goal_functional, integrated_goal_functional)
def solve_dual(problem, parameters): "Solve dual FSI problem" # Get parameters T = problem.end_time() Omega = problem.mesh() Omega_F = problem.fluid_mesh() Omega_S = problem.structure_mesh() save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] # Create files for saving to VTK files = None level = refinement_level() if save_solution: Z_F_file = File("%s/pvd/level_%d/Z_F.pvd" % (parameters["output_directory"], level)) Y_F_file = File("%s/pvd/level_%d/Y_F.pvd" % (parameters["output_directory"], level)) X_F_file = File("%s/pvd/level_%d/X_F.pvd" % (parameters["output_directory"], level)) Z_S_file = File("%s/pvd/level_%d/Z_S.pvd" % (parameters["output_directory"], level)) Y_S_file = File("%s/pvd/level_%d/Y_S.pvd" % (parameters["output_directory"], level)) Z_M_file = File("%s/pvd/level_%d/Z_M.pvd" % (parameters["output_directory"], level)) Y_M_file = File("%s/pvd/level_%d/Y_M.pvd" % (parameters["output_directory"], level)) files = [Z_F_file, Y_F_file, X_F_file, Z_S_file, Y_S_file, Z_M_file, Y_M_file] # Create time series for storing solution primal_series = create_primal_series(parameters) dual_series = create_dual_series(parameters) # Record CPU time cpu_time = python_time() # Create mixed function space W = create_dual_space(Omega, parameters) # Create test and trial functions (v_F, q_F, s_F, v_S, q_S, v_M, q_M) = TestFunctions(W) (Z_F, Y_F, X_F, Z_S, Y_S, Z_M, Y_M) = TrialFunctions(W) # Create dual functions # These will effect the forms Z0, (Z_F0, Y_F0, X_F0, Z_S0, Y_S0, Z_M0, Y_M0) = create_dual_functions(Omega, parameters) # These are used for data storage Z1, (Z_F1, Y_F1, X_F1, Z_S1, Y_S1, Z_M1, Y_M1) = create_dual_functions(Omega, parameters) # Create primal functions U_F0, P_F0, U_S0, P_S0, U_M0 = U0 = create_primal_functions(Omega, parameters) U_F1, P_F1, U_S1, P_S1, U_M1 = U1 = create_primal_functions(Omega, parameters) # Create time step (value set in each time step) k = Constant(0.0) # Create variational forms for dual problem A, L = create_dual_forms( Omega_F, Omega_S, k, problem, v_F, q_F, s_F, v_S, q_S, v_M, q_M, Z_F, Y_F, X_F, Z_S, Y_S, Z_M, Y_M, Z_F0, Y_F0, X_F0, Z_S0, Y_S0, Z_M0, Y_M0, U_F0, P_F0, U_S0, P_S0, U_M0, U_F1, P_F1, U_S1, P_S1, U_M1, parameters, ) # Create dual boundary conditions bcs = create_dual_bcs(problem, W) # Write initial value for dual write_dual_data(Z1, T, dual_series) # Time-stepping T = problem.end_time() timestep_range = read_timestep_range(T, primal_series) for i in reversed(range(len(timestep_range) - 1)): # Get current time and time step t0 = timestep_range[i] t1 = timestep_range[i + 1] dt = t1 - t0 k.assign(dt) # Display progress info("") info("-" * 80) begin("* Starting new time step") info_blue("* t = %g (T = %g, dt = %g)" % (t0, T, dt)) # Read primal data read_primal_data(U0, t0, Omega, Omega_F, Omega_S, primal_series, parameters) read_primal_data(U1, t1, Omega, Omega_F, Omega_S, primal_series, parameters) # GB: In the Analytic problem there are no do nothing fluid boundaries. I am not # this is reflected here in the meshfunctions and their facet numberings. # Assemble matrix info("Assembling matrix") matrix = assemble( A, cell_domains=problem.cell_domains, exterior_facet_domains=problem.fsi_boundary, interior_facet_domains=problem.fsi_boundary, ) # Assemble vector info("Assembling vector") vector = assemble( L, cell_domains=problem.cell_domains, exterior_facet_domains=problem.fsi_boundary, interior_facet_domains=problem.fsi_boundary, ) # Remove inactive dofs info("Removing inactive dofs") matrix.ident_zeros() # Apply boundary conditions info("Applying boundary conditions") for bc in bcs: bc.apply(matrix, vector) # Solve linear system solve(matrix, Z0.vector(), vector) info("Solved linear system: ||Z|| = " + str(Z0.vector().norm("l2"))) # Save and plot solution if save_solution: _save_solution(Z0, files) write_dual_data(Z0, t0, dual_series) if plot_solution: _plot_solution(Z_F0, Y_F0, X_F0, Z_S0, Y_S0, Z_M0, Y_M0) # Copy solution to previous interval (going backwards in time) Z1.assign(Z0) end() # Report elapsed time info_blue("Dual solution computed in %g seconds." % (python_time() - cpu_time))
def solve_primal(problem, parameters): "Solve primal FSI problem" # Get parameters T = problem.end_time() dt = initial_timestep(problem, parameters) TOL = parameters["tolerance"] w_k = parameters["w_k"] w_c = parameters["w_c"] save_solution = parameters["save_solution"] plot_solution = parameters["plot_solution"] uniform_timestep = parameters["uniform_timestep"] maxiter = parameters["maximum_iterations"] num_smoothings = parameters["num_smoothings"] # Create files for saving to VTK level = refinement_level() if save_solution: files = (File("%s/pvd/level_%d/u_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/p_F.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/P_S.pvd" % (parameters["output_directory"], level)), File("%s/pvd/level_%d/U_M.pvd" % (parameters["output_directory"], level))) # Create time series for storing solution primal_series = create_primal_series(parameters) # Create time series for dual solution if level > 0: dual_series = create_dual_series(parameters) else: dual_series = None # Record CPU time cpu_time = python_time() # Record number of time steps timestep_counter = 0 # Define the three subproblems F = FluidProblem(problem) S = StructureProblem(problem, parameters) M = MeshProblem(problem, parameters) # Get solution values u_F0, u_F1, p_F0, p_F1 = F.solution_values() U_M0, U_M1 = M.solution_values() # Extract number of dofs num_dofs_FSM = extract_num_dofs(F, S, M) # Get initial structure displacement (used for plotting and checking convergence) structure_element_degree = parameters["structure_element_degree"] V_S = VectorFunctionSpace(problem.structure_mesh(), "CG", structure_element_degree) U_S0 = Function(V_S) # Save initial solution to file and series U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, 0, primal_series) # Initialize adaptive data init_adaptive_data(problem, parameters) # Initialize time-stepping t0 = 0.0 t1 = dt at_end = False # Initialize integration of goal functional (assuming M(u) = 0 at t = 0) integrated_goal_functional = 0.0 old_goal_functional = 0.0 # Time-stepping loop while True: # Display progress info("") info("-"*80) begin("* Starting new time step") info_blue(" * t = %g (T = %g, dt = %g)" % (t1, T, dt)) # Compute tolerance for FSI iterations itertol = compute_itertol(problem, w_c, TOL, dt, t1, parameters) # Fixed point iteration on FSI problem for iter in range(maxiter): info("") begin("* Starting nonlinear iteration") # Solve fluid subproblem begin("* Solving fluid subproblem (F)") F.step(dt) end() # Transfer fluid stresses to structure begin("* Transferring fluid stresses to structure (F --> S)") Sigma_F = F.compute_fluid_stress(u_F0, u_F1, p_F0, p_F1, U_M0, U_M1) S.update_fluid_stress(Sigma_F) end() # Solve structure subproblem begin("* Solving structure subproblem (S)") U_S1, P_S1 = S.step(dt) end() # Transfer structure displacement to fluid mesh begin("* Transferring structure displacement to fluid mesh (S --> M)") M.update_structure_displacement(U_S1) end() # Solve mesh equation begin("* Solving mesh subproblem (M)") M.step(dt) end() # Transfer mesh displacement to fluid begin("* Transferring mesh displacement to fluid (M --> S)") F.update_mesh_displacement(U_M1, dt, num_smoothings) end() # Compute increment of displacement vector U_S0.vector().axpy(-1, U_S1.vector()) increment = norm(U_S0.vector()) U_S0.vector()[:] = U_S1.vector()[:] # Plot solution if plot_solution: _plot_solution(u_F1, p_F1, U_S1, U_M1) # Check convergence if increment < itertol: info("") info_green("Increment = %g (tolerance = %g), converged after %d iterations" % (increment, itertol, iter + 1)) info("") end() # Saving number of FSI iterations save_no_FSI_iter(t1, iter + 1, parameters) # Evaluate user goal functional goal_functional = assemble(problem.evaluate_functional(u_F1, p_F1, U_S1, P_S1, U_M1, dx, dx, dx)) # Integrate goal functional integrated_goal_functional += 0.5 * dt * (old_goal_functional + goal_functional) old_goal_functional = goal_functional # Save goal functional save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters) break # Check if we have reached the maximum number of iterations elif iter == maxiter - 1: raise RuntimeError, "FSI iteration failed to converge after %d iterations." % maxiter # Print size of increment info("") info_red("Increment = %g (tolerance = %g), iteration %d" % (increment, itertol, iter + 1)) end() # Save solution and time series to file U = extract_solution(F, S, M) if save_solution: _save_solution(U, files) write_primal_data(U, t1, primal_series) # Move to next time step F.update(t1) S.update() M.update(t1) # Update time step counter timestep_counter += 1 # FIXME: This should be done automatically by the solver F.update_extra() # Check if we have reached the end time if at_end: info("") info_green("Finished time-stepping") save_dofs(num_dofs_FSM, timestep_counter, parameters) end() break # Use constant time step if uniform_timestep: t0 = t1 t1 = min(t1 + dt, T) dt = t1 - t0 at_end = abs(t1 - T) / T < 100.0*DOLFIN_EPS # Compute new adaptive time step else: Rk = compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters) (dt, at_end) = compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters) t0 = t1 t1 = t1 + dt # Save final value of goal functional save_goal_functional_final(goal_functional, integrated_goal_functional, parameters) # Report elapsed time info_blue("Primal solution computed in %g seconds." % (python_time() - cpu_time)) info("") # Return solution return goal_functional