You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.7 KiB
190 lines
6.7 KiB
|
|
|
|
#include "physical_domain.h"
|
|
|
|
#include <igl/write_triangle_mesh.h>
|
|
|
|
#include "sha-base-framework/frame.h"
|
|
#include "sha-io-foundation/data_io.h"
|
|
#include "sha-io-foundation/mesh_io.h"
|
|
|
|
namespace da::sha {
|
|
PhysicalDomain::PhysicalDomain(const MatMesh3 &mesh,
|
|
const std::vector<Eigen::Matrix<double, 2, 3>> &p_NBCRelBBox,
|
|
const std::vector<Eigen::Vector3d> &p_NBCVal,
|
|
const std::vector<Eigen::Matrix<double, 2, 3>> &p_DBCRelBBox,
|
|
const std::vector<Eigen::Vector3d> &p_DBCVal)
|
|
: NBCRelBBox(p_NBCRelBBox),
|
|
NBCVal(p_NBCVal),
|
|
DBCRelBBox(p_DBCRelBBox),
|
|
DBCVal(p_DBCVal),
|
|
mesh_(mesh) {
|
|
Assert(mesh.mat_coordinates.cols() == 3);
|
|
Assert(mesh.mat_faces.cols() == 3);
|
|
|
|
numV = (int)mesh.mat_coordinates.rows();
|
|
numF = (int)mesh.mat_faces.rows();
|
|
V1.resize(numV, 3);
|
|
|
|
bbox.row(0) = mesh.mat_coordinates.colwise().minCoeff();
|
|
bbox.row(1) = mesh.mat_coordinates.colwise().maxCoeff();
|
|
lenBBox = bbox.row(1) - bbox.row(0);
|
|
|
|
for (int triI = 0; triI < numF; ++triI) {
|
|
Tri.emplace_back(Triangle(mesh.mat_coordinates(
|
|
{mesh.mat_faces(triI, 0), mesh.mat_faces(triI, 1), mesh.mat_faces(triI, 2)}, Eigen::all)));
|
|
}
|
|
|
|
igl::fast_winding_number(mesh.mat_coordinates, mesh.mat_faces, 2, fwn_bvh);
|
|
|
|
InitializeBoundaryConditions();
|
|
|
|
spdlog::info("physical domain constructed" + std::to_string(numV) + " points, " +
|
|
std::to_string(numF) + " triangles");
|
|
}
|
|
|
|
void PhysicalDomain::Update() {
|
|
// update bbox
|
|
bbox.row(0) = mesh_.mat_coordinates.colwise().minCoeff();
|
|
bbox.row(1) = mesh_.mat_coordinates.colwise().maxCoeff();
|
|
lenBBox = bbox.row(1) - bbox.row(0);
|
|
|
|
// update Triangle
|
|
for (int triI = 0; triI < numF; ++triI) {
|
|
Tri[triI].Update(
|
|
mesh_.mat_coordinates({mesh_.mat_coordinates(triI, 0), mesh_.mat_coordinates(triI, 1),
|
|
mesh_.mat_coordinates(triI, 2)},
|
|
Eigen::all));
|
|
}
|
|
|
|
// update fwn_bvh
|
|
igl::fast_winding_number(mesh_.mat_coordinates, mesh_.mat_faces, 2, fwn_bvh);
|
|
}
|
|
|
|
void PhysicalDomain::GetDomainID(const Eigen::MatrixXd &Q, Eigen::VectorXi &domainID) const {
|
|
Assert(Q.cols() == 3);
|
|
// winding number bigger than val will be seen inside physical domain, otherwise outside
|
|
double val = 0.5;
|
|
|
|
Eigen::VectorXd W;
|
|
igl::fast_winding_number(fwn_bvh, 2, Q, W);
|
|
Assert(W.rows() == Q.rows());
|
|
|
|
domainID = (W.array() > val).cast<int>();
|
|
}
|
|
|
|
void PhysicalDomain::InitializeBoundaryConditions() {
|
|
nNBC = 0;
|
|
int num = (int)NBCRelBBox.size();
|
|
NBCBBox.resize(num);
|
|
|
|
for (int i = 0; i < num; ++i) {
|
|
NBCBBox[i].row(0) = bbox.row(0) + (lenBBox.array() * NBCRelBBox[i].row(0).array()).matrix();
|
|
NBCBBox[i].row(1) = bbox.row(0) + (lenBBox.array() * NBCRelBBox[i].row(1).array()).matrix();
|
|
}
|
|
// log::info("hhhhhhh");
|
|
// log::info("num V: {}", numV);
|
|
// log::info("num: {}", num);
|
|
// log::info("mat_coordinates: {} x {}", mesh.mat_coordinates.rows(),
|
|
// mesh.mat_coordinates.cols()); log::info("NBCBBox: {}", NBCBBox.size());
|
|
for (int vI = 0; vI < numV; ++vI) {
|
|
for (int i = 0; i < num; ++i) {
|
|
if (mesh_.mat_coordinates(vI, 0) >= NBCBBox[i](0, 0) &&
|
|
mesh_.mat_coordinates(vI, 0) <= NBCBBox[i](1, 0) &&
|
|
mesh_.mat_coordinates(vI, 1) >= NBCBBox[i](0, 1) &&
|
|
mesh_.mat_coordinates(vI, 1) <= NBCBBox[i](1, 1) &&
|
|
mesh_.mat_coordinates(vI, 2) >= NBCBBox[i](0, 2) &&
|
|
mesh_.mat_coordinates(vI, 2) <= NBCBBox[i](1, 2)) {
|
|
NBC.emplace_back(std::make_pair(mesh_.mat_coordinates.row(vI), NBCVal[i]));
|
|
++nNBC;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
nDBC = 0;
|
|
num = (int)DBCRelBBox.size();
|
|
DBCBBox.resize(num);
|
|
|
|
for (int i = 0; i < num; ++i) {
|
|
DBCBBox[i].row(0) = bbox.row(0) + (lenBBox.array() * DBCRelBBox[i].row(0).array()).matrix();
|
|
DBCBBox[i].row(1) = bbox.row(0) + (lenBBox.array() * DBCRelBBox[i].row(1).array()).matrix();
|
|
}
|
|
|
|
for (int triI = 0; triI < numF; ++triI) {
|
|
const Eigen::RowVector3d &v1 = mesh_.mat_coordinates.row(mesh_.mat_faces(triI, 0));
|
|
const Eigen::RowVector3d &v2 = mesh_.mat_coordinates.row(mesh_.mat_faces(triI, 1));
|
|
const Eigen::RowVector3d &v3 = mesh_.mat_coordinates.row(mesh_.mat_faces(triI, 2));
|
|
for (int i = 0; i < num; ++i) {
|
|
if (v1(0) >= DBCBBox[i](0, 0) && v1(0) <= DBCBBox[i](1, 0) && v1(1) >= DBCBBox[i](0, 1) &&
|
|
v1(1) <= DBCBBox[i](1, 1) && v1(2) >= DBCBBox[i](0, 2) && v1(2) <= DBCBBox[i](1, 2) &&
|
|
v2(0) >= DBCBBox[i](0, 0) && v2(0) <= DBCBBox[i](1, 0) && v2(1) >= DBCBBox[i](0, 1) &&
|
|
v2(1) <= DBCBBox[i](1, 1) && v2(2) >= DBCBBox[i](0, 2) && v2(2) <= DBCBBox[i](1, 2) &&
|
|
v3(0) >= DBCBBox[i](0, 0) && v3(0) <= DBCBBox[i](1, 0) && v3(1) >= DBCBBox[i](0, 1) &&
|
|
v3(1) <= DBCBBox[i](1, 1) && v3(2) >= DBCBBox[i](0, 2) && v3(2) <= DBCBBox[i](1, 2)) {
|
|
DBC.emplace_back(std::make_pair(triI, DBCVal[i]));
|
|
++nDBC;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PhysicalDomain::SetBoundaryConditions(
|
|
int p_nNBC, const std::vector<std::pair<Eigen::RowVector3d, Eigen::Vector3d>> &p_NBC,
|
|
int p_nDBC, const std::vector<std::pair<int, Eigen::Vector3d>> &p_DBC,
|
|
double p_penaltyNitsche) {
|
|
nNBC = p_nNBC;
|
|
NBC = p_NBC;
|
|
nDBC = p_nDBC;
|
|
DBC = p_DBC;
|
|
use_Nitsche = true;
|
|
penaltyNitsche = p_penaltyNitsche;
|
|
}
|
|
|
|
void PhysicalDomain::WriteNBCToVtk(const fs_path &path) {
|
|
spdlog::info("number of NBC points: {}", nNBC);
|
|
Eigen::MatrixXd NBC_V(nNBC, 3);
|
|
for (int NBCI = 0; NBCI < nNBC; ++NBCI) {
|
|
NBC_V.row(NBCI) = NBC[NBCI].first;
|
|
}
|
|
sha::WritePointsToVtk(path, NBC_V);
|
|
}
|
|
|
|
void PhysicalDomain::WriteDBCToObj(const fs_path &path) {
|
|
Eigen::MatrixXd Vdebug(numV, 3);
|
|
Eigen::MatrixXi Fdebug(nDBC, 3);
|
|
std::map<int, int> mp;
|
|
int cnt = 0;
|
|
spdlog::info("number of DBC triangles: {}", nDBC);
|
|
|
|
for (int DBCI = 0; DBCI < nDBC; ++DBCI) {
|
|
int triI = DBC[DBCI].first;
|
|
int vI = mesh_.mat_faces(triI, 0);
|
|
int vJ = mesh_.mat_faces(triI, 1);
|
|
int vK = mesh_.mat_faces(triI, 2);
|
|
if (!mp.count(vI)) {
|
|
mp[vI] = cnt;
|
|
Vdebug.row(cnt) = mesh_.mat_coordinates.row(vI);
|
|
++cnt;
|
|
}
|
|
if (!mp.count(vJ)) {
|
|
mp[vJ] = cnt;
|
|
Vdebug.row(cnt) = mesh_.mat_coordinates.row(vJ);
|
|
++cnt;
|
|
}
|
|
if (!mp.count(vK)) {
|
|
mp[vK] = cnt;
|
|
Vdebug.row(cnt) = mesh_.mat_coordinates.row(vK);
|
|
++cnt;
|
|
}
|
|
Fdebug.row(DBCI) = Eigen::RowVector3i(mp[vI], mp[vJ], mp[vK]);
|
|
}
|
|
Vdebug.conservativeResize(cnt, 3);
|
|
igl::write_triangle_mesh(path.string(), Vdebug, Fdebug);
|
|
}
|
|
|
|
void PhysicalDomain::WriteV1MeshToObj(const fs_path &path) {
|
|
igl::write_triangle_mesh(path.string(), V1, mesh_.mat_faces);
|
|
}
|
|
} // namespace da::sha
|