//----------------------------------------------------------------------------- void dolfin::assemble_multimesh(GenericTensor& A, const MultiMeshForm& a) { MultiMeshAssembler assembler; assembler.assemble(A, a); }
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); }
// Compute solution for given mesh configuration void solve(double t, double x1, double y1, double x2, double y2, bool plot_solution, File& u0_file, File& u1_file, File& u2_file) { // Create meshes double r = 0.5; RectangleMesh mesh_0(Point(-r, -r), Point(r, r), 16, 16); RectangleMesh mesh_1(Point(x1 - r, y1 - r), Point(x1 + r, y1 + r), 8, 8); RectangleMesh mesh_2(Point(x2 - r, y2 - r), Point(x2 + r, y2 + r), 8, 8); mesh_1.rotate(70*t); mesh_2.rotate(-70*t); // Create function spaces MultiMeshPoisson::FunctionSpace V0(mesh_0); MultiMeshPoisson::FunctionSpace V1(mesh_1); MultiMeshPoisson::FunctionSpace V2(mesh_2); // FIXME: Some of this stuff may be wrapped or automated later to // avoid needing to explicitly call add() and build() // Create forms MultiMeshPoisson::BilinearForm a0(V0, V0); MultiMeshPoisson::BilinearForm a1(V1, V1); MultiMeshPoisson::BilinearForm a2(V2, V2); MultiMeshPoisson::LinearForm L0(V0); MultiMeshPoisson::LinearForm L1(V1); MultiMeshPoisson::LinearForm L2(V2); // Build multimesh function space MultiMeshFunctionSpace V; V.parameters("multimesh")["quadrature_order"] = 2; V.add(V0); V.add(V1); V.add(V2); V.build(); // Set coefficients Source f; L0.f = f; L1.f = f; L2.f = f; // Build multimesh forms MultiMeshForm a(V, V); MultiMeshForm L(V); a.add(a0); a.add(a1); a.add(a2); L.add(L0); L.add(L1); L.add(L2); a.build(); L.build(); // Create boundary condition Constant zero(0); DirichletBoundary boundary; MultiMeshDirichletBC bc(V, zero, boundary); // Assemble linear system Matrix A; Vector b; MultiMeshAssembler assembler; assembler.assemble(A, a); assembler.assemble(b, L); // Apply boundary condition bc.apply(A, b); // Compute solution MultiMeshFunction u(V); solve(A, *u.vector(), b); // Save to file u0_file << *u.part(0); u1_file << *u.part(1); u2_file << *u.part(2); // Plot solution (last time) if (plot_solution) { plot(V.multimesh()); plot(u.part(0), "u_0"); plot(u.part(1), "u_1"); plot(u.part(2), "u_2"); interactive(); } }