コード例 #1
0
def _test_time_stepping_1_sparse(callback_type, integrator_type):
    # Create mesh and define function space
    mesh = IntervalMesh(132, 0, 2*pi)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Define Dirichlet boundary (x = 0 or x = 2*pi)
    def boundary(x):
        return x[0] < 0 + DOLFIN_EPS or x[0] > 2*pi - 10*DOLFIN_EPS
        
    # Define time step
    dt = 0.01
    T = 1.

    # Define exact solution
    exact_solution_expression = Expression("sin(x[0]+t)", t=0, element=V.ufl_element())
    # ... and interpolate it at the final time
    exact_solution_expression.t = T
    exact_solution = project(exact_solution_expression, V)

    # Define exact solution dot
    exact_solution_dot_expression = Expression("cos(x[0]+t)", t=0, element=V.ufl_element())
    # ... and interpolate it at the final time
    exact_solution_dot_expression.t = T
    exact_solution_dot = project(exact_solution_dot_expression, V)

    # Define variational problem
    du = TrialFunction(V)
    du_dot = TrialFunction(V)
    v = TestFunction(V)
    u = Function(V)
    u_dot = Function(V)
    g = Expression("sin(x[0]+t) + cos(x[0]+t)", t=0., element=V.ufl_element())
    r_u = inner(grad(u), grad(v))*dx
    j_u = derivative(r_u, u, du)
    r_u_dot = inner(u_dot, v)*dx
    j_u_dot = derivative(r_u_dot, u_dot, du_dot)
    r = r_u_dot + r_u - g*v*dx
    x = inner(du, v)*dx
    def bc(t):
        exact_solution_expression.t = t
        return [DirichletBC(V, exact_solution_expression, boundary)]

    # Assemble inner product matrix
    X = assemble(x)
    
    # Define callback function depending on callback type
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":
        def callback(arg):
            return arg
    elif callback_type == "tensor callbacks":
        def callback(arg):
            return assemble(arg)
            
    # Define problem wrapper
    class SparseProblemWrapper(TimeDependentProblem1Wrapper):
        # Residual and jacobian functions
        def residual_eval(self, t, solution, solution_dot):
            g.t = t
            return callback(r)
        def jacobian_eval(self, t, solution, solution_dot, solution_dot_coefficient):
            return callback(Constant(solution_dot_coefficient)*j_u_dot + j_u)
            
        # Define boundary condition
        def bc_eval(self, t):
            return bc(t)
            
        # Define initial condition
        def ic_eval(self):
            exact_solution_expression.t = 0.
            return project(exact_solution_expression, V)
            
        # Define custom monitor to plot the solution
        def monitor(self, t, solution, solution_dot):
            if matplotlib.get_backend() != "agg":
                plt.subplot(1, 2, 1).clear()
                plot(solution, title="u at t = " + str(t))
                plt.subplot(1, 2, 2).clear()
                plot(solution_dot, title="u_dot at t = " + str(t))
                plt.show(block=False)
                plt.pause(DOLFIN_EPS)
            else:
                print("||u|| at t = " + str(t) + ": " + str(solution.vector().norm("l2")))
                print("||u_dot|| at t = " + str(t) + ": " + str(solution_dot.vector().norm("l2")))

    # Solve the time dependent problem
    sparse_problem_wrapper = SparseProblemWrapper()
    (sparse_solution, sparse_solution_dot) = (u, u_dot)
    sparse_solver = SparseTimeStepping(sparse_problem_wrapper, sparse_solution, sparse_solution_dot)
    sparse_solver.set_parameters({
        "initial_time": 0.0,
        "time_step_size": dt,
        "final_time": T,
        "exact_final_time": "stepover",
        "integrator_type": integrator_type,
        "problem_type": "linear",
        "linear_solver": "mumps",
        "monitor": sparse_problem_wrapper.monitor,
        "report": True
    })
    all_sparse_solutions_time, all_sparse_solutions, all_sparse_solutions_dot = sparse_solver.solve()
    assert len(all_sparse_solutions_time) == int(T/dt + 1)
    assert len(all_sparse_solutions) == int(T/dt + 1)
    assert len(all_sparse_solutions_dot) == int(T/dt + 1)

    # Compute the error
    sparse_error = Function(V)
    sparse_error.vector().add_local(+ sparse_solution.vector().get_local())
    sparse_error.vector().add_local(- exact_solution.vector().get_local())
    sparse_error.vector().apply("")
    sparse_error_norm = sparse_error.vector().inner(X*sparse_error.vector())
    sparse_error_dot = Function(V)
    sparse_error_dot.vector().add_local(+ sparse_solution_dot.vector().get_local())
    sparse_error_dot.vector().add_local(- exact_solution_dot.vector().get_local())
    sparse_error_dot.vector().apply("")
    sparse_error_dot_norm = sparse_error_dot.vector().inner(X*sparse_error_dot.vector())
    print("SparseTimeStepping error (" + callback_type + ", " + integrator_type + "):", sparse_error_norm, sparse_error_dot_norm)
    assert isclose(sparse_error_norm, 0., atol=1.e-4)
    assert isclose(sparse_error_dot_norm, 0., atol=1.e-4)
    return ((sparse_error_norm, sparse_error_dot_norm), V, dt, T, u, u_dot, g, r, j_u, j_u_dot, X, exact_solution_expression, exact_solution, exact_solution_dot)
コード例 #2
0
ファイル: test_time_stepping_1.py プロジェクト: ljnpu/RBniCS
def _test_time_stepping_1_dense(integrator_type, V, dt, monitor_dt, T, u,
                                u_dot, g, r, j_u, j_u_dot, X,
                                exact_solution_expression, exact_solution,
                                exact_solution_dot):
    from rbnics.backends.online.numpy import Function, Matrix, TimeStepping, Vector

    x_to_dof = dict(
        zip(V.tabulate_dof_coordinates().flatten(),
            V.dofmap().dofs()))
    dof_0 = x_to_dof[0.]
    dof_2pi = x_to_dof[2 * pi]
    min_dof_0_2pi = min(dof_0, dof_2pi)
    max_dof_0_2pi = max(dof_0, dof_2pi)

    # Define problem wrapper
    class ProblemWrapper(TimeDependentProblemWrapper):
        # Residual and jacobian functions, reordering resulting matrix and vector
        # such that dof_0 and dof_2pi are in the first two rows/cols,
        # because the dense time stepping solver has implicitly this assumption
        def residual_eval(self, t, solution, solution_dot):
            self._solution_from_dense_to_sparse(solution, u)
            self._solution_from_dense_to_sparse(solution_dot, u_dot)
            g.t = t
            residual_array = assemble(r).get_local()
            residual_array[[0, 1, min_dof_0_2pi,
                            max_dof_0_2pi]] = residual_array[[
                                min_dof_0_2pi, max_dof_0_2pi, 0, 1
                            ]]
            residual = Vector(*residual_array.shape)
            residual[:] = residual_array
            return residual

        def jacobian_eval(self, t, solution, solution_dot,
                          solution_dot_coefficient):
            self._solution_from_dense_to_sparse(solution, u)
            self._solution_from_dense_to_sparse(solution_dot, u_dot)
            jacobian_array = assemble(
                Constant(solution_dot_coefficient) * j_u_dot + j_u).array()
            jacobian_array[
                [0, 1, min_dof_0_2pi, max_dof_0_2pi], :] = jacobian_array[
                    [min_dof_0_2pi, max_dof_0_2pi, 0, 1], :]
            jacobian_array[:, [
                0, 1, min_dof_0_2pi, max_dof_0_2pi
            ]] = jacobian_array[:, [min_dof_0_2pi, max_dof_0_2pi, 0, 1]]
            jacobian = Matrix(*jacobian_array.shape)
            jacobian[:, :] = jacobian_array
            return jacobian

        # Define boundary condition
        def bc_eval(self, t):
            return (sin(t), sin(t))

        # Define initial condition
        def ic_eval(self):
            exact_solution_expression.t = 0.
            solution = Function(*exact_solution.vector().get_local().shape)
            solution.vector()[:] = project(exact_solution_expression,
                                           V).vector().get_local()
            solution_array = solution.vector()
            solution_array[[0, 1, min_dof_0_2pi,
                            max_dof_0_2pi]] = solution_array[[
                                min_dof_0_2pi, max_dof_0_2pi, 0, 1
                            ]]
            return solution

        # Define custom monitor to plot the solution
        def monitor(self, t, solution, solution_dot):
            assert isclose(round(t / monitor_dt), t / monitor_dt)
            if matplotlib.get_backend() != "agg":
                self._solution_from_dense_to_sparse(solution, u)
                self._solution_from_dense_to_sparse(solution_dot, u_dot)
                plt.subplot(1, 2, 1).clear()
                plot(u, title="u at t = " + str(t))
                plt.subplot(1, 2, 2).clear()
                plot(u_dot, title="u_dot at t = " + str(t))
                plt.show(block=False)
                plt.pause(DOLFIN_EPS)
            else:
                print("||u|| at t = " + str(t) + ": " +
                      str(monitor_norm(solution.vector())))
                print("||u_dot|| at t = " + str(t) + ": " +
                      str(monitor_norm(solution_dot.vector())))

        def _solution_from_dense_to_sparse(self, solution, u):
            solution_array = solution.vector()
            solution_array[[min_dof_0_2pi, max_dof_0_2pi, 0,
                            1]] = solution_array[[
                                0, 1, min_dof_0_2pi, max_dof_0_2pi
                            ]]
            u.vector().zero()
            u.vector().add_local(solution_array.__array__())
            u.vector().apply("")
            solution_array[[0, 1, min_dof_0_2pi,
                            max_dof_0_2pi]] = solution_array[[
                                min_dof_0_2pi, max_dof_0_2pi, 0, 1
                            ]]

    # Solve the time dependent problem
    problem_wrapper = ProblemWrapper()
    shape = exact_solution.vector().get_local().shape
    (solution, solution_dot) = (Function(*shape), Function(*shape))
    solver = TimeStepping(problem_wrapper, solution, solution_dot)
    solver.set_parameters({
        "initial_time": 0.0,
        "time_step_size": dt,
        "monitor": {
            "time_step_size": monitor_dt,
        },
        "final_time": T,
        "integrator_type": integrator_type,
        "problem_type": "linear",
        "report": True
    })
    solver.solve()

    # Compute the error at the final time
    error = Function(*exact_solution.vector().get_local().shape)
    error.vector()[:] = exact_solution.vector().get_local()
    solution_array = solution.vector()
    solution_array[[min_dof_0_2pi, max_dof_0_2pi, 0,
                    1]] = solution_array[[0, 1, min_dof_0_2pi, max_dof_0_2pi]]
    error.vector()[:] -= solution_array
    solution_array[[0, 1, min_dof_0_2pi, max_dof_0_2pi
                    ]] = solution_array[[min_dof_0_2pi, max_dof_0_2pi, 0, 1]]
    error_norm = dot(error.vector(), dot(X.array(), error.vector()))
    error_dot = Function(*exact_solution_dot.vector().get_local().shape)
    error_dot.vector()[:] = exact_solution_dot.vector().get_local()
    solution_dot_array = solution_dot.vector()
    solution_dot_array[[min_dof_0_2pi, max_dof_0_2pi, 0,
                        1]] = solution_dot_array[[
                            0, 1, min_dof_0_2pi, max_dof_0_2pi
                        ]]
    error_dot.vector()[:] -= solution_dot_array
    solution_dot_array[[0, 1, min_dof_0_2pi,
                        max_dof_0_2pi]] = solution_dot_array[[
                            min_dof_0_2pi, max_dof_0_2pi, 0, 1
                        ]]
    error_dot_norm = dot(error_dot.vector(), dot(X.array(),
                                                 error_dot.vector()))
    print("Dense error (" + integrator_type + "):", error_norm, error_dot_norm)
    assert isclose(error_norm, 0., atol=1.e-4)
    assert isclose(error_dot_norm, 0., atol=1.e-4)
    return (error_norm, error_dot_norm)