diff --git a/README.md b/README.md index ff8856f..47e37c2 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,8 @@ There are several flags you can pass to the example binaries. These influence th | `--max_tri` | Prints a help message showing all of the options detailed here. | | `--bound_subdiv` | Defines the number of subdivisions along one edge of the cubic boundary. | | `--bound_len` | Defines the edge length of the cubic boundary of the vacuum region | +| `--boundary_type` | Defines the type of boundary generated. Set to either ``Cube`` or ``Bbox`` | +| `--scale_[x,y,z]` | If using the `Bbox` boundary type, use these options to specify the scaling factor used for each dimension. By default each dimension is given a scale factor of 1.2 (i.e. 120%) | | `--sideset_one_id` | For a coil problem, this option defines the ID of your first coil sideset that you want to be coplanar with the boundary. | | `--sideset_two_id` | For a coil problem, this option defines the ID of your second coil sideset that you want to be coplanar with the boundary. | diff --git a/VacuumMeshing/CMakeLists.txt b/VacuumMeshing/CMakeLists.txt index 747e3d8..2cdb339 100644 --- a/VacuumMeshing/CMakeLists.txt +++ b/VacuumMeshing/CMakeLists.txt @@ -5,16 +5,7 @@ option(LIBIGL_INSTALL "Enable installation of libigl targets" ON) # libigl module options option(LIBIGL_EMBREE "Build target igl::embree" ON) -option(LIBIGL_GLFW "Build target igl::glfw" OFF) -option(LIBIGL_IMGUI "Build target igl::imgui" OFF) -option(LIBIGL_OPENGL "Build target igl::opengl" OFF) -option(LIBIGL_PNG "Build target igl::png" OFF) -option(LIBIGL_PREDICATES "Build target igl::predicates" OFF) -option(LIBIGL_XML "Build target igl::xml" OFF) -option(LIBIGL_COPYLEFT_CGAL "Build target igl_copyleft::cgal" OFF) -option(LIBIGL_COPYLEFT_COMISO "Build target igl_copyleft::comiso" OFF) option(LIBIGL_COPYLEFT_CORE "Build target igl_copyleft::core" ON) -option(LIBIGL_COPYLEFT_CORK "Build target igl_copyleft::cork" OFF) option(LIBIGL_COPYLEFT_TETGEN "Build target igl_copyleft::tetgen" ON) option(LIBIGL_RESTRICTED_TRIANGLE "Build target igl_restricted::triangle" ON) diff --git a/VacuumMeshing/include/BoundaryGeneration/BoundaryGenerator.hpp b/VacuumMeshing/include/BoundaryGeneration/BoundaryGenerator.hpp index dec4750..37b7895 100644 --- a/VacuumMeshing/include/BoundaryGeneration/BoundaryGenerator.hpp +++ b/VacuumMeshing/include/BoundaryGeneration/BoundaryGenerator.hpp @@ -35,12 +35,31 @@ class BoundaryGenerator { virtual void addBoundary(double length, int subdivisions, std::string tri_flags); + + /** Method generates a rectangular mesh comprised of tri elements. + \c verts will be populated with the vertex data, \c elems will be populated + with the element connectivity data. \c x_dim and \c y_dim will allow the + user to change the length of the edges of the square. \c x_subdiv and \c y_subdiv will allow + you to set how many elements there should be per edge*/ + void genTriangulatedRect(Eigen::MatrixXd &rect_verts, + Eigen::MatrixXi &rect_elems, double x_dim, double y_dim, + int x_subdiv, int y_subdiv, std::string tri_flags); + + /** Method generates a rectangular boundary comprised of just edge elements, i.e. the perimeter of the rectangle. + \c verts will be populated with the vertex data, \c elems will be populated + with the element connectivity data. \c x_dim and \c y_dim will allow the + user to change the length of the edges of the square. \c x_subdiv and \c y_subdiv will allow + you to set how many elements there should be per edge*/ + void genRect(Eigen::MatrixXd &edge_verts, + Eigen::MatrixXi &edge_elems, double x_dim, double y_dim, + int x_subdiv, int y_subdiv); + /** Method generates a square boundary comprised of just edge elements. \c verts will be populated with the vertex data, \c elems will be populated with the element connectivity data. \c length and \c subdivisions allow the user to change the length of the edges of the square, as well as how many elements there should be per edge*/ - void genSquare(Eigen::MatrixXd &verts, Eigen::MatrixXi &elems, double length, + void genSquare(Eigen::MatrixXd &edge_verts, Eigen::MatrixXi &edge_elems, double length, int subdivisions); /** Method for combining two libigl meshes that you are SURE do NOT intersect @@ -61,10 +80,30 @@ class BoundaryGenerator { Eigen::MatrixXi &boundary_elements, double length, int subdivisions, std::string tri_flags); + /** Generates a cuboid boundary based off of the bounding box dimensions of the input mesh */ + void genBoundingBoxBoundary(Eigen::MatrixXd &boundary_vertices, + Eigen::MatrixXi &boundary_elements, + double scaling_x, double scaling_y, + double scaling_z, int subdivisions, + std::string tri_flags); + + + /** Function overload that accepts one scaling factor for all dimensions */ + void genBoundingBoxBoundary(Eigen::MatrixXd &boundary_vertices, + Eigen::MatrixXi &boundary_elements, + double scaling_factor, int subdivisions, + std::string tri_flags); + + void addBoundingBoxBoundary(double scaling_x, double scaling_y, double scaling_z, + int subdivisions, std::string tri_flags); + void translateMesh(Eigen::MatrixXd &verts, Eigen::Vector3d translationVector); void translateMesh(Eigen::MatrixXd &verts, std::vector &translationVector); + void getBoundaryDimensions(double scaling_factor); + + void getBoundaryDimensions(double scaling_x, double scaling_y, double scaling_z); /**Checks to see if the boundary will overlap with component mesh.*/ void checkBoundary(const double &length); @@ -84,5 +123,7 @@ class BoundaryGenerator { std::vector centroid_; + double bb_x_dim, bb_y_dim, bb_z_dim; + private: }; diff --git a/VacuumMeshing/include/BoundaryGeneration/CoilBoundaryGenerator.hpp b/VacuumMeshing/include/BoundaryGeneration/CoilBoundaryGenerator.hpp index b410a54..637c55e 100644 --- a/VacuumMeshing/include/BoundaryGeneration/CoilBoundaryGenerator.hpp +++ b/VacuumMeshing/include/BoundaryGeneration/CoilBoundaryGenerator.hpp @@ -15,6 +15,12 @@ class CoilBoundaryGenerator : public BoundaryGenerator { virtual void addBoundary(const double length, const int subdivisions, const std::string tri_flags) override; + void addCoilBoundingBoxBoundary(const double scaling_x, + const double scaling_y, + const double scaling_z, + const int subdivisions, + const std::string tri_flags); + /** Method to generate the boundary for a coil. A method exists specifically for coils, as often the boundary needs to be coplanar with some coil "in" and "out" sidesets. This method will generate the correct boundary for a @@ -24,6 +30,14 @@ vertices and faces (vertice connectivity data)*/ void generateCoilBoundary(const double length, const int subdivisions, const std::string tri_flags); + + + void generateCoilBoundingBoxBoundary(const double scaling_x, + const double scaling_y, + const double scaling_z, + const int subdivisions, + const std::string tri_flags); + /** Method takes in an Eigen::Matrix "basis_matrix" by reference. This matrix will be populated with the basis vectors for a cartesian coordinate system. The new systems "XY" plane is defined by 3 points contained within @@ -60,6 +74,13 @@ tri mesh will be stored.*/ Eigen::MatrixXi &tri_elems, double length, int subdivisions, std::string tri_flags); + + void generateCoilFaceBound( + const Eigen::MatrixXd &verts, const Eigen::MatrixXi &elems, + const Eigen::MatrixXd &holes, Eigen::MatrixXd &tri_vertices, + Eigen::MatrixXi &tri_elems, double x_dim, double y_dim, int x_subdiv, int y_subdiv, + std::string tri_flags); + /** Method for generating the face of the cubic boundary that is coplanar with the coil sidesets. Here V and F are the vertices and faces(connectivity data) for the input mesh, which is probably composed of 2D edge elements. @@ -76,6 +97,13 @@ tri mesh will be stored.*/ void genSidesetBounds(Eigen::MatrixXd &verts, Eigen::MatrixXi &elems, const double length, const int subdivisions); + void genSidesetBounds(Eigen::MatrixXd &verts, + Eigen::MatrixXi &elems, + const double x_dim, + const double y_dim, + const int x_subdiv, + const int y_subdiv); + void genSidesetBounds(libMesh::Mesh &sideset_mesh, libMesh::Mesh &remaining_boundary); @@ -100,6 +128,10 @@ tri mesh will be stored.*/ Eigen::MatrixXi &triElems, double length, int subdivisions, std::string tri_flags); + void genRemainingFiveBoundaryFaces(Eigen::MatrixXd &tri_vertices, Eigen::MatrixXi &tri_elems, + double x_dim, double y_dim, double z_dim, + int x_subdiv, int y_subdiv, int z_subdiv, std::string tri_flags); + /** For our coil problem, to generate the part of the boundary that is coplanar with the coil sidesets correctly*/ void getCoplanarSeedPoints(libMesh::Mesh &mesh, Eigen::MatrixXd &seed_points); @@ -108,4 +140,6 @@ tri mesh will be stored.*/ private: const int coil_sideset_one_id; const int coil_sideset_two_id; + + double coil_sideset_elevation_; }; \ No newline at end of file diff --git a/VacuumMeshing/include/Utils/parseFlags.hpp b/VacuumMeshing/include/Utils/parseFlags.hpp index 01ec217..b1e68a8 100644 --- a/VacuumMeshing/include/Utils/parseFlags.hpp +++ b/VacuumMeshing/include/Utils/parseFlags.hpp @@ -34,9 +34,23 @@ struct inputFlags { int coil_sideset_two_id = 2; + // Scaling factors for bounding box generation, default is 120% scaling on all axes + double scale_factor_x = 1.2; + double scale_factor_y = 1.2; + double scale_factor_z = 1.2; + void setSwitches(); // Method to print help message void helpMessage(); + + enum BoundaryType{ + CUBE, + BOUNDING_BOX + }; + + BoundaryType bound_type = CUBE; + + std::unordered_map boundMap{{"Cube", CUBE}, {"BBox", BOUNDING_BOX}}; }; // Function that will return an inputFlags struct from which we can access CLI diff --git a/VacuumMeshing/include/VacuumGeneration/VacuumGenerator.hpp b/VacuumMeshing/include/VacuumGeneration/VacuumGenerator.hpp index fba0674..a9e6125 100644 --- a/VacuumMeshing/include/VacuumGeneration/VacuumGenerator.hpp +++ b/VacuumMeshing/include/VacuumGeneration/VacuumGenerator.hpp @@ -1,6 +1,6 @@ #pragma once -#include "Utils/libmeshConversions.hpp" +#include "Utils/utils.hpp" #include "libmesh/mesh.h" #include #include @@ -56,12 +56,15 @@ class VacuumGenerator { // Get seeds Eigen::MatrixXd getSeeds(libMesh::Mesh mesh) const; + // Get tolerance for mesh merging + void setMergeToleranceAuto(); + protected: // References to mesh objects passed in via constructor libMesh::Mesh &mesh_, &boundary_mesh_, &surface_mesh_, &vacuum_mesh_; // Tolerance value used for rTree merging - double merge_tolerance_ = 1e-07; + double mesh_merge_tolerance_; double seeding_tolerance_ = 1e-07; const std::multimap* surface_face_map_; diff --git a/VacuumMeshing/src/BoundaryGeneration/BoundaryGenerator.cpp b/VacuumMeshing/src/BoundaryGeneration/BoundaryGenerator.cpp index 9d59700..3267ab8 100644 --- a/VacuumMeshing/src/BoundaryGeneration/BoundaryGenerator.cpp +++ b/VacuumMeshing/src/BoundaryGeneration/BoundaryGenerator.cpp @@ -38,6 +38,31 @@ void BoundaryGenerator::addBoundary(double length, int subdivisions, combineMeshes(mesh_merge_tolerance_, boundary_mesh_, surface_mesh_); } +void BoundaryGenerator::addBoundingBoxBoundary(double scaling_x, double scaling_y, double scaling_z, int subdivisions, + std::string tri_flags) { + + Eigen::MatrixXd boundary_vertices; + Eigen::MatrixXi boundary_elements; + + // Generate boundary mesh + try { + genBoundingBoxBoundary(boundary_vertices, boundary_elements, scaling_x, scaling_y, scaling_z, subdivisions, tri_flags); + } catch (const std::invalid_argument &ex) { + std::terminate(); + } + + // Turn IGL mesh into libmesh Mesh + IGLToLibMesh(boundary_mesh_, boundary_vertices, boundary_elements); + + // If unspecified, get merge tolerance + if (mesh_merge_tolerance_ == 0) { + setMergeToleranceAuto(); + } + + // Combine IGL mesh with boundary + combineMeshes(mesh_merge_tolerance_, boundary_mesh_, surface_mesh_); +} + void BoundaryGenerator::genBoundary(Eigen::MatrixXd &boundary_vertices, Eigen::MatrixXi &boundary_elements, double length, int subdivisions, @@ -56,11 +81,11 @@ void BoundaryGenerator::genBoundary(Eigen::MatrixXd &boundary_vertices, Eigen::MatrixXd seeds; // Create a square from 1st order edge elements - genSquare(square_boundary_verts, square_boundary_elems, length, subdivisions); + genSquare(square_verts, square_elems, length, subdivisions); // Triangulate the square that we just created - igl::triangle::triangulate(square_boundary_verts, square_boundary_elems, seeds, tri_flags, square_verts, - square_elems); + // igl::triangle::triangulate(square_boundary_verts, square_boundary_elems, seeds, tri_flags, square_verts, + // square_elems); // Rotation matrices to rotate elements Eigen::Matrix3d x_rot_base; @@ -78,8 +103,6 @@ void BoundaryGenerator::genBoundary(Eigen::MatrixXd &boundary_vertices, // them later std::vector rot_matrices = {x_rot_base, y_rot_base}; - - // Vector to store faces of cubic boundary std::vector new_faces(6, square_verts); @@ -114,54 +137,270 @@ void BoundaryGenerator::genBoundary(Eigen::MatrixXd &boundary_vertices, } } -void BoundaryGenerator::genSquare(Eigen::MatrixXd &verts, - Eigen::MatrixXi &elems, double length, - int subdivisions) { +void BoundaryGenerator::genBoundingBoxBoundary(Eigen::MatrixXd &boundary_vertices, + Eigen::MatrixXi &boundary_elements, + double scaling_x, double scaling_y, + double scaling_z, int subdivisions, + std::string tri_flags) { + + // Get dimensions for the boundary based off of a scaled version of the mesh bounding box + getBoundaryDimensions(scaling_x, scaling_y, scaling_z); + + // Eigen matrices to store vertices and elements for all faces of bounding box + Eigen::MatrixXd xy_verts, xz_verts, yz_verts; + Eigen::MatrixXi xy_elems, xz_elems, yz_elems; + Eigen::MatrixXd seeds; + + // Get number of elements along each axis + double x_subdiv, y_subdiv, z_subdiv; + x_subdiv = subdivisions; + y_subdiv = (bb_y_dim/bb_x_dim) * x_subdiv; + z_subdiv = (bb_z_dim/bb_x_dim) * x_subdiv; + + // Create a square from 1st order edge elements + genTriangulatedRect(xy_verts, xy_elems, bb_x_dim, bb_y_dim, x_subdiv, y_subdiv, tri_flags); + genTriangulatedRect(xz_verts, xz_elems, bb_x_dim, bb_z_dim, x_subdiv, z_subdiv, tri_flags); + genTriangulatedRect(yz_verts, yz_elems, bb_z_dim, bb_y_dim, z_subdiv, y_subdiv, tri_flags); + + // Rotation matrices to rotate elements + Eigen::Matrix3d x_rot_base; + x_rot_base << 1, 0, 0, 0, 0, -1, 0, 1, 0; + + Eigen::Matrix3d y_rot_base; + y_rot_base << 0, 0, -1, 0, 1, 0, 1, 0, 0; + + // Add a column of zeroes as our "z" coord to make this square exist in 3D + xy_verts.conservativeResize(xy_verts.rows(), xy_verts.cols() + 1); + xy_verts.col(xy_verts.cols() - 1) = + Eigen::VectorXd::Zero(xy_verts.rows()); + + xz_verts.conservativeResize(xz_verts.rows(), xz_verts.cols() + 1); + xz_verts.col(xz_verts.cols() - 1) = + Eigen::VectorXd::Zero(xz_verts.rows()); + + yz_verts.conservativeResize(yz_verts.rows(), yz_verts.cols() + 1); + yz_verts.col(yz_verts.cols() - 1) = + Eigen::VectorXd::Zero(yz_verts.rows()); + + // Create vector to hold our rotation matrices, this will make it easier to loop over + // them later + std::vector rot_matrices = {x_rot_base, y_rot_base}; + + // Vector to store faces of cubic boundary + std::vector new_faces = {xy_verts, xy_verts, xz_verts, yz_verts, xz_verts, yz_verts}; + + // Loop over 4 of the 6 squares and rotate them. We only loop + // over 4 because 2 of them are already orientated correctly for our cubic + // boundary + for (int i = 2; i < 6; i++) { + new_faces[i] *= rot_matrices[(i % 2)]; + } + + // Currently every square face of our cubic boundary has its centre at {0, 0, + // 0}, these need to be translated to make a cube + translateMesh(new_faces[0], {0, 0, bb_z_dim / 2}); + translateMesh(new_faces[1], {0, 0, -bb_z_dim / 2}); + translateMesh(new_faces[2], {0, bb_y_dim / 2, 0}); + translateMesh(new_faces[3], {bb_x_dim / 2, 0, 0}); + translateMesh(new_faces[4], {0, -bb_y_dim / 2, 0}); + translateMesh(new_faces[5], {-bb_x_dim / 2, 0, 0}); + + + for(auto &face: new_faces) + { + // Translate vertices so that the centre of the boundary is the centre of the mesh bounding box + translateMesh(face, centroid_); + } + // Eigen::MatrixXi square_elems_2 = square_elems; + + std::vector elements = {&xy_elems, &xy_elems, &xz_elems, &yz_elems, &xz_elems, &yz_elems}; + // Combine the 6 square meshes to create the cubic boundary, using the rTree + // to avoid having any duplicate nodes + for (int i = 0; i < 6; i++) { + combineMeshes(boundary_face_merge_tolerance_, boundary_vertices, boundary_elements, + new_faces[i], *elements[i]); + } +} + +void BoundaryGenerator::genBoundingBoxBoundary(Eigen::MatrixXd &boundary_vertices, + Eigen::MatrixXi &boundary_elements, + double scaling_factor, int subdivisions, + std::string tri_flags) +{ + genBoundingBoxBoundary(boundary_vertices, + boundary_elements, + scaling_factor, scaling_factor, scaling_factor, + subdivisions, tri_flags); +} + +void BoundaryGenerator::genRect(Eigen::MatrixXd &boundary_verts, + Eigen::MatrixXi &boundary_elems, double x_dim, double y_dim, + int x_subdiv, int y_subdiv) { + + // Calculate the number of subdivisions for the longer side of the rectangle + int total_nodes = (2 * x_subdiv) + (2 * y_subdiv); // Resize eigen matrices to correct size - verts = Eigen::MatrixXd(4 * subdivisions, 2); - elems = Eigen::MatrixXi(4 * subdivisions, 2); + boundary_verts = Eigen::MatrixXd(total_nodes, 2); + boundary_elems = Eigen::MatrixXi(total_nodes, 2); + // Eigen::MatrixXd boundary_verts(total_nodes, 2); + // Eigen::MatrixXi boundary_elems(total_nodes, 2); + + // edge_verts. // - double increment = (double)(length / subdivisions); + double increment_x = (double)(x_dim / x_subdiv); + double increment_y = (double)(y_dim / y_subdiv); // Use offset so that the square mesh is symmetric about the x and y axes - double offset = length / 2; + double offset_x = x_dim / 2; + double offset_y = y_dim / 2; // Place all the nodes long int node_id = 0; - for (int i = 0; i <= subdivisions; i++) { - verts.row(node_id) << -offset + (i * increment), -offset; + for (int i = 0; i <= x_subdiv; i++) { + boundary_verts.row(node_id) << -offset_x + (i * increment_x), -offset_y; node_id++; } // All the other for loops start at 1 and not 0, this prevents creating a // duplicate node - for (int i = 1; i <= subdivisions; i++) { - verts.row(node_id) << offset, (i * increment) - offset; + for (int i = 1; i <= y_subdiv; i++) { + boundary_verts.row(node_id) << offset_x, (i * increment_y) - offset_y; node_id++; } - for (int i = 1; i <= subdivisions; i++) { - verts.row(node_id) << offset - (i * increment), offset; + for (int i = 1; i <= x_subdiv; i++) { + boundary_verts.row(node_id) << offset_x - (i * increment_x), offset_y; node_id++; } - // Last loop has to start at 1 and end at (subdivisions - 1), + // Last loop has to start at 1 and end at (x_subdiv - 1), // to avoid duplicating the starting node - for (int i = 1; i <= subdivisions - 1; i++) { - verts.row(node_id) << -offset, offset - (i * increment); + for (int i = 1; i <= y_subdiv - 1; i++) { + boundary_verts.row(node_id) << -offset_x, offset_y - (i * increment_y); node_id++; } // Loop over all elements, and assign them the correct nodes - for (int elem_id = 0; elem_id < (4 * subdivisions) - 1; elem_id++) { - elems(elem_id, 0) = elem_id; - elems(elem_id, 1) = elem_id + 1; + for (int elem_id = 0; elem_id < total_nodes - 1; elem_id++) { + boundary_elems(elem_id, 0) = elem_id; + boundary_elems(elem_id, 1) = elem_id + 1; } - elems(((4 * subdivisions) - 1), 0) = 0; - elems(((4 * subdivisions) - 1), 1) = (4 * subdivisions) - 1; + boundary_elems((total_nodes - 1), 0) = 0; + boundary_elems((total_nodes - 1), 1) = total_nodes - 1; +} + +void BoundaryGenerator::genTriangulatedRect(Eigen::MatrixXd &square_verts, + Eigen::MatrixXi &square_elems, double x_dim, double y_dim, + int x_subdiv, int y_subdiv, std::string tri_flags) { + + // Calculate the number of subdivisions for the longer side of the rectangle + int total_nodes = (2 * x_subdiv) + (2 * y_subdiv); + + // Resize eigen matrices to correct size + Eigen::MatrixXd boundary_verts(total_nodes, 2); + Eigen::MatrixXi boundary_elems(total_nodes, 2); + + genRect(boundary_verts, boundary_elems, x_dim, y_dim, x_subdiv, y_subdiv); + // // + // double increment_x = (double)(x_dim / x_subdiv); + // double increment_y = (double)(y_dim / y_subdiv); + + // // Use offset so that the square mesh is symmetric about the x and y axes + // double offset_x = x_dim / 2; + // double offset_y = y_dim / 2; + + // // Place all the nodes + // long int node_id = 0; + // for (int i = 0; i <= x_subdiv; i++) { + // boundary_verts.row(node_id) << -offset_x + (i * increment_x), -offset_y; + // node_id++; + // } + + // // All the other for loops start at 1 and not 0, this prevents creating a + // // duplicate node + // for (int i = 1; i <= y_subdiv; i++) { + // boundary_verts.row(node_id) << offset_x, (i * increment_y) - offset_y; + // node_id++; + // } + + // for (int i = 1; i <= x_subdiv; i++) { + // boundary_verts.row(node_id) << offset_x - (i * increment_x), offset_y; + // node_id++; + // } + + // // Last loop has to start at 1 and end at (x_subdiv - 1), + // // to avoid duplicating the starting node + // for (int i = 1; i <= y_subdiv - 1; i++) { + // boundary_verts.row(node_id) << -offset_x, offset_y - (i * increment_y); + // node_id++; + // } + + // // Loop over all elements, and assign them the correct nodes + // for (int elem_id = 0; elem_id < total_nodes - 1; elem_id++) { + // boundary_elems(elem_id, 0) = elem_id; + // boundary_elems(elem_id, 1) = elem_id + 1; + // } + + // boundary_elems((total_nodes - 1), 0) = 0; + // boundary_elems((total_nodes - 1), 1) = total_nodes - 1; + + Eigen::MatrixXd seeds; + igl::triangle::triangulate(boundary_verts, boundary_elems, seeds, + tri_flags, square_verts, square_elems); +} + +void BoundaryGenerator::genSquare(Eigen::MatrixXd &edge_verts, + Eigen::MatrixXi &edge_elems, double length, + int subdivisions) { + + genRect(edge_verts, edge_elems, length, length, subdivisions, subdivisions); + // Resize eigen matrices to correct size + // verts = Eigen::MatrixXd(4 * subdivisions, 2); + // elems = Eigen::MatrixXi(4 * subdivisions, 2); + + // + // double increment = (double)(length / subdivisions); + + // // Use offset so that the square mesh is symmetric about the x and y axes + // double offset = length / 2; + + // // Place all the nodes + // long int node_id = 0; + // for (int i = 0; i <= subdivisions; i++) { + // verts.row(node_id) << -offset + (i * increment), -offset; + // node_id++; + // } + + // // All the other for loops start at 1 and not 0, this prevents creating a + // // duplicate node + // for (int i = 1; i <= subdivisions; i++) { + // verts.row(node_id) << offset, (i * increment) - offset; + // node_id++; + // } + + // for (int i = 1; i <= subdivisions; i++) { + // verts.row(node_id) << offset - (i * increment), offset; + // node_id++; + // } + + // // Last loop has to start at 1 and end at (subdivisions - 1), + // // to avoid duplicating the starting node + // for (int i = 1; i <= subdivisions - 1; i++) { + // verts.row(node_id) << -offset, offset - (i * increment); + // node_id++; + // } + + // // Loop over all elements, and assign them the correct nodes + // for (int elem_id = 0; elem_id < (4 * subdivisions) - 1; elem_id++) { + // elems(elem_id, 0) = elem_id; + // elems(elem_id, 1) = elem_id + 1; + // } + + // elems(((4 * subdivisions) - 1), 0) = 0; + // elems(((4 * subdivisions) - 1), 1) = (4 * subdivisions) - 1; } // Method for combining IGL meshes that we know DO NOT OVERLAP. If you are not @@ -233,6 +472,28 @@ void BoundaryGenerator::checkBoundary(const double &length) { } } +void BoundaryGenerator::getBoundaryDimensions(double scaling_x, double scaling_y, double scaling_z) { + + // If the scaling factor is less than 1 just throw, the mesh will definitely not work + if((scaling_x < 1) || (scaling_y < 1) || (scaling_z < 1)) + { + throw std::invalid_argument("Cannot have a scaling factor < 1 for vacuum boundary, there will be overlaps."); + } + + libMesh::BoundingBox bbox = + libMesh::MeshTools::create_nodal_bounding_box(mesh_); + libMesh::Point point = (bbox.max() - bbox.min()); + + bb_x_dim = point(0) * scaling_x; + bb_y_dim = point(1) * scaling_y; + bb_z_dim = point(2) * scaling_z; + + libMesh::Point libmesh_centroid = bbox.min() + (point/2); + centroid_[0] = libmesh_centroid(0); + centroid_[1] = libmesh_centroid(1); + centroid_[2] = libmesh_centroid(2); +} + void BoundaryGenerator::setMergeToleranceAuto() { VacuumMesher::ClosestPairFinder closestPairBoundary(boundary_mesh_); VacuumMesher::ClosestPairFinder closestPairSkin(surface_mesh_); diff --git a/VacuumMeshing/src/BoundaryGeneration/CoilBoundaryGenerator.cpp b/VacuumMeshing/src/BoundaryGeneration/CoilBoundaryGenerator.cpp index 50ef6bc..062a2f8 100644 --- a/VacuumMeshing/src/BoundaryGeneration/CoilBoundaryGenerator.cpp +++ b/VacuumMeshing/src/BoundaryGeneration/CoilBoundaryGenerator.cpp @@ -33,20 +33,40 @@ void CoilBoundaryGenerator::addBoundary(const double length, combineMeshes(mesh_merge_tolerance_, boundary_mesh_, surface_mesh_); } +void CoilBoundaryGenerator::addCoilBoundingBoxBoundary(const double scaling_x, + const double scaling_y, + const double scaling_z, + const int subdivisions, + const std::string tri_flags) { + + // generate the boundary and store it in boundary_mesh_ + generateCoilBoundingBoxBoundary(scaling_x, scaling_y, scaling_z, subdivisions, tri_flags); + + if (mesh_merge_tolerance_ == 0) { + setMergeToleranceAuto(); + std::cout << "Mesh merge tolerance used: " << mesh_merge_tolerance_ + << std::endl; + } + // Combine the boundary mesh with the surface mesh to create a mesh ready for + // tetrahedralisation + combineMeshes(mesh_merge_tolerance_, boundary_mesh_, surface_mesh_); +} + + void CoilBoundaryGenerator::generateCoilBoundary(const double length, const int subdivisions, const std::string tri_flags) { // Libmesh mesh_ that stores only sideset data libMesh::Mesh sideset_mesh(mesh_.comm()); - libMesh::Mesh sideset_mesh_skinned(mesh_.comm()); + libMesh::Mesh sideset_mesh_skin(mesh_.comm()); - // Generate sideset mesh_ (uses default argument for sideset names) + // Generate sideset_mesh_ (uses default argument for sideset names) genSidesetMesh(mesh_, sideset_mesh); // Use a SurfaceMeshGenerator to "skin" the mesh of the sidesets. This results // in a mesh of edge elements - SurfaceMeshGenerator sidesetSkinner(sideset_mesh, sideset_mesh_skinned); + SurfaceMeshGenerator sidesetSkinner(sideset_mesh, sideset_mesh_skin); sidesetSkinner.getSurface(); // Create Eigen 3x3 matrix to store 3 points from the co-planar sidesets, that @@ -76,7 +96,7 @@ void CoilBoundaryGenerator::generateCoilBoundary(const double length, Eigen::MatrixXi sideset_element_verts, cube_element_verts; // Convert the sideset mesh_ to - libMeshToIGL(sideset_mesh_skinned, sideset_vertices, sideset_element_verts); + libMeshToIGL(sideset_mesh_skin, sideset_vertices, sideset_element_verts); // Do a change of basis on the mesh changeMeshBasis(sideset_vertices, origin, basis_matrix); @@ -111,6 +131,118 @@ void CoilBoundaryGenerator::generateCoilBoundary(const double length, IGLToLibMesh(boundary_mesh_, cube_vertices, cube_element_verts); } +void CoilBoundaryGenerator::generateCoilBoundingBoxBoundary(const double scaling_x, + const double scaling_y, + const double scaling_z, + const int subdivisions, + const std::string tri_flags) { + + + + // Libmesh mesh_ that stores only sideset data + libMesh::Mesh sideset_mesh(mesh_.comm()); + libMesh::Mesh sideset_mesh_skin(mesh_.comm()); + + // Generate sideset_mesh_ (uses default argument for sideset names) + genSidesetMesh(mesh_, sideset_mesh); + + // Use a SurfaceMeshGenerator to "skin" the mesh of the sidesets. This results + // in a mesh of edge elements + SurfaceMeshGenerator sidesetSkinner(sideset_mesh, sideset_mesh_skin); + sidesetSkinner.getSurface(); + + // Create Eigen 3x3 matrix to store 3 points from the co-planar sidesets, that + // will be used to define the plane that they sit on + Eigen::Matrix3d plane_points; + + // Populate plane points matrix with the nodes belonging to an element on + // the sidesets + for (int row_id = 0; row_id < 3; row_id++) { + auto &node = sideset_mesh.elem_ref(0).node_ref(row_id); + plane_points.row(row_id) << node(0), node(1), node(2); + } + + // Eigen 3x3 Matrix that will store the basis vectors of our transformed + // cartesian system + Eigen::Matrix3d basis_matrix; + + // Keep same origin + Eigen::Vector3d origin = Eigen::Vector3d::Zero(); + + // Generate basis matrix from 3 points that define a plane + getBasisMatrix(basis_matrix, plane_points); + + // Eigen objects to store + Eigen::MatrixXd sideset_skin_vertices, cube_vertices; + Eigen::MatrixXi sideset_skin_elements, cube_elements; + + // Convert the sideset mesh_ to eigen representation + libMeshToIGL(sideset_mesh_skin, sideset_skin_vertices, sideset_skin_elements); + + + // Define seed points matrix + Eigen::MatrixXd seed_points(2, 3); + + // Get the seed points of the coplanar coil boundaries + getCoplanarSeedPoints(mesh_, seed_points); + + // Perform temporary change of basis on libmesh representation of mesh_, to get bounding box dimensions + changeMeshBasis(mesh_, origin, basis_matrix); + + // Get dimensions for the boundary based off of a scaled version of the mesh_ bounding box + getBoundaryDimensions(scaling_x, scaling_y, scaling_z); + + // Change mesh_ back to original basis + changeMeshBasis(mesh_, origin, Eigen::Matrix3d::Identity(), origin, basis_matrix); + + Eigen::Vector3d centroid_eigen = {centroid_[0], centroid_[1], centroid_[2]}; + Eigen::Vector3d centroid_eigen_no_z = {centroid_[0], centroid_[1], 0}; + + // Perform change of basis on eigen representation of the sideset_skin_mesh + changeMeshBasis(sideset_skin_vertices, origin, basis_matrix); + translateMesh(sideset_skin_vertices, -centroid_eigen_no_z); + + // + coil_sideset_elevation_ = sideset_skin_vertices(0, 2); + + // Get number of elements along each axis + double x_subdiv, y_subdiv, z_subdiv; + x_subdiv = subdivisions; + y_subdiv = (bb_y_dim/bb_x_dim) * x_subdiv; + z_subdiv = (bb_z_dim/bb_x_dim) * x_subdiv; + + + + std::vector centroid_no_z = {centroid_[0], centroid_[1], 0}; + std::cout << seed_points << std::endl; + + // Transform seed points into new coordinate system + for (int i = 0; i < seed_points.rows(); i++) { + Eigen::Vector3d point(seed_points.row(i)); + seed_points.row(i) = calculateLocalCoords(point, origin, basis_matrix); + } + + translateMesh(seed_points, -centroid_eigen); + std::cout << seed_points << std::endl; + + // Generates the face of the boundary that is coplanar with the coil sidesets + // (the special boundary face) + std::cout << bb_x_dim << std::endl; + generateCoilFaceBound(sideset_skin_vertices, sideset_skin_elements, seed_points, + cube_vertices, cube_elements, bb_x_dim, bb_y_dim, x_subdiv, y_subdiv, + tri_flags); + + // Generates the 5 other faces of the cubic boundary + genRemainingFiveBoundaryFaces(cube_vertices, cube_elements, bb_x_dim, bb_y_dim, bb_z_dim, x_subdiv, y_subdiv, z_subdiv, tri_flags); + + // Change back to original basis + changeMeshBasis(cube_vertices, {0, 0, 0}, Eigen::Matrix3d::Identity(), origin, + basis_matrix); + + // Convert our IGL mesh back to libMesh + IGLToLibMesh(boundary_mesh_, cube_vertices, cube_elements); +} + bool CoilBoundaryGenerator::getBasisMatrix( Eigen::Matrix3d &basis_matrix, const Eigen::Matrix3d &plane_points) { @@ -168,6 +300,32 @@ void CoilBoundaryGenerator::generateCoilFaceBound( Eigen::VectorXd::Zero(tri_vertices.rows()); } +void CoilBoundaryGenerator::generateCoilFaceBound( + const Eigen::MatrixXd &verts, const Eigen::MatrixXi &elems, + const Eigen::MatrixXd &holes, Eigen::MatrixXd &tri_vertices, + Eigen::MatrixXi &tri_elems, double x_dim, double y_dim, int x_subdiv, int y_subdiv, + std::string tri_flags) { + + // + Eigen::MatrixXd holes2D = holes.block(0, 0, 2, 2); + Eigen::MatrixXd verts2D = verts.block(0, 0, verts.rows(), 2); + Eigen::MatrixXi elems2D = elems; + + // Generate a border around the skinned sideset, which is then used to define + // space for triangulation + genSidesetBounds(verts2D, elems2D, x_dim, y_dim, x_subdiv, y_subdiv); + + // Perform Delauny triangulation + igl::triangle::triangulate(verts2D, elems2D, holes2D, tri_flags, tri_vertices, + tri_elems); + + // Resize triangle vertices matrix to have 3 cols instead of 2 (2D -> 3D), set + // all z coords to 0 + tri_vertices.conservativeResize(tri_vertices.rows(), tri_vertices.cols() + 1); + tri_vertices.col(tri_vertices.cols() - 1) = + Eigen::VectorXd::Zero(tri_vertices.rows()); +} + void CoilBoundaryGenerator::generateCoilFaceBound( libMesh::Mesh &mesh, libMesh::Mesh &output_mesh, libMesh::Mesh &remaining_boundary, Eigen::MatrixXd &holes, @@ -213,6 +371,20 @@ void CoilBoundaryGenerator::genSidesetBounds(Eigen::MatrixXd &verts, combineIGLMeshes(verts, elems, square_verts, square_elems); } +void CoilBoundaryGenerator::genSidesetBounds(Eigen::MatrixXd &verts, + Eigen::MatrixXi &elems, + const double x_dim, + const double y_dim, + const int x_subdiv, + const int y_subdiv) { + Eigen::MatrixXd edge_verts; + Eigen::MatrixXi edge_elems; + + genRect(edge_verts, edge_elems, x_dim, y_dim, x_subdiv, y_subdiv); + + combineIGLMeshes(verts, elems, edge_verts, edge_elems); +} + void CoilBoundaryGenerator::genSidesetBounds( libMesh::Mesh &sideset_mesh, libMesh::Mesh &boundary_without_coilside_face) { @@ -262,10 +434,9 @@ void CoilBoundaryGenerator::changeMeshBasis(libMesh::Mesh &input_mesh, const Eigen::Matrix3d &new_basis, const Eigen::Vector3d &old_origin, const Eigen::Matrix3d &old_basis) { - libMesh::Mesh mesh_copy(input_mesh); - input_mesh.clear(); - for (auto &node : mesh_copy.node_ptr_range()) { + // Change node positions to new basis + for (auto &node : input_mesh.node_ptr_range()) { // Eigen::Vector to store node coords Eigen::Vector3d point, new_point; @@ -285,15 +456,7 @@ void CoilBoundaryGenerator::changeMeshBasis(libMesh::Mesh &input_mesh, libMesh::Point xyz(pnt[0], pnt[1], pnt[2]); // std::cout << pnt[0] << " " << pnt[1] << " " << pnt[2] << std::endl; - input_mesh.add_point(xyz, node->id()); - } - - for (auto &elem : mesh_copy.element_ptr_range()) { - libMesh::Elem *new_elem = libMesh::Elem::build(elem->type()).release(); - for (int j = 0; j < elem->n_nodes(); j++) { - new_elem->set_node(j) = input_mesh.node_ptr(elem->node_ref(j).id()); - } - input_mesh.add_elem(new_elem); + *node = xyz; } input_mesh.prepare_for_use(); } @@ -318,6 +481,79 @@ void CoilBoundaryGenerator::changeMeshBasis(Eigen::MatrixXd &vertices, } } +void CoilBoundaryGenerator::genRemainingFiveBoundaryFaces(Eigen::MatrixXd &tri_vertices, Eigen::MatrixXi &tri_elems, + double x_dim, double y_dim, double z_dim, + int x_subdiv, int y_subdiv, int z_subdiv, std::string tri_flags) { + + Eigen::MatrixXd xy_verts; + Eigen::MatrixXd xz_verts; + Eigen::MatrixXd yz_verts; + + Eigen::MatrixXi xy_elems; + Eigen::MatrixXi xz_elems; + Eigen::MatrixXi yz_elems; + + // tri_vertices(4 * subdivisions, 2); + // tri_elems(4 * subdivisions, 3); + + Eigen::MatrixXd seeds; + + genTriangulatedRect(xy_verts, xy_elems, x_dim, y_dim, x_subdiv, y_subdiv, tri_flags); + genTriangulatedRect(xz_verts, xz_elems, x_dim, z_dim, x_subdiv, z_subdiv, tri_flags); + genTriangulatedRect(yz_verts, yz_elems, z_dim, y_dim, z_subdiv, y_subdiv, tri_flags); + + // Rotational matrices to rotate elements + Eigen::Matrix3d x_rot_base; + x_rot_base << 1, 0, 0, 0, 0, -1, 0, 1, 0; + + Eigen::Matrix3d y_rot_base; + y_rot_base << 0, 0, -1, 0, 1, 0, 1, 0, 0; + + + // Add a column of zeroes as our "z" coord to make this square exist in 3D + xy_verts.conservativeResize(xy_verts.rows(), xy_verts.cols() + 1); + xy_verts.col(xy_verts.cols() - 1) = + Eigen::VectorXd::Zero(xy_verts.rows()); + + xz_verts.conservativeResize(xz_verts.rows(), xz_verts.cols() + 1); + xz_verts.col(xz_verts.cols() - 1) = + Eigen::VectorXd::Zero(xz_verts.rows()); + + yz_verts.conservativeResize(yz_verts.rows(), yz_verts.cols() + 1); + yz_verts.col(yz_verts.cols() - 1) = + Eigen::VectorXd::Zero(yz_verts.rows()); + + // Define our rotation matrices + std::vector new_faces = {xy_verts, xz_verts, yz_verts, xz_verts, yz_verts}; + std::vector elements = {xy_elems, xz_elems, yz_elems, xz_elems, yz_elems}; + + new_faces[1] *= x_rot_base; + new_faces[2] *= y_rot_base; + new_faces[3] *= x_rot_base; + new_faces[4] *= y_rot_base; + + translateMesh(new_faces[0], {0, 0, z_dim / 2}); + translateMesh(new_faces[1], {0, y_dim / 2, 0}); + translateMesh(new_faces[2], {x_dim / 2, 0, 0}); + translateMesh(new_faces[3], {0, -y_dim / 2, 0}); + translateMesh(new_faces[4], {-x_dim / 2, 0, 0}); + + std::vector centroid_no_z = {centroid_[0], centroid_[1], 0}; + + translateMesh(new_faces[0], {0, 0, z_dim / 2}); + translateMesh(new_faces[1], {0, 0, z_dim / 2}); + translateMesh(new_faces[2], {0, 0, z_dim / 2}); + translateMesh(new_faces[3], {0, 0, z_dim / 2}); + translateMesh(new_faces[4], {0, 0, z_dim / 2}); + + for (int i = 0; i < 5; i++) { + combineMeshes(boundary_face_merge_tolerance_, tri_vertices, tri_elems, + new_faces[i], elements[i]); + } + translateMesh(tri_vertices, centroid_no_z); + translateMesh(tri_vertices, {0, 0, coil_sideset_elevation_}); +} + void CoilBoundaryGenerator::genRemainingFiveBoundaryFaces( Eigen::MatrixXd &tri_vertices, Eigen::MatrixXi &tri_elems, double length, int subdivisions, std::string tri_flags) { diff --git a/VacuumMeshing/src/Utils/parseFlags.cpp b/VacuumMeshing/src/Utils/parseFlags.cpp index 53d65a0..8cdd5f8 100644 --- a/VacuumMeshing/src/Utils/parseFlags.cpp +++ b/VacuumMeshing/src/Utils/parseFlags.cpp @@ -41,6 +41,11 @@ const std::unordered_map OneArgs{ s.boundSubd = std::stoi(arg); }}, + {"--boundary_type", + [](inputFlags &s, const std::string &arg) { + s.bound_type = s.boundMap[arg]; + }}, + {"--bound_len", [](inputFlags &s, const std::string &arg) { s.boundLen = std::stod(arg); @@ -53,14 +58,27 @@ const std::unordered_map OneArgs{ {"--sideset_two_id", [](inputFlags &s, const std::string &arg) { s.coil_sideset_two_id = std::stoi(arg); - }}}; + }}, + + {"--scale_x", [](inputFlags &s, const std::string &arg) { + s.scale_factor_x = std::stod(arg); + }}, + + {"--scale_y", [](inputFlags &s, const std::string &arg) { + s.scale_factor_y = std::stod(arg); + }}, + + {"--scale_z", [](inputFlags &s, const std::string &arg) { + s.scale_factor_z = std::stod(arg); + }} +}; inputFlags parse_settings(int argc, const char *argv[]) { // inputFlags object we will return inputFlags settings; - // Start at 1 because arg 0 is the exe name + // Start loop at 1 because arg 0 is the exe name for (int i = 1; i < argc; i++) { std::string opt = argv[i]; // Check if this is a noArg @@ -78,6 +96,15 @@ inputFlags parse_settings(int argc, const char *argv[]) { throw std::runtime_error{"missing param after " + opt}; } + if(opt == "--boundary_type") + { + if((argv[i] != std::string("Cube")) && (argv[i] != std::string("BBox"))) + { + std::cout << argv[i] << std::endl; + throw std::runtime_error{"Please input a compatible boundary type, \"Cube\" or \"BBox\""}; + } + } + // An argument was recieved, use it in settings k->second(settings, argv[i]); } @@ -146,5 +173,9 @@ void inputFlags::helpMessage() { "boundary" << std::endl << "--bound_len Set the length of one edge of the boundary\n" + << std::endl + << "--boundary_type Set the scaling factor for each dimension when using bounding box boundaries\n" + << std::endl + << "--scale_[x,y,z] Set the scaling factor for each dimension when using bounding box boundaries\n" << std::endl; } \ No newline at end of file diff --git a/VacuumMeshing/src/VacuumGeneration/VacuumGenerator.cpp b/VacuumMeshing/src/VacuumGeneration/VacuumGenerator.cpp index f20f54d..09ad858 100644 --- a/VacuumMeshing/src/VacuumGeneration/VacuumGenerator.cpp +++ b/VacuumMeshing/src/VacuumGeneration/VacuumGenerator.cpp @@ -11,6 +11,7 @@ VacuumGenerator::VacuumGenerator( // surface_face_map_ = // std::make_shared>( // surface_face_map); + } VacuumGenerator::~VacuumGenerator(){}; @@ -20,17 +21,16 @@ void VacuumGenerator::generateVacuumMesh(const std::string tet_settings) { // They are needed so that the tetrahedralisation methods know where to not // generate tets Eigen::MatrixXd seed_points(getSeeds(surface_mesh_)); - // Eigen::MatrixXd seed_points; - // std::cout << seed_points << std::endl; // Create the mesh of the vacuumRegion tetrahedraliseVacuumRegion(seed_points, tet_settings); + setMergeToleranceAuto(); // Temporary mesh, so that we don't have to edit the original libMesh::Mesh temp(mesh_); // combine - combineMeshes(merge_tolerance_, temp, vacuum_mesh_, *surface_face_map_); + combineMeshes(mesh_merge_tolerance_, temp, vacuum_mesh_, *surface_face_map_); vacuum_mesh_.clear(); vacuum_mesh_ = libMesh::Mesh(temp); } @@ -42,7 +42,6 @@ void VacuumGenerator::tetrahedraliseVacuumRegion( Eigen::MatrixXd V; Eigen::MatrixXi F; libMeshToIGL(boundary_mesh_, V, F); - boundary_mesh_.write("boundary_test.e"); // Eigen data structures needed for tetrahedralize method to be run Eigen::MatrixXd R; @@ -58,7 +57,6 @@ void VacuumGenerator::tetrahedraliseVacuumRegion( TT, TF, TR, TN, PT, FT, num_regions); IGLToLibMesh(vacuum_mesh_, TV, TT); - vacuum_mesh_.write("vacuum_test.e"); } void VacuumGenerator::tetrahedraliseVacuumRegion( @@ -138,4 +136,15 @@ Eigen::MatrixXd VacuumGenerator::getSeeds(const libMesh::Mesh mesh) const { } return seed_points; +} + +void VacuumGenerator::setMergeToleranceAuto() +{ + VacuumMesher::ClosestPairFinder closestPairMesh(mesh_); + VacuumMesher::ClosestPairFinder closestPairVac(vacuum_mesh_); + + mesh_merge_tolerance_ = std::min(closestPairVac.closestPairMagnitude(), + closestPairMesh.closestPairMagnitude()); + mesh_merge_tolerance_ /= 10; + std::cout << "Merge tolerance set for vacuum mesh merging: Tolerance = " << mesh_merge_tolerance_ << std::endl; } \ No newline at end of file diff --git a/bin/boundary.cpp b/bin/boundary.cpp index 05d9ac5..06ab93b 100644 --- a/bin/boundary.cpp +++ b/bin/boundary.cpp @@ -30,9 +30,24 @@ int main(int argc, const char **argv) { // Skin mesh surfMeshGen.getSurface(); + // Add boundary to skinned mesh - boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), - flags.triSettings); + switch (flags.bound_type) + { + case inputFlags::BoundaryType::CUBE: + boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), + flags.triSettings); + break; + + case inputFlags::BoundaryType::BOUNDING_BOX: + boundMeshGen.addCoilBoundingBoxBoundary(flags.scale_factor_x, flags.scale_factor_y, flags.scale_factor_z, flags.boundSubd.value(), + flags.triSettings); + break; + + default: + break; + } + // Write output mesh boundary_mesh.write(flags.outfile.value()); diff --git a/bin/coil_boundary.cpp b/bin/coil_boundary.cpp index 8347674..e4997e7 100644 --- a/bin/coil_boundary.cpp +++ b/bin/coil_boundary.cpp @@ -33,9 +33,24 @@ int main(int argc, const char **argv) { // Skin mesh surfMeshGen.getSurface(); + // Add boundary to skinned mesh - boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), - flags.triSettings); + switch (flags.bound_type) + { + case inputFlags::BoundaryType::CUBE: + boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), + flags.triSettings); + break; + + case inputFlags::BoundaryType::BOUNDING_BOX: + boundMeshGen.addCoilBoundingBoxBoundary(flags.scale_factor_x, flags.scale_factor_y, flags.scale_factor_z, flags.boundSubd.value(), + flags.triSettings); + break; + + default: + break; + } + // Write output mesh boundary_mesh.write(flags.outfile.value()); diff --git a/bin/coil_vacuum.cpp b/bin/coil_vacuum.cpp index 417a162..155015b 100644 --- a/bin/coil_vacuum.cpp +++ b/bin/coil_vacuum.cpp @@ -28,17 +28,33 @@ int main(int argc, const char **argv) { // Instantiate all mesh generators SurfaceMeshGenerator surfMeshGen(mesh, surface_mesh); - CoilBoundaryGenerator boundMeshGen(mesh, surface_mesh, boundary_mesh); + CoilBoundaryGenerator boundMeshGen(mesh, surface_mesh, boundary_mesh, flags.coil_sideset_one_id, flags.coil_sideset_two_id); VacuumGenerator vacGenner(mesh, surface_mesh, boundary_mesh, vacuum_mesh, surfMeshGen.getSurfaceMap()); // Skin mesh surfMeshGen.getSurface(); + // Add boundary to skinned mesh - boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), - flags.triSettings); + switch (flags.bound_type) + { + case inputFlags::BoundaryType::CUBE: + boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), + flags.triSettings); + break; + + case inputFlags::BoundaryType::BOUNDING_BOX: + boundMeshGen.addCoilBoundingBoxBoundary(flags.scale_factor_x, flags.scale_factor_y, flags.scale_factor_z, flags.boundSubd.value(), + flags.triSettings); + break; + + default: + break; + } + // Generate vacuum region vacGenner.generateVacuumMesh(flags.tetSettings); + // Write output mesh vacuum_mesh.write(flags.outfile.value()); diff --git a/bin/vacuum.cpp b/bin/vacuum.cpp index f22c912..6697371 100644 --- a/bin/vacuum.cpp +++ b/bin/vacuum.cpp @@ -34,9 +34,23 @@ int main(int argc, const char **argv) { // Skin mesh surfMeshGen.getSurface(); - // Add boundary to skinned mesh - boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), - flags.triSettings); + + // Add boundary to skinned mesh + switch (flags.bound_type) + { + case inputFlags::BoundaryType::CUBE: + boundMeshGen.addBoundary(flags.boundLen.value(), flags.boundSubd.value(), + flags.triSettings); + break; + + case inputFlags::BoundaryType::BOUNDING_BOX: + boundMeshGen.addBoundingBoxBoundary(flags.scale_factor_x, flags.scale_factor_y, flags.scale_factor_z, flags.boundSubd.value(), + flags.triSettings); + break; + + default: + break; + } // Generate vacuum region vacGenner.generateVacuumMesh(flags.tetSettings); // Write output mesh