diff --git a/main.cpp b/main.cpp index db92772..beb98b3 100644 --- a/main.cpp +++ b/main.cpp @@ -15,19 +15,22 @@ void print_tensor(const Tensor3f &t3) { } int main() { - auto para = std::make_shared<top::CtrlPara>(); - para->penal=3; - para->max_loop=4; + para->max_loop=200; + para->volfrac=0.2; + para->penal=3.0; + para->r_min=1.5; double E = 1.0; double Poisson_ratio = 0.3; auto material = std::make_shared<SIM::Material>(E, Poisson_ratio); - auto mesh = std::make_shared<top::Mesh>(10, 200,10); + auto mesh = std::make_shared<top::Mesh>(20, 120,20); top::Top3d top3d(para, material, mesh); top::Boundary bdr(mesh); - auto l_bd=bdr.GetLeftBoundary(); - top3d.AddDBC(l_bd,{1,1,1}); - top3d.AddNBC(bdr.GetRightBottomMidPoint(),{0,0,-1}); + top3d.AddDBC(bdr.GetCornerPoint(0),{1,1,1}); + top3d.AddDBC(bdr.GetCornerPoint(1),{1,1,1}); + top3d.AddDBC(bdr.GetCornerPoint(2),{1,1,1}); + top3d.AddDBC(bdr.GetCornerPoint(3),{1,1,1}); + top3d.AddNBC(bdr.GetTopSurfaceCenter(),{0,0,-1}); top3d.TopOptMainLoop(); diff --git a/ref/top3d.pdf b/ref/top3d.pdf new file mode 100644 index 0000000..bc86fa9 Binary files /dev/null and b/ref/top3d.pdf differ diff --git a/src/Boundary.h b/src/Boundary.h index 68abc75..4261151 100644 --- a/src/Boundary.h +++ b/src/Boundary.h @@ -16,26 +16,61 @@ namespace top { } + Eigen::MatrixXi GetTopBoundary() { + Eigen::VectorXi x_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLx() + 1, 0, sp_mesh_->GetLx()); + Eigen::VectorXi y_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLy() + 1, 0, sp_mesh_->GetLy()); + Eigen::VectorXi z_sequence = Eigen::Vector<int, 1>(sp_mesh_->GetLz()); + return GetChosenCoords(x_sequence, y_sequence, z_sequence); + } + + Eigen::MatrixXi GetBottomBoundary() { + Eigen::VectorXi x_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLx() + 1, 0, sp_mesh_->GetLx()); + Eigen::VectorXi y_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLy() + 1, 0, sp_mesh_->GetLy()); + Eigen::VectorXi z_sequence = Eigen::Vector<int, 1>(0); + return GetChosenCoords(x_sequence, y_sequence, z_sequence); + } + Eigen::MatrixXi GetLeftBoundary() { Eigen::VectorXi x_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLx() + 1, 0, sp_mesh_->GetLx()); + Eigen::VectorXi y_sequence = Eigen::Vector<int, 1>(0); Eigen::VectorXi z_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLz() + 1, 0, sp_mesh_->GetLz()); - Eigen::MatrixXi bound_coords((sp_mesh_->GetLx() + 1) * (sp_mesh_->GetLz() + 1), 3); - bound_coords.col(1).setZero(); - bound_coords.col(0) = (x_sequence * Eigen::RowVectorXi::Ones(z_sequence.size())).reshaped(); - bound_coords.col(2) = (Eigen::VectorXi::Ones(x_sequence.size()) * z_sequence.transpose()).reshaped(); - return bound_coords; + return GetChosenCoords(x_sequence, y_sequence, z_sequence); } Eigen::MatrixXi GetRightBoundary() { Eigen::VectorXi x_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLx() + 1, 0, sp_mesh_->GetLx()); + Eigen::VectorXi y_sequence = Eigen::Vector<int, 1>(sp_mesh_->GetLy()); Eigen::VectorXi z_sequence = Eigen::VectorXi::LinSpaced(sp_mesh_->GetLz() + 1, 0, sp_mesh_->GetLz()); - Eigen::MatrixXi bound_coords((sp_mesh_->GetLx() + 1) * (sp_mesh_->GetLz() + 1), 3); - bound_coords.col(1).setConstant(sp_mesh_->GetLy()); - bound_coords.col(0) = (x_sequence * Eigen::RowVectorXi::Ones(z_sequence.size())).reshaped(); - bound_coords.col(2) = (Eigen::VectorXi::Ones(x_sequence.size()) * z_sequence.transpose()).reshaped(); - return bound_coords; + return GetChosenCoords(x_sequence, y_sequence, z_sequence); } + Eigen::MatrixXi GetTopSurfaceCenter(){ + Eigen::MatrixXi coord(1, 3); + coord << sp_mesh_->GetLx() / 2, sp_mesh_->GetLy() / 2,sp_mesh_->GetLz(); + return coord; + } + Eigen::MatrixXi GetCornerPoint(int i){ + bool is_top=i%4; + i%=4; + Eigen::MatrixXi coord(1,3); + int lx=sp_mesh_->GetLx(),ly=sp_mesh_->GetLy(),lz=sp_mesh_->GetLz(); + switch (i) { + case 0:coord<<0,0,0; + break; + case 1:coord<<lx,0,0; + break; + case 2:coord<<lx,ly,0; + break; + case 3:coord<<0,ly,0; + break; + default: + spdlog::debug("never arrive!"); + } + if(is_top){ + coord.col(2).setConstant(lz); + } + return coord; + } Eigen::MatrixXi GetRightBottomMidPoint() { int lx = sp_mesh_->GetLx(); int ly = sp_mesh_->GetLy(); @@ -50,7 +85,19 @@ namespace top { lx / 2 + 1, ly, 0; return bound_coords; + } + +// private: + Eigen::MatrixXi GetChosenCoords(const Eigen::VectorXi &x_sequence, const Eigen::VectorXi &y_sequence, + const Eigen::VectorXi &z_sequence) { + Eigen::MatrixXi chosen_coords(x_sequence.size() * y_sequence.size() * z_sequence.size(), 3); + chosen_coords.col(0) = x_sequence.replicate(y_sequence.size() * z_sequence.size(), 1); + chosen_coords.col(1) = y_sequence.transpose().replicate(x_sequence.size(), 1).reshaped().replicate( + z_sequence.size(), 1); + chosen_coords.col(2) = z_sequence.transpose().replicate(x_sequence.size() * y_sequence.size(), + 1).reshaped(); + return chosen_coords; } private: diff --git a/src/IrregularMesh.cpp b/src/IrregularMesh.cpp new file mode 100644 index 0000000..c04d07d --- /dev/null +++ b/src/IrregularMesh.cpp @@ -0,0 +1,8 @@ +// +// Created by cflin on 4/24/23. +// + +#include "IrregularMesh.h" + +namespace top { +} // top \ No newline at end of file diff --git a/src/IrregularMesh.h b/src/IrregularMesh.h new file mode 100644 index 0000000..1068c5b --- /dev/null +++ b/src/IrregularMesh.h @@ -0,0 +1,137 @@ +// +// Created by cflin on 4/24/23. +// + +#ifndef TOP3D_IRREGULARMESH_H +#define TOP3D_IRREGULARMESH_H + +#include "Mesh.h" + +namespace top { + struct ModelMesh { + Eigen::MatrixX3d points; + Eigen::MatrixXi surfaces; + }; + + class IrregularMesh : public Mesh { + public: + IrregularMesh(const ModelMesh &arbitrary_mesh) : Mesh() { + // get num_pixels + min_point_box_ = arbitrary_mesh.points.colwise().minCoeff(); + Eigen::Vector3d box_max_point = arbitrary_mesh.points.colwise().maxCoeff(); + Eigen::Vector3d box_len = box_max_point - min_point_box_; + const double percentage_of_min_len = 0.20; + len_pixel_ = box_len.minCoeff() * percentage_of_min_len; + Eigen::Vector3d d_num_pixels = box_len / len_pixel_; + Eigen::Vector3i num_pixels(std::ceil(d_num_pixels(0)), std::ceil(d_num_pixels(1)), + std::ceil(d_num_pixels(2))); + + lx_ = num_pixels(0); + ly_ = num_pixels(1); + lz_ = num_pixels(2); + num_node_ = (lx_ + 1) * (ly_ + 1) * (lz_ + 1); + num_ele_ = lx_ * ly_ * lz_; + + ten_ele_coord2ele_id = Tensor3i(lx_, ly_, lz_); + ten_node_coord2node_id.setConstant(-1); + ten_node_coord2node_id = Tensor3i(lx_ + 1, ly_ + 1, lz_ + 1); + ten_node_coord2node_id.setConstant(-1); + + auto EvaluateSDF = [](const Eigen::Vector3d point) { + Eigen::Vector3d center(1, 1, 1); + double r = 5; + return r - (point - center).norm(); + }; + auto GetWorldCoordByElementIdx = [&](const Eigen::Vector3i &ele_idx) { + Eigen::Vector3d local_coord = ele_idx.cast<double>(); + Eigen::Vector3d world_coord = ((local_coord.array() + 0.5) * len_pixel_).matrix() + min_point_box_; + return world_coord; + }; + auto Is_in_model = [&](const Eigen::Vector3i &ele_idx) { + return EvaluateSDF(GetWorldCoordByElementIdx(ele_idx)) >= 0; + }; + + static const Eigen::MatrixXi delta_coord = (Eigen::MatrixXi(8, 3) << + 0, 0, 0, + 1, 0, 0, + 1, 1, 0, + 0, 1, 0, + 0, 0, 1, + 1, 0, 1, + 1, 1, 1, + 0, 1, 1 + ).finished(); + // get num_pixel_ && fill pixel id + int cnt_pixel = 0; + for (int k = 0; k < lz_; ++k) { + for (int j = 0; j < ly_; ++j) { + for (int i = 0; i < lx_; ++i) { + if (Is_in_model({i, j, k})) { + ten_ele_coord2ele_id(i, j, k) = cnt_pixel++; + for (int di = 0; di < delta_coord.rows(); ++di) { + Eigen::Vector3i cur_delta_coord = delta_coord.row(di); + ten_node_coord2node_id(i + cur_delta_coord(0), j + cur_delta_coord(1), + k + cur_delta_coord(2)) = 1; + } + } + } + } + } + num_pixel_ = cnt_pixel; + // get_num_node_pixel && fill node_id + int cnt_node_pixel = 0; + for (int k = 0; k < lz_ + 1; ++k) { + for (int j = 0; j < ly_ + 1; ++j) { + for (int i = 0; i < lx_ + 1; ++i) { + if (ten_node_coord2node_id(i, j, k) == 1) { + ten_node_coord2node_id(i, j, k) = cnt_node_pixel++; + } + } + } + } + num_node_pixel_ = cnt_node_pixel; + // fill mat_ele_id2dofs_ + mat_ele_id2dofs_.resize(num_pixel_, NUM_NODES_EACH_ELE * 3); + for (int k = 0; k < lz_; ++k) { + for (int j = 0; j < ly_; ++j) { + for (int i = 0; i < lx_; ++i) { + int cur_ele_id = ten_ele_coord2ele_id(i, j, k); + if (cur_ele_id == -1) { + continue; + } + Eigen::MatrixXi world_node_coords = delta_coord.rowwise() + Eigen::RowVector3i(i, j, k); + assert(world_node_coords.rows() == 8 && world_node_coords.cols() == 3); + Eigen::Vector<int, 8> node_ids = ten_node_coord2node_id(world_node_coords); + for (int nodi = 0; nodi < 8; ++nodi) { + mat_ele_id2dofs_(cur_ele_id, {3 * nodi, 3 * nodi + 1, 3 * nodi + 2}) = Eigen::Vector3i( + 3 * node_ids(nodi), 3 * node_ids(nodi) + 1, 3 * node_ids(nodi) + 2); + } + } + } + } + + } + + int GetNumDofs() const override { + return num_node_pixel_ * 3; + } + + int GetNumEles() const override { + return num_pixel_; + } + + int GetNumNodes() const override { + return num_node_pixel_; + } + + private: + double len_pixel_; + double num_pixel_; + double num_node_pixel_; + Eigen::Vector3d min_point_box_; + + }; + +} // top + +#endif //TOP3D_IRREGULARMESH_H diff --git a/src/Mesh.h b/src/Mesh.h index b20498c..fa8c012 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -10,6 +10,7 @@ namespace top { class Mesh { public: + Mesh()=default; Mesh(int len_x, int len_y, int len_z) : lx_(len_x), ly_(len_y), lz_(len_z), num_node_((lx_ + 1) * (ly_ + 1) * (lz_ + 1)), num_ele_(lx_ * ly_ * lz_) { @@ -64,13 +65,13 @@ namespace top { return lz_; } - int GetNumDofs() const{ + virtual int GetNumDofs() const{ return num_node_*3; } - int GetNumEles()const{ + virtual int GetNumEles()const{ return num_ele_; } - int GetNumNodes()const{ + virtual int GetNumNodes()const{ return num_node_; } Eigen::MatrixXi GetEleId2DofsMap()const{ @@ -90,7 +91,7 @@ namespace top { return mat_ele_id2dofs_(ele_id,all); } - private: + protected: static const int NUM_NODES_EACH_ELE = 8; int lx_; int ly_; diff --git a/src/Top3d.h b/src/Top3d.h index 83c540c..73304a6 100644 --- a/src/Top3d.h +++ b/src/Top3d.h @@ -26,9 +26,9 @@ namespace top { double volfrac = 0.5; double penal = 1.0; int max_loop = 100; - int tol_x = 0.01; double r_min = 2.0; + double tol_x = 0.01; double E_factor = 1e-9; }; @@ -39,7 +39,8 @@ namespace top { ), sp_material_(sp_material), sp_mesh_(sp_mesh) { F_ = SpMat(sp_mesh_->GetNumDofs(), 1); K_ = SpMat(sp_mesh_->GetNumDofs(), sp_mesh_->GetNumDofs()); - + spdlog::info("sizeof K: {}",K_.rows()); + spdlog::info("start to precompute..."); Precompute(); } @@ -50,6 +51,7 @@ namespace top { if (directions[dir]) dofs_to_fixed_.insert(node_id_to_fix[i] * 3 + dir); } + auto ttt=dofs_to_fixed_; } void AddNBC(const Eigen::MatrixXi &NBC_coords, const Eigen::Vector3d &forces) { @@ -86,7 +88,6 @@ namespace top { #ifdef USE_SUITESPARSE Eigen::CholmodSupernodalLLT<Eigen::SparseMatrix<double>> solver; -// Eigen::CholmodSimplicialLDLT<Eigen::SparseMatrix<double>> solver; solver.compute(K_); Eigen::VectorXd U = solver.solve(F_); diff --git a/src/Util.h b/src/Util.h index 3bce920..8c8796f 100644 --- a/src/Util.h +++ b/src/Util.h @@ -17,7 +17,7 @@ #include <vtkFloatArray.h> #include <vtkStructuredGridWriter.h> #include <Eigen/Dense> - +#include <spdlog/spdlog.h> #include <iostream> namespace top { using Tensor3d=TensorWrapper<double,3>;