void test_multiple_meshes_interface_quadrature() { // // These three meshes are ok // UnitSquareMesh mesh_0(1, 1); // RectangleMesh mesh_1(Point(0.1, 0.1), Point(0.9, 0.9), 1, 1); // RectangleMesh mesh_2(Point(0.2, 0.2), Point(0.8, 0.8), 1, 1); // double exact_volume = 4*(0.9-0.1); // mesh0 and mesh1 // exact_volume += 4*(0.8-0.2); // mesh1 and mesh2 // UnitCubeMesh mesh_0(1, 2, 3); // BoxMesh mesh_1(Point(0.1, 0.1, 0.1), Point(0.9, 0.9, 0.9), 2,3,4); //2, 3, 4); // BoxMesh mesh_2(Point(-0.1, -0.1, -0.1), Point(0.7, 0.7, 0.7), 4, 3, 2); // BoxMesh mesh_3(Point(0.51, 0.51, 0.51), Point( 0.7, 0.7, 0.7), 1, 1, 1); //4, 3, 2); // BoxMesh mesh_4(Point(0.3, 0.3, 0.3), Point(0.7, 0.7, 0.7), 1, 1, 1); // double exact_volume = 0.8*0.8*6; // for mesh_0 and mesh_1 // exact_volume += 0.4*0.4*6; // for mesh_1 and mesh_4 UnitCubeMesh mesh_0(1, 1, 1); BoxMesh mesh_1(Point(0.1, 0.1, 0.1), Point(0.9, 0.9, 0.9), 1, 1, 1); BoxMesh mesh_2(Point(0.2, 0.2, 0.2), Point(0.8, 0.8, 0.8), 1, 1, 1); // BoxMesh mesh_3(Point(0.51, 0.51, 0.51), Point(0.7, 0.7, 0.7), 1, 1, 1); //4, 3, 2); // BoxMesh mesh_4(Point(0.3, 0.3, 0.3), Point(0.7, 0.7, 0.7), 1, 1, 1); double exact_volume = (0.9 - 0.1)*(0.9 - 0.1)*6; // for mesh_0 and mesh_1 exact_volume += (0.8 - 0.2)*(0.8 - 0.2)*6; // mesh_1 and mesh_2 // UnitCubeMesh mesh_0(1, 1, 1); // MeshEditor editor; // Mesh mesh_1; // editor.open(mesh_1, 3, 3); // editor.init_vertices(4); // editor.init_cells(1); // editor.add_vertex(0, Point(0.7, 0.1, -0.1)); // editor.add_vertex(1, Point(0.7, 0.3, -0.1)); // editor.add_vertex(2, Point(0.5, 0.1, -0.1)); // editor.add_vertex(3, Point(0.7, 0.1, 0.1)); // editor.add_cell(0, 0,1,2,3); // editor.close(); // Mesh mesh_2; // editor.open(mesh_2, 3,3); // editor.init_vertices(4); // editor.init_cells(1); // editor.add_vertex(0, Point(0.7, 0.1, -0.2)); // editor.add_vertex(1, Point(0.7, 0.3, -0.2)); // editor.add_vertex(2, Point(0.5, 0.1, -0.2)); // editor.add_vertex(3, Point(0.7, 0.1, 0.05)); // editor.add_cell(0, 0,1,2,3); // editor.close(); //double exact_volume = 0.8*0.8*6; // for mesh_0 and mesh_1 //exact_volume += 0.4*0.4*6; // for mesh_1 and mesh_4 // MeshEditor editor; // Mesh mesh_0; // editor.open(mesh_0, 2, 2); // editor.init_vertices(3); // editor.init_cells(1); // editor.add_vertex(0, Point(0.,0.)); // editor.add_vertex(1, Point(2.,0.)); // editor.add_vertex(2, Point(1.,2.)); // editor.add_cell(0, 0,1,2); // editor.close(); // Mesh mesh_1; // editor.open(mesh_1, 2, 2); // editor.init_vertices(3); // editor.init_cells(1); // editor.add_vertex(0, Point(0.,-0.5)); // editor.add_vertex(1, Point(2.,-0.5)); // editor.add_vertex(2, Point(1.,1.5)); // editor.add_cell(0, 0,1,2); // editor.close(); // Mesh mesh_2; // editor.open(mesh_2, 2, 2); // editor.init_vertices(3); // editor.init_cells(1); // editor.add_vertex(0, Point(0.,-1.)); // editor.add_vertex(1, Point(2.,-1.)); // editor.add_vertex(2, Point(1.,1.)); // editor.add_cell(0, 0,1,2); // editor.close(); // double exact_volume = 2*std::sqrt(0.75*0.75 + 1.5*1.5); // mesh_0 and mesh_1 // exact_volume += 2*std::sqrt(0.5*0.5 + 1*1); // mesh_0 and mesh_2 // exact_volume += 2*std::sqrt(0.75*0.75 + 1.5*1.5); // mesh_1and mesh_2 // double volume = 0; // // These three meshes are ok. // MeshEditor editor; // Mesh mesh_0; // editor.open(mesh_0, 2, 2); // editor.init_vertices(3); // editor.init_cells(1); // editor.add_vertex(0, Point(0.,0.)); // editor.add_vertex(1, Point(2.,0.)); // editor.add_vertex(2, Point(1.,2.)); // editor.add_cell(0, 0,1,2); // editor.close(); // Mesh mesh_1; // editor.open(mesh_1, 2, 2); // editor.init_vertices(3); // editor.init_cells(1); // editor.add_vertex(0, Point(1.5,-2.)); // editor.add_vertex(1, Point(4.,0.)); // editor.add_vertex(2, Point(1.5,2)); // editor.add_cell(0, 0,1,2); // editor.close(); // Mesh mesh_2; // editor.open(mesh_2, 2, 2); // editor.init_vertices(3); // editor.init_cells(1); // editor.add_vertex(0, Point(3.,0.5)); // editor.add_vertex(1, Point(-1.,0.5)); // editor.add_vertex(2, Point(1.,-1.5)); // editor.add_cell(0, 0,1,2); // editor.close(); // double exact_volume = (1.5-0.25) + (1-0.5); // mesh_0, mesh_1 and mesh_2 // exact_volume += (3-1.5) + std::sqrt(1.5*1.5 + 1.5*1.5); // mesh_1 and mesh_2 File("mesh_0.xml") << mesh_0; File("mesh_1.xml") << mesh_1; File("mesh_2.xml") << mesh_2; // Build the multimesh MultiMesh multimesh; multimesh.add(mesh_0); multimesh.add(mesh_1); multimesh.add(mesh_2); //multimesh.add(mesh_3); //multimesh.add(mesh_4); multimesh.build(); // Sum contribution from all parts std::cout << "\n\n Sum up\n\n"; double volume = 0; for (std::size_t part = 0; part < multimesh.num_parts(); part++) { std::cout << "% part " << part << '\n'; double part_volume = 0; const auto& quadrature_rules = multimesh.quadrature_rule_interface(part); // Get collision map const auto& cmap = multimesh.collision_map_cut_cells(part); for (auto it = cmap.begin(); it != cmap.end(); ++it) { const unsigned int cut_cell_index = it->first; // Iterate over cutting cells const auto& cutting_cells = it->second; for (auto jt = cutting_cells.begin(); jt != cutting_cells.end(); jt++) { //const std::size_t cutting_part = jt->first; //const std::size_t cutting_cell_index = jt->second; // Get quadrature rule for interface part defined by // intersection of the cut and cutting cells const std::size_t k = jt - cutting_cells.begin(); dolfin_assert(k < quadrature_rules.at(cut_cell_index).size()); const auto& qr = quadrature_rules.at(cut_cell_index)[k]; for (std::size_t j = 0; j < qr.second.size(); ++j) { volume += qr.second[j]; part_volume += qr.second[j]; } } } std::cout<<"part volume " << part_volume<<std::endl; } std::cout << "exact volume " << exact_volume<<'\n' << "volume " << volume<<std::endl; CPPUNIT_ASSERT_DOUBLES_EQUAL(exact_volume, volume, DOLFIN_EPS_LARGE); }
void test_multiple_meshes_quadrature() { set_log_level(DEBUG); // Create multimesh from three triangle meshes of the unit square // Many meshes, but not more than three overlap => this works UnitCubeMesh mesh_0(11, 12, 13); BoxMesh mesh_1(Point(0.1, 0.1, 0.1), Point(0.9, 0.9, 0.9), 13, 11, 12); BoxMesh mesh_2(Point(0.2, 0.2, 0.2), Point(0.95, 0.95, 0.8), 11, 13, 11); BoxMesh mesh_3(Point(0.94, 0.01, 0.01), Point(0.98, 0.99, 0.99), 1, 11, 11); BoxMesh mesh_4(Point(0.01, 0.01, 0.01), Point(0.02, 0.02, 0.02), 1, 1, 1); // // Completely nested 2D: can't do no more than three meshes // UnitSquareMesh mesh_0(1, 1); // RectangleMesh mesh_1(Point(0.1, 0.1), Point(0.9, 0.9, 1, 1); // RectangleMesh mesh_2(Point(0.2, 0.2), Point(0.8, 0.8, 1, 1); // RectangleMesh mesh_3(Point(0.3, 0.3), Point(0.7, 0.7, 1, 1); // RectangleMesh mesh_4(Point(0.4, 0.4), Point(0.6, 0.6, 1, 1); // // Completely nested 3D: can't do no more than three meshes // UnitCubeMesh mesh_0(2, 3, 4); // BoxMesh mesh_1(Point(0.1, 0.1, 0.1), Point(0.9, 0.9, 0.9), 4, 3, 2); // BoxMesh mesh_2(Point(0.2, 0.2, 0.2), Point(0.8, 0.8, 0.8), 3, 4, 3); // BoxMesh mesh_3(Point(0.8, 0.01, 0.01), Point(0.9, 0.99, 0.99), 4, 2, 3); // BoxMesh mesh_4(Point(0.01, 0.01, 0.01), Point(0.02, 0.02, 0.02), 1, 1, 1); // Build the multimesh MultiMesh multimesh; multimesh.add(mesh_0); multimesh.add(mesh_1); multimesh.add(mesh_2); multimesh.add(mesh_3); multimesh.add(mesh_4); multimesh.build(); // Exact volume is known const double exact_volume = 1; double volume = 0; // Sum contribution from all parts std::cout << "Sum contributions\n"; for (std::size_t part = 0; part < multimesh.num_parts(); part++) { std::cout << "% part " << part; double part_volume = 0; // Uncut cell volume given by function volume const auto uncut_cells = multimesh.uncut_cells(part); for (auto it = uncut_cells.begin(); it != uncut_cells.end(); ++it) { const Cell cell(*multimesh.part(part), *it); volume += cell.volume(); part_volume += cell.volume(); } std::cout << "\t uncut volume "<< part_volume<<' '; // Cut cell volume given by quadrature rule const auto& cut_cells = multimesh.cut_cells(part); for (auto it = cut_cells.begin(); it != cut_cells.end(); ++it) { const auto& qr = multimesh.quadrature_rule_cut_cell(part, *it); for (std::size_t i = 0; i < qr.second.size(); ++i) { volume += qr.second[i]; part_volume += qr.second[i]; } } std::cout << "\ttotal volume " << part_volume<< std::endl; } std::cout<<std::setprecision(13) << "exact volume " << exact_volume<<'\n' << "volume " << volume<<std::endl; CPPUNIT_ASSERT_DOUBLES_EQUAL(exact_volume, volume, DOLFIN_EPS_LARGE); }
// Compute solution for given mesh configuration void solve_poisson(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); // Build multimesh MultiMesh multimesh; multimesh.add(mesh_0); multimesh.add(mesh_1); multimesh.add(mesh_2); multimesh.build(); // Create function space MultiMeshPoisson::MultiMeshFunctionSpace V(multimesh); // Create forms MultiMeshPoisson::MultiMeshBilinearForm a(V, V); MultiMeshPoisson::MultiMeshLinearForm L(V); // Attach coefficients Source f; L.f = f; // Assemble linear system Matrix A; Vector b; assemble_multimesh(A, a); assemble_multimesh(b, L); // Apply boundary condition Constant zero(0); DirichletBoundary boundary; MultiMeshDirichletBC bc(V, zero, boundary); 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(); } }