示例#1
0
//-----------------------------------------------------------------------------
double dolfin::assemble(const Form& a)
{
  if (a.rank() != 0)
  {
    dolfin_error("assemble.cpp",
                 "assemble form",
                 "Expecting a scalar form but rank is %d",
                 a.rank());
  }

  Scalar s;
  Assembler assembler;
  assembler.assemble(s, a);
  return s.get_scalar_value();
}
示例#2
0
  void test_assembly()
  {
    // Set some parameters
    parameters["reorder_dofs_serial"] = false;

    // Some parameters
    const std::size_t N = 4;
    const std::size_t n = 2;
    const double b1 = 1.0;
    const double b2 = 1.0;

    // Right-hand side
    class Source : public Expression
    {
    public:
      Source() : Expression(2) {}

      void eval(Array<double>& values, const Array<double>& x) const
      {
        values[0] = 2*DOLFIN_PI*sin(2*DOLFIN_PI*x[1])*
          (cos(2*DOLFIN_PI*x[0]) -
           2*DOLFIN_PI*DOLFIN_PI*cos(2*DOLFIN_PI*x[0]) +
           DOLFIN_PI*DOLFIN_PI);
        values[1] = 2*DOLFIN_PI*sin(2*DOLFIN_PI*x[0])*
          (cos(2*DOLFIN_PI*x[1]) +
           2*DOLFIN_PI*DOLFIN_PI*cos(2*DOLFIN_PI*x[1]) -
           DOLFIN_PI*DOLFIN_PI);
      }
    } source;

    // Subdomain for no-slip boundary
    class DirichletBoundary : public SubDomain
    {
      bool inside(const Array<double>& x, bool on_boundary) const
      {
        return on_boundary and
          (near(x[0], 0) || near(x[0], 1) ||
           near(x[1], 0) || near(x[1], 1));
      }
    } dirichlet_boundary;

    // Create meshes
    UnitSquareMesh mesh_0(N, N);
    const double c = 0.123123;
    RectangleMesh mesh_1(Point(0.5 - c, 0.5 - c), Point(0.5 + c, 0.5 + c), n, n);
    mesh_1.rotate(37, 2);

    // Create function spaces
    MultiMeshStokes2D::FunctionSpace W0(mesh_0);
    MultiMeshStokes2D::FunctionSpace W1(mesh_1);

    // Create forms
    MultiMeshStokes2D::BilinearForm a0(W0, W0);
    MultiMeshStokes2D::BilinearForm a1(W1, W1);
    MultiMeshStokes2D::LinearForm L0(W0);
    MultiMeshStokes2D::LinearForm L1(W1);
    MultiMeshStokes2D::Functional M0(mesh_0);
    MultiMeshStokes2D::Functional M1(mesh_1);

    // Build multimesh function space
    MultiMeshFunctionSpace W;
    W.parameters("multimesh")["quadrature_order"] = 3;
    W.add(W0);
    W.add(W1);
    W.build();

    // Create constants
    Constant beta_1(b1);
    Constant beta_2(b2);

    // Create solution function
    MultiMeshFunction w(W);

    // Set coefficients
    a0.w0 = beta_1;
    a1.w0 = beta_1;
    a0.w1 = beta_2;
    a1.w1 = beta_2;
    L0.w0 = source;
    L1.w0 = source;
    L0.w1 = beta_2;
    L1.w1 = beta_2;
    M0.w0 = *w.part(0);
    M1.w0 = *w.part(1);

    // Build multimesh forms
    MultiMeshForm a(W, W);
    MultiMeshForm L(W);
    MultiMeshForm M(W);
    a.add(a0);
    a.add(a1);
    L.add(L0);
    L.add(L1);
    M.add(M0);
    M.add(M1);
    a.build();
    L.build();
    M.build();

    // Create subspaces for boundary conditions
    MultiMeshSubSpace V(W, 0);
    MultiMeshSubSpace Q(W, 1);

    // Create boundary condition
    Constant zero(0, 0);
    MultiMeshDirichletBC bc(V, zero, dirichlet_boundary);

    // Assemble system matrix and right-hand side
    Matrix A;
    Vector b;
    MultiMeshAssembler assembler;
    assembler.assemble(A, a);
    assembler.assemble(b, L);

    // Apply boundary condition
    bc.apply(A, b);

    // Compute solutipon
    solve(A, *w.vector(), b);

    // Compute squared L2 norm of solution
    Scalar m;
    assembler.assemble(m, M);

    // Check value
    CPPUNIT_ASSERT_DOUBLES_EQUAL(2.217133856286212, m.get_scalar_value(), 1e-12);
  }