Example #1
0
    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
Example #2
0
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))
Example #3
0
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))
Example #4
0
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
Example #5
0
    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
Example #6
0
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
Example #7
0
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))
Example #8
0
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
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
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))
Example #12
0
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