refactoring. Saving of drm settings. TBB instead of openmp
This commit is contained in:
parent
af4449a9dd
commit
3c879db90f
|
@ -43,6 +43,17 @@ download_project(PROJ threed-beam-fea
|
||||||
)
|
)
|
||||||
add_subdirectory(${threed-beam-fea_SOURCE_DIR} ${threed-beam-fea_BINARY_DIR})
|
add_subdirectory(${threed-beam-fea_SOURCE_DIR} ${threed-beam-fea_BINARY_DIR})
|
||||||
|
|
||||||
|
##TBB
|
||||||
|
download_project(PROJ TBB
|
||||||
|
GIT_REPOSITORY https://github.com/wjakob/tbb.git
|
||||||
|
GIT_TAG master
|
||||||
|
PREFIX ${EXTERNAL_DEPS_DIR}
|
||||||
|
${UPDATE_DISCONNECTED_IF_AVAILABLE}
|
||||||
|
)
|
||||||
|
add_subdirectory(${TBB_SOURCE_DIR} ${TBB_BINARY_DIR})
|
||||||
|
link_directories(${TBB_BINARY_DIR})
|
||||||
|
message(${TBB_BINARY_DIR})
|
||||||
|
|
||||||
|
|
||||||
###Eigen 3 NOTE: Eigen is required on the system the code is ran
|
###Eigen 3 NOTE: Eigen is required on the system the code is ran
|
||||||
find_package(Eigen3 3.3 REQUIRED)
|
find_package(Eigen3 3.3 REQUIRED)
|
||||||
|
@ -53,6 +64,7 @@ endif(MSVC)
|
||||||
|
|
||||||
#link_directories(${CMAKE_CURRENT_LIST_DIR}/boost_graph/libs)
|
#link_directories(${CMAKE_CURRENT_LIST_DIR}/boost_graph/libs)
|
||||||
file(GLOB MySourcesFiles ${CMAKE_CURRENT_LIST_DIR}/*.hpp ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
|
file(GLOB MySourcesFiles ${CMAKE_CURRENT_LIST_DIR}/*.hpp ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
|
||||||
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ltbb")
|
||||||
add_library(${PROJECT_NAME} ${MySourcesFiles} ${vcglib_devel_SOURCE_DIR}/wrap/ply/plylib.cpp)
|
add_library(${PROJECT_NAME} ${MySourcesFiles} ${vcglib_devel_SOURCE_DIR}/wrap/ply/plylib.cpp)
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,9 +76,8 @@ target_include_directories(${PROJECT_NAME}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${USE_POLYSCOPE})
|
if(${USE_POLYSCOPE})
|
||||||
find_package(OpenMP REQUIRED)
|
target_link_libraries(${PROJECT_NAME} Eigen3::Eigen matplot polyscope glad ThreedBeamFEA ${TBB_BINARY_DIR}/libtbb_static.a pthread)
|
||||||
target_link_libraries(${PROJECT_NAME} Eigen3::Eigen matplot polyscope glad ThreedBeamFEA OpenMP::OpenMP_CXX)
|
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} -static Eigen3::Eigen matplot ThreedBeamFEA)
|
target_link_libraries(${PROJECT_NAME} -static Eigen3::Eigen matplot ThreedBeamFEA ${TBB_BINARY_DIR}/libtbb_static.a pthread)
|
||||||
endif()
|
endif()
|
||||||
target_link_directories(MySources PUBLIC ${CMAKE_CURRENT_LIST_DIR}/boost_graph/libs)
|
target_link_directories(MySources PUBLIC ${CMAKE_CURRENT_LIST_DIR}/boost_graph/libs)
|
||||||
|
|
|
@ -222,7 +222,7 @@ void DRMSimulationModel::reset()
|
||||||
mCurrentSimulationStep = 0;
|
mCurrentSimulationStep = 0;
|
||||||
history.clear();
|
history.clear();
|
||||||
constrainedVertices.clear();
|
constrainedVertices.clear();
|
||||||
rigidSupports.clear();
|
isRigidSupport.clear();
|
||||||
pMesh.reset();
|
pMesh.reset();
|
||||||
plotYValues.clear();
|
plotYValues.clear();
|
||||||
plotHandle.reset();
|
plotHandle.reset();
|
||||||
|
@ -807,10 +807,17 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
// omp_lock_t writelock;
|
// omp_lock_t writelock;
|
||||||
// omp_init_lock(&writelock);
|
// omp_init_lock(&writelock);
|
||||||
//#ifdef ENABLE_OPENMP
|
//#ifdef ENABLE_OPENMP
|
||||||
//#pragma omp parallel for schedule(static) num_threads(8)
|
//#pragma omp parallel for schedule(static) num_threads(5)
|
||||||
//#endif
|
//#endif
|
||||||
for (int ei = 0; ei < pMesh->EN(); ei++) {
|
std::for_each(
|
||||||
const EdgeType &e = pMesh->edge[ei];
|
std::execution::par_unseq,
|
||||||
|
pMesh->edge.begin(),
|
||||||
|
pMesh->edge.end(),
|
||||||
|
[&](const EdgeType &e)
|
||||||
|
// for (int ei = 0; ei < pMesh->EN(); ei++)
|
||||||
|
{
|
||||||
|
const int ei = pMesh->getIndex(e);
|
||||||
|
// const EdgeType &e = pMesh->edge[ei];
|
||||||
const SimulationMesh::VertexType &ev_j = *e.cV(0);
|
const SimulationMesh::VertexType &ev_j = *e.cV(0);
|
||||||
const SimulationMesh::VertexType &ev_jplus1 = *e.cV(1);
|
const SimulationMesh::VertexType &ev_jplus1 = *e.cV(1);
|
||||||
const Element &element = pMesh->elements[e];
|
const Element &element = pMesh->elements[e];
|
||||||
|
@ -830,9 +837,8 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
// element.rotationalDisplacements_jplus1.theta2 = theta2_jplus1;
|
// element.rotationalDisplacements_jplus1.theta2 = theta2_jplus1;
|
||||||
// element.rotationalDisplacements_j.theta3 = theta3_j;
|
// element.rotationalDisplacements_j.theta3 = theta3_j;
|
||||||
// element.rotationalDisplacements_jplus1.theta3 = theta3_jplus1;
|
// element.rotationalDisplacements_jplus1.theta3 = theta3_jplus1;
|
||||||
std::vector<std::pair<int, Vector6d>> internalForcesContributionFromThisEdge(4,
|
std::vector<std::pair<int, Vector6d>>
|
||||||
{-1,
|
internalForcesContributionFromThisEdge(4, {-1, Vector6d()});
|
||||||
Vector6d()});
|
|
||||||
for (VertexIndex evi = 0; evi < 2; evi++) {
|
for (VertexIndex evi = 0; evi < 2; evi++) {
|
||||||
const SimulationMesh::VertexType &ev = *e.cV(evi);
|
const SimulationMesh::VertexType &ev = *e.cV(evi);
|
||||||
const Node &edgeNode = pMesh->nodes[ev];
|
const Node &edgeNode = pMesh->nodes[ev];
|
||||||
|
@ -850,7 +856,8 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
// #pragma omp parallel for schedule(static) num_threads(6)
|
// #pragma omp parallel for schedule(static) num_threads(6)
|
||||||
for (DoFType dofi = DoF::Ux; dofi < DoF::NumDoF; dofi++) {
|
for (DoFType dofi = DoF::Ux; dofi < DoF::NumDoF; dofi++) {
|
||||||
const bool isDofConstrainedFor_ev = isVertexConstrained[edgeNode.vi]
|
const bool isDofConstrainedFor_ev = isVertexConstrained[edgeNode.vi]
|
||||||
&& fixedVertices.at(edgeNode.vi).contains(dofi);
|
&& fixedVertices.at(edgeNode.vi)
|
||||||
|
.contains(dofi);
|
||||||
if (!isDofConstrainedFor_ev) {
|
if (!isDofConstrainedFor_ev) {
|
||||||
DifferentiateWithRespectTo dui{ev, dofi};
|
DifferentiateWithRespectTo dui{ev, dofi};
|
||||||
// Axial force computation
|
// Axial force computation
|
||||||
|
@ -883,7 +890,8 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
////theta2_jplus1 derivative
|
////theta2_jplus1 derivative
|
||||||
const double theta2_jplus1_deriv = computeDerivativeTheta2(e, 1, evi, dofi);
|
const double theta2_jplus1_deriv = computeDerivativeTheta2(e, 1, evi, dofi);
|
||||||
////1st in bracket term
|
////1st in bracket term
|
||||||
const double firstBendingForce_inBracketsTerm_0 = theta2_j_deriv * 2 * theta2_j;
|
const double firstBendingForce_inBracketsTerm_0 = theta2_j_deriv * 2
|
||||||
|
* theta2_j;
|
||||||
////2nd in bracket term
|
////2nd in bracket term
|
||||||
const double firstBendingForce_inBracketsTerm_1 = theta2_jplus1_deriv
|
const double firstBendingForce_inBracketsTerm_1 = theta2_jplus1_deriv
|
||||||
* theta2_j;
|
* theta2_j;
|
||||||
|
@ -895,8 +903,10 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
* theta2_jplus1;
|
* theta2_jplus1;
|
||||||
// 3rd term computation
|
// 3rd term computation
|
||||||
const double firstBendingForce_inBracketsTerm
|
const double firstBendingForce_inBracketsTerm
|
||||||
= firstBendingForce_inBracketsTerm_0 + firstBendingForce_inBracketsTerm_1
|
= firstBendingForce_inBracketsTerm_0
|
||||||
+ firstBendingForce_inBracketsTerm_2 + firstBendingForce_inBracketsTerm_3;
|
+ firstBendingForce_inBracketsTerm_1
|
||||||
|
+ firstBendingForce_inBracketsTerm_2
|
||||||
|
+ firstBendingForce_inBracketsTerm_3;
|
||||||
const double firstBendingForce_dofi = firstBendingForce_inBracketsTerm
|
const double firstBendingForce_dofi = firstBendingForce_inBracketsTerm
|
||||||
* element.rigidity.firstBending;
|
* element.rigidity.firstBending;
|
||||||
|
|
||||||
|
@ -904,7 +914,9 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
////theta2_j derivative
|
////theta2_j derivative
|
||||||
const double theta3_j_deriv = computeDerivativeTheta3(e, ev_j, dui);
|
const double theta3_j_deriv = computeDerivativeTheta3(e, ev_j, dui);
|
||||||
////theta2_jplus1 derivative
|
////theta2_jplus1 derivative
|
||||||
const double theta3_jplus1_deriv = computeDerivativeTheta3(e, ev_jplus1, dui);
|
const double theta3_jplus1_deriv = computeDerivativeTheta3(e,
|
||||||
|
ev_jplus1,
|
||||||
|
dui);
|
||||||
////1st in bracket term
|
////1st in bracket term
|
||||||
const double secondBendingForce_inBracketsTerm_0 = theta3_j_deriv * 2
|
const double secondBendingForce_inBracketsTerm_0 = theta3_j_deriv * 2
|
||||||
* theta3_j;
|
* theta3_j;
|
||||||
|
@ -919,7 +931,8 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
* theta3_jplus1;
|
* theta3_jplus1;
|
||||||
// 3rd term computation
|
// 3rd term computation
|
||||||
const double secondBendingForce_inBracketsTerm
|
const double secondBendingForce_inBracketsTerm
|
||||||
= secondBendingForce_inBracketsTerm_0 + secondBendingForce_inBracketsTerm_1
|
= secondBendingForce_inBracketsTerm_0
|
||||||
|
+ secondBendingForce_inBracketsTerm_1
|
||||||
+ secondBendingForce_inBracketsTerm_2
|
+ secondBendingForce_inBracketsTerm_2
|
||||||
+ secondBendingForce_inBracketsTerm_3;
|
+ secondBendingForce_inBracketsTerm_3;
|
||||||
double secondBendingForce_dofi = secondBendingForce_inBracketsTerm
|
double secondBendingForce_dofi = secondBendingForce_inBracketsTerm
|
||||||
|
@ -950,8 +963,8 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
const double secondBendingForce_inBracketsTerm_2 = theta3_j_deriv
|
const double secondBendingForce_inBracketsTerm_2 = theta3_j_deriv
|
||||||
* theta3_jplus1;
|
* theta3_jplus1;
|
||||||
////4th in bracket term
|
////4th in bracket term
|
||||||
const double secondBendingForce_inBracketsTerm_3 = theta3_jplus1_deriv * 2
|
const double secondBendingForce_inBracketsTerm_3 = theta3_jplus1_deriv
|
||||||
* theta3_jplus1;
|
* 2 * theta3_jplus1;
|
||||||
|
|
||||||
// 4th term computation
|
// 4th term computation
|
||||||
const double secondBendingForce_inBracketsTerm
|
const double secondBendingForce_inBracketsTerm
|
||||||
|
@ -968,7 +981,7 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internalForcesContributionsFromEachEdge[ei] = internalForcesContributionFromThisEdge;
|
internalForcesContributionsFromEachEdge[ei] = internalForcesContributionFromThisEdge;
|
||||||
}
|
});
|
||||||
|
|
||||||
//#pragma omp parallel for schedule(static) num_threads(8)
|
//#pragma omp parallel for schedule(static) num_threads(8)
|
||||||
|
|
||||||
|
@ -1251,7 +1264,7 @@ void DRMSimulationModel::updateNodalMasses()
|
||||||
pMesh->nodes[v].damping_6d[DoF::Nr] = 2
|
pMesh->nodes[v].damping_6d[DoF::Nr] = 2
|
||||||
* std::sqrt(rotationalSumSk_I2
|
* std::sqrt(rotationalSumSk_I2
|
||||||
* pMesh->nodes[v].mass_6d[DoF::Nr]);
|
* pMesh->nodes[v].mass_6d[DoF::Nr]);
|
||||||
pMesh->nodes[v].damping_6d = pMesh->nodes[v].damping_6d * 1e-2;
|
pMesh->nodes[v].damping_6d = pMesh->nodes[v].damping_6d * 1e-3;
|
||||||
}
|
}
|
||||||
assert(std::pow(mSettings.Dtini, 2.0) * translationalSumSk
|
assert(std::pow(mSettings.Dtini, 2.0) * translationalSumSk
|
||||||
/ pMesh->nodes[v].mass.translational
|
/ pMesh->nodes[v].mass.translational
|
||||||
|
@ -1296,8 +1309,8 @@ void DRMSimulationModel::updateNodalVelocities()
|
||||||
Node &node = pMesh->nodes[v];
|
Node &node = pMesh->nodes[v];
|
||||||
if (mSettings.useViscousDamping) {
|
if (mSettings.useViscousDamping) {
|
||||||
const Vector6d massOverDt = node.mass_6d / Dt;
|
const Vector6d massOverDt = node.mass_6d / Dt;
|
||||||
const Vector6d visciousDampingFactor(viscuousDampingConstant / 2);
|
// const Vector6d visciousDampingFactor(viscuousDampingConstant / 2);
|
||||||
// const Vector6d &visciousDampingFactor = node.damping_6d;
|
const Vector6d &visciousDampingFactor = node.damping_6d;
|
||||||
const Vector6d denominator = massOverDt + visciousDampingFactor / 2;
|
const Vector6d denominator = massOverDt + visciousDampingFactor / 2;
|
||||||
const Vector6d firstTermNominator = massOverDt - visciousDampingFactor / 2;
|
const Vector6d firstTermNominator = massOverDt - visciousDampingFactor / 2;
|
||||||
const Vector6d firstTerm = node.velocity * firstTermNominator / denominator;
|
const Vector6d firstTerm = node.velocity * firstTermNominator / denominator;
|
||||||
|
@ -2609,3 +2622,19 @@ mesh->currentTotalPotentialEnergykN*/
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DRMSimulationModel::Settings::save(const filesystem::__cxx11::path &folderPath) const
|
||||||
|
{
|
||||||
|
bool returnValue = true;
|
||||||
|
std::filesystem::create_directories(folderPath);
|
||||||
|
nlohmann::json json;
|
||||||
|
json[jsonLabels.meshFilename]
|
||||||
|
= std::filesystem::relative(std::filesystem::path(meshFilename),
|
||||||
|
std::filesystem::path(jsonFilename).parent_path())
|
||||||
|
.string();
|
||||||
|
const std::string jsonFilename = "drmSettings.json";
|
||||||
|
std::ofstream jsonFile(std::filesystem::path(folderPath).append(jsonFilename));
|
||||||
|
jsonFile << json;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DRMSimulationModel::Settings::load(const filesystem::__cxx11::path &filePath) const {}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,30 +25,32 @@ class DRMSimulationModel
|
||||||
public:
|
public:
|
||||||
struct Settings
|
struct Settings
|
||||||
{
|
{
|
||||||
bool isDebugMode{false};
|
// bool isDebugMode{false};
|
||||||
int debugModeStep{100000};
|
std::optional<int> debugModeStep{0};
|
||||||
bool shouldDraw{false};
|
bool shouldDraw{false};
|
||||||
bool beVerbose{false};
|
bool beVerbose{false};
|
||||||
bool shouldCreatePlots{false};
|
bool shouldCreatePlots{false};
|
||||||
int drawingStep{1};
|
// int drawingStep{0};
|
||||||
double totalTranslationalKineticEnergyThreshold{1e-8};
|
// double residualForcesMovingAverageDerivativeNormThreshold{1e-8};
|
||||||
double residualForcesMovingAverageDerivativeNormThreshold{1e-8};
|
// double residualForcesMovingAverageNormThreshold{1e-8};
|
||||||
double residualForcesMovingAverageNormThreshold{1e-8};
|
|
||||||
double Dtini{0.1};
|
double Dtini{0.1};
|
||||||
double xi{0.9969};
|
double xi{0.9969};
|
||||||
int maxDRMIterations{0};
|
int maxDRMIterations{0};
|
||||||
bool shouldUseTranslationalKineticEnergyThreshold{false};
|
std::optional<double> shouldUseTranslationalKineticEnergyThreshold;
|
||||||
int gradualForcedDisplacementSteps{50};
|
// int gradualForcedDisplacementSteps{50};
|
||||||
int desiredGradualExternalLoadsSteps{1};
|
// int desiredGradualExternalLoadsSteps{1};
|
||||||
double gamma{0.8};
|
double gamma{0.8};
|
||||||
std::optional<double> displacementCap;
|
std::optional<double> displacementCap;
|
||||||
double totalResidualForcesNormThreshold{1e-3};
|
double totalResidualForcesNormThreshold{1e-3};
|
||||||
double totalExternalForcesNormPercentageTermination{1e-3};
|
double totalExternalForcesNormPercentageTermination{1e-3};
|
||||||
bool useAverage{false};
|
std::optional<double> averageResidualForcesCriterionThreshold{1e-5};
|
||||||
double averageResidualForcesCriterionThreshold{1e-5};
|
|
||||||
Settings() {}
|
Settings() {}
|
||||||
|
bool save(const std::filesystem::path &folderPath) const;
|
||||||
|
bool load(const std::filesystem::path &filePath) const;
|
||||||
bool useViscousDamping{false};
|
bool useViscousDamping{false};
|
||||||
bool useKineticDamping{true};
|
bool useKineticDamping{true};
|
||||||
|
struct JsonLabels
|
||||||
|
{};
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -0,0 +1,254 @@
|
||||||
|
#ifndef BEAMFORMFINDER_HPP
|
||||||
|
#define BEAMFORMFINDER_HPP
|
||||||
|
|
||||||
|
#include "simulationmesh.hpp"
|
||||||
|
#include "matplot/matplot.h"
|
||||||
|
#include "simulation_structs.hpp"
|
||||||
|
#include <Eigen/Dense>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
struct SimulationJob;
|
||||||
|
|
||||||
|
enum DoF { Ux = 0, Uy, Uz, Nx, Ny, Nr, NumDoF };
|
||||||
|
using DoFType = int;
|
||||||
|
using EdgeType = VCGEdgeMesh::EdgeType;
|
||||||
|
using VertexType = VCGEdgeMesh::VertexType;
|
||||||
|
|
||||||
|
struct DifferentiateWithRespectTo {
|
||||||
|
const VertexType &v;
|
||||||
|
const DoFType &dofi;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DRMSimulationModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Settings
|
||||||
|
{
|
||||||
|
bool isDebugMode{false};
|
||||||
|
int debugModeStep{100000};
|
||||||
|
bool shouldDraw{false};
|
||||||
|
bool beVerbose{false};
|
||||||
|
bool shouldCreatePlots{false};
|
||||||
|
int drawingStep{1};
|
||||||
|
double totalTranslationalKineticEnergyThreshold{1e-8};
|
||||||
|
double residualForcesMovingAverageDerivativeNormThreshold{1e-8};
|
||||||
|
double residualForcesMovingAverageNormThreshold{1e-8};
|
||||||
|
double Dtini{0.1};
|
||||||
|
double xi{0.9969};
|
||||||
|
int maxDRMIterations{0};
|
||||||
|
bool shouldUseTranslationalKineticEnergyThreshold{false};
|
||||||
|
int gradualForcedDisplacementSteps{50};
|
||||||
|
int desiredGradualExternalLoadsSteps{1};
|
||||||
|
double gamma{0.8};
|
||||||
|
std::optional<double> displacementCap;
|
||||||
|
double totalResidualForcesNormThreshold{1e-3};
|
||||||
|
double totalExternalForcesNormPercentageTermination{1e-3};
|
||||||
|
bool useAverage{false};
|
||||||
|
double averageResidualForcesCriterionThreshold{1e-5};
|
||||||
|
Settings() {}
|
||||||
|
bool useViscousDamping{false};
|
||||||
|
bool useKineticDamping{true};
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Settings mSettings;
|
||||||
|
double Dt{mSettings.Dtini};
|
||||||
|
bool checkedForMaximumMoment{false};
|
||||||
|
bool shouldTemporarilyDampForces{false};
|
||||||
|
bool shouldTemporarilyAmplifyForces{true};
|
||||||
|
double externalMomentsNorm{0};
|
||||||
|
size_t mCurrentSimulationStep{0};
|
||||||
|
matplot::line_handle plotHandle;
|
||||||
|
std::vector<double> plotYValues;
|
||||||
|
size_t numOfDampings{0};
|
||||||
|
int externalLoadStep{1};
|
||||||
|
<<<<<<< HEAD
|
||||||
|
const double viscuousDampingConstant{100};
|
||||||
|
=======
|
||||||
|
>>>>>>> master
|
||||||
|
std::vector<bool> isVertexConstrained;
|
||||||
|
std::vector<bool> isRigidSupport;
|
||||||
|
double minTotalResidualForcesNorm{std::numeric_limits<double>::max()};
|
||||||
|
|
||||||
|
const std::string meshPolyscopeLabel{"Simulation mesh"};
|
||||||
|
std::unique_ptr<SimulationMesh> pMesh;
|
||||||
|
std::unordered_map<VertexIndex, std::unordered_set<DoFType>> constrainedVertices;
|
||||||
|
SimulationHistory history;
|
||||||
|
// Eigen::Tensor<double, 4> theta3Derivatives;
|
||||||
|
// std::unordered_map<MyKeyType, double, key_hash> theta3Derivatives;
|
||||||
|
bool shouldApplyInitialDistortion = false;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void updateNodalInternalForces(
|
||||||
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>> &fixedVertices);
|
||||||
|
void updateNodalExternalForces(
|
||||||
|
const std::unordered_map<VertexIndex, Vector6d> &nodalForces,
|
||||||
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>> &fixedVertices);
|
||||||
|
void updateResidualForces();
|
||||||
|
void updateRotationalDisplacements();
|
||||||
|
void updateElementalLengths();
|
||||||
|
|
||||||
|
void updateNodalMasses();
|
||||||
|
|
||||||
|
void updateNodalAccelerations();
|
||||||
|
|
||||||
|
void updateNodalVelocities();
|
||||||
|
|
||||||
|
void updateNodalDisplacements();
|
||||||
|
|
||||||
|
void applyForcedDisplacements(
|
||||||
|
const std::unordered_map<VertexIndex, Eigen::Vector3d> &nodalForcedDisplacements);
|
||||||
|
|
||||||
|
Vector6d computeElementTorsionalForce(const Element &element,
|
||||||
|
const Vector6d &displacementDifference,
|
||||||
|
const std::unordered_set<DoFType> &constrainedDof);
|
||||||
|
|
||||||
|
// BeamFormFinder::Vector6d computeElementFirstBendingForce(
|
||||||
|
// const Element &element, const Vector6d &displacementDifference,
|
||||||
|
// const std::unordered_set<gsl::index> &constrainedDof);
|
||||||
|
|
||||||
|
// BeamFormFinder::Vector6d computeElementSecondBendingForce(
|
||||||
|
// const Element &element, const Vector6d &displacementDifference,
|
||||||
|
// const std::unordered_set<gsl::index> &constrainedDof);
|
||||||
|
|
||||||
|
void updateKineticEnergy();
|
||||||
|
|
||||||
|
void resetVelocities();
|
||||||
|
|
||||||
|
SimulationResults computeResults(const std::shared_ptr<SimulationJob> &pJob);
|
||||||
|
|
||||||
|
void updateNodePosition(
|
||||||
|
VertexType &v,
|
||||||
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>> &fixedVertices);
|
||||||
|
|
||||||
|
void applyDisplacements(
|
||||||
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>> &fixedVertices);
|
||||||
|
|
||||||
|
#ifdef POLYSCOPE_DEFINED
|
||||||
|
void draw(const string &screenshotsFolder= {});
|
||||||
|
#endif
|
||||||
|
void
|
||||||
|
updateNodalInternalForce(Vector6d &nodalInternalForce,
|
||||||
|
const Vector6d &elementInternalForce,
|
||||||
|
const std::unordered_set<DoFType> &nodalFixedDof);
|
||||||
|
|
||||||
|
Vector6d computeElementInternalForce(
|
||||||
|
const Element &elem, const Node &n0, const Node &n1,
|
||||||
|
const std::unordered_set<DoFType> &n0ConstrainedDof,
|
||||||
|
const std::unordered_set<DoFType> &n1ConstrainedDof);
|
||||||
|
|
||||||
|
Vector6d computeElementAxialForce(const ::EdgeType &e) const;
|
||||||
|
VectorType computeDisplacementDifferenceDerivative(
|
||||||
|
const EdgeType &e, const DifferentiateWithRespectTo &dui) const;
|
||||||
|
double
|
||||||
|
computeDerivativeElementLength(const EdgeType &e,
|
||||||
|
const DifferentiateWithRespectTo &dui) const;
|
||||||
|
|
||||||
|
VectorType computeDerivativeT1(const EdgeType &e,
|
||||||
|
const DifferentiateWithRespectTo &dui) const;
|
||||||
|
|
||||||
|
VectorType
|
||||||
|
computeDerivativeOfNormal(const VertexType &v,
|
||||||
|
const DifferentiateWithRespectTo &dui) const;
|
||||||
|
|
||||||
|
VectorType computeDerivativeT3(const EdgeType &e,
|
||||||
|
const DifferentiateWithRespectTo &dui) const;
|
||||||
|
|
||||||
|
VectorType computeDerivativeT2(const EdgeType &e,
|
||||||
|
const DifferentiateWithRespectTo &dui) const;
|
||||||
|
|
||||||
|
double computeDerivativeTheta2(const EdgeType &e, const VertexIndex &evi,
|
||||||
|
const VertexIndex &dwrt_evi,
|
||||||
|
const DoFType &dwrt_dofi) const;
|
||||||
|
|
||||||
|
void updateElementalFrames();
|
||||||
|
|
||||||
|
VectorType computeDerivativeOfR(const EdgeType &e, const DifferentiateWithRespectTo &dui) const;
|
||||||
|
|
||||||
|
// bool isRigidSupport(const VertexType &v) const;
|
||||||
|
|
||||||
|
static double computeDerivativeOfNorm(const VectorType &x,
|
||||||
|
const VectorType &derivativeOfX);
|
||||||
|
static VectorType computeDerivativeOfCrossProduct(
|
||||||
|
const VectorType &a, const VectorType &derivativeOfA, const VectorType &b,
|
||||||
|
const VectorType &derivativeOfB);
|
||||||
|
|
||||||
|
double computeTheta3(const EdgeType &e, const VertexType &v);
|
||||||
|
double computeDerivativeTheta3(const EdgeType &e, const VertexType &v,
|
||||||
|
const DifferentiateWithRespectTo &dui) const;
|
||||||
|
double computeTotalPotentialEnergy();
|
||||||
|
void computeRigidSupports();
|
||||||
|
void updateNormalDerivatives();
|
||||||
|
void updateT1Derivatives();
|
||||||
|
void updateT2Derivatives();
|
||||||
|
void updateT3Derivatives();
|
||||||
|
void updateRDerivatives();
|
||||||
|
|
||||||
|
double computeDerivativeTheta1(const EdgeType &e, const VertexIndex &evi,
|
||||||
|
const VertexIndex &dwrt_evi,
|
||||||
|
const DoFType &dwrt_dofi) const;
|
||||||
|
|
||||||
|
// void updatePositionsOnTheFly(
|
||||||
|
// const std::unordered_map<VertexIndex,
|
||||||
|
// std::unordered_set<gsl::index>>
|
||||||
|
// &fixedVertices);
|
||||||
|
|
||||||
|
void updateResidualForcesOnTheFly(
|
||||||
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
||||||
|
&fixedVertices);
|
||||||
|
|
||||||
|
void updatePositionsOnTheFly(
|
||||||
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
||||||
|
&fixedVertices);
|
||||||
|
|
||||||
|
void updateNodeNormal(
|
||||||
|
VertexType &v,
|
||||||
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>>
|
||||||
|
&fixedVertices);
|
||||||
|
|
||||||
|
void applyForcedNormals(
|
||||||
|
const std::unordered_map<VertexIndex, VectorType> nodalForcedRotations);
|
||||||
|
|
||||||
|
void printCurrentState() const;
|
||||||
|
|
||||||
|
void printDebugInfo() const;
|
||||||
|
|
||||||
|
double computeTotalInternalPotentialEnergy();
|
||||||
|
|
||||||
|
void applySolutionGuess(const SimulationResults &solutionGuess,
|
||||||
|
const std::shared_ptr<SimulationJob> &pJob);
|
||||||
|
|
||||||
|
void updateNodeNr(VertexType &v);
|
||||||
|
|
||||||
|
public:
|
||||||
|
DRMSimulationModel();
|
||||||
|
SimulationResults executeSimulation(const std::shared_ptr<SimulationJob> &pJob,
|
||||||
|
const Settings &settings = Settings(),
|
||||||
|
const SimulationResults &solutionGuess = SimulationResults());
|
||||||
|
|
||||||
|
static void runUnitTests();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename PointType> PointType Cross(PointType p1, PointType p2) {
|
||||||
|
return p1 ^ p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t currentStep{0};
|
||||||
|
inline bool TriggerBreakpoint(const VertexIndex &vi, const EdgeIndex &ei,
|
||||||
|
const DoFType &dofi) {
|
||||||
|
const size_t numberOfVertices = 10;
|
||||||
|
const VertexIndex middleNodeIndex = numberOfVertices / 2;
|
||||||
|
// return vi == middleNodeIndex && dofi == 1;
|
||||||
|
return dofi == 1 && ((vi == 1 && ei == 0) || (vi == 9 && ei == 9));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool TriggerBreakpoint(const VertexIndex &vi, const EdgeIndex &ei) {
|
||||||
|
const size_t numberOfVertices = 10;
|
||||||
|
const VertexIndex middleNodeIndex = numberOfVertices / 2;
|
||||||
|
return (vi == middleNodeIndex);
|
||||||
|
// return (vi == 0 || vi == numberOfVertices - 1) && currentStep == 1;
|
||||||
|
return (vi == 1 && ei == 0) || (vi == 9 && ei == 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BEAMFORMFINDER_HPP
|
|
@ -191,7 +191,8 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
|
||||||
patternGeometryAllEdges.getVertices(),
|
patternGeometryAllEdges.getVertices(),
|
||||||
intersectingEdges,
|
intersectingEdges,
|
||||||
validEdges);
|
validEdges);
|
||||||
// statistics.print(setupString, perEdgeResultPath);
|
statistics.print(setupString, perEdgeResultPath);
|
||||||
|
statistics.reset();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Computing " + setupString << " with " << numberOfDesiredEdges << " edges."
|
std::cout << "Computing " + setupString << " with " << numberOfDesiredEdges << " edges."
|
||||||
|
@ -372,6 +373,20 @@ std::vector<vcg::Point2i> TopologyEnumerator::getValidEdges(
|
||||||
return validEdges;
|
return validEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TopologyEnumerator::exportPattern(const std::filesystem::path &saveToPath,
|
||||||
|
PatternGeometry &patternGeometry,
|
||||||
|
const bool saveTilledPattern) const
|
||||||
|
{
|
||||||
|
const std::string patternName = patternGeometry.getLabel();
|
||||||
|
std::filesystem::create_directory(saveToPath);
|
||||||
|
patternGeometry.save(std::filesystem::path(saveToPath).append(patternName).string() + ".ply");
|
||||||
|
if (saveTilledPattern) {
|
||||||
|
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(patternGeometry);
|
||||||
|
tiledPatternGeometry.save(
|
||||||
|
std::filesystem::path(saveToPath).append(patternName + "_tiled").string() + ".ply");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TopologyEnumerator::computeValidPatterns(
|
void TopologyEnumerator::computeValidPatterns(
|
||||||
const std::vector<size_t> &numberOfNodesPerSlot,
|
const std::vector<size_t> &numberOfNodesPerSlot,
|
||||||
const size_t &numberOfDesiredEdges,
|
const size_t &numberOfDesiredEdges,
|
||||||
|
@ -418,6 +433,8 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
// std::string previousPatternBinaryRepresentation(validEdges.size(),'0');
|
// std::string previousPatternBinaryRepresentation(validEdges.size(),'0');
|
||||||
size_t patternIndex = 0;
|
size_t patternIndex = 0;
|
||||||
bool validPatternsExist = false;
|
bool validPatternsExist = false;
|
||||||
|
const bool exportTilledPattern = false;
|
||||||
|
const bool saveCompressedFormat = false;
|
||||||
do {
|
do {
|
||||||
patternIndex++;
|
patternIndex++;
|
||||||
const std::string patternName = std::to_string(patternIndex);
|
const std::string patternName = std::to_string(patternIndex);
|
||||||
|
@ -438,6 +455,7 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
|
|
||||||
PatternGeometry patternGeometry;
|
PatternGeometry patternGeometry;
|
||||||
patternGeometry.add(allVertices, patternEdges);
|
patternGeometry.add(allVertices, patternEdges);
|
||||||
|
patternGeometry.setLabel(patternName);
|
||||||
|
|
||||||
// Check if pattern contains intersecting edges
|
// Check if pattern contains intersecting edges
|
||||||
const bool patternContainsIntersectingEdges
|
const bool patternContainsIntersectingEdges
|
||||||
|
@ -448,40 +466,24 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
statistics.numberOfPatternsWithIntersectingEdges++;
|
statistics.numberOfPatternsWithIntersectingEdges++;
|
||||||
if (debugIsOn) {
|
if (debugIsOn) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
exportPattern(std::filesystem::path(resultsPath).append("Intersecting"),
|
||||||
patternGeometry);
|
patternGeometry,
|
||||||
auto intersectingPatternsPath = std::filesystem::path(resultsPath)
|
exportTilledPattern);
|
||||||
.append("Intersecting");
|
|
||||||
std::filesystem::create_directory(intersectingPatternsPath);
|
|
||||||
patternGeometry.save(
|
|
||||||
std::filesystem::path(intersectingPatternsPath).append(patternName).string()
|
|
||||||
+ ".ply");
|
|
||||||
tiledPatternGeometry.save(std::filesystem::path(intersectingPatternsPath)
|
|
||||||
.append(patternName + "_tiled")
|
|
||||||
.string()
|
|
||||||
+ ".ply");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
continue; // should be uncommented in order to improve performance
|
continue; // should be uncommented in order to improve performance
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bool tiledPatternHasEdgesWithAngleSmallerThanThreshold
|
const bool tiledPatternHasEdgesWithAngleSmallerThanThreshold
|
||||||
= patternGeometry.hasAngleSmallerThanThreshold(numberOfNodesPerSlot, 15);
|
= patternGeometry.hasAngleSmallerThanThreshold(numberOfNodesPerSlot, 15);
|
||||||
if (tiledPatternHasEdgesWithAngleSmallerThanThreshold) {
|
if (tiledPatternHasEdgesWithAngleSmallerThanThreshold) {
|
||||||
if (debugIsOn /*|| savePlyFiles*/) {
|
if (debugIsOn /*|| savePlyFiles*/) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
auto danglingEdgesPath = std::filesystem::path(resultsPath)
|
exportPattern(std::filesystem::path(resultsPath)
|
||||||
.append("ExceedingAngleThreshold");
|
.append("ExceedingAngleThreshold"),
|
||||||
std::filesystem::create_directory(danglingEdgesPath);
|
patternGeometry,
|
||||||
patternGeometry.save(
|
exportTilledPattern);
|
||||||
std::filesystem::path(danglingEdgesPath).append(patternName).string()
|
|
||||||
+ ".ply");
|
|
||||||
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
|
||||||
patternGeometry); // the marked nodes of hasDanglingEdges are
|
|
||||||
tiledPatternGeometry.save(std::filesystem::path(danglingEdgesPath)
|
|
||||||
.append(patternName + "_tiled")
|
|
||||||
.string()
|
|
||||||
+ ".ply");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -493,18 +495,9 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
if (tiledPatternHasNodeWithValenceGreaterThanDesired) {
|
if (tiledPatternHasNodeWithValenceGreaterThanDesired) {
|
||||||
if (debugIsOn) {
|
if (debugIsOn) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
auto danglingEdgesPath = std::filesystem::path(resultsPath)
|
auto highValencePath = std::filesystem::path(resultsPath)
|
||||||
.append("HighValencePatterns");
|
.append("HighValencePatterns");
|
||||||
std::filesystem::create_directory(danglingEdgesPath);
|
exportPattern(highValencePath, patternGeometry, exportTilledPattern);
|
||||||
patternGeometry.save(
|
|
||||||
std::filesystem::path(danglingEdgesPath).append(patternName).string()
|
|
||||||
+ ".ply");
|
|
||||||
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
|
||||||
patternGeometry); // the marked nodes of hasDanglingEdges are
|
|
||||||
tiledPatternGeometry.save(std::filesystem::path(danglingEdgesPath)
|
|
||||||
.append(patternName + "_tiled")
|
|
||||||
.string()
|
|
||||||
+ ".ply");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -522,28 +515,19 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
// Check dangling edges with vcg method
|
// Check dangling edges with vcg method
|
||||||
// const bool vcg_tiledPatternHasDangling =
|
// const bool vcg_tiledPatternHasDangling =
|
||||||
// tiledPatternGeometry.hasUntiledDanglingEdges();
|
// tiledPatternGeometry.hasUntiledDanglingEdges();
|
||||||
if (tiledPatternHasDanglingEdges && !hasFloatingComponents /*&& !hasArticulationPoints*/) {
|
if (tiledPatternHasDanglingEdges /*&& !hasFloatingComponents && !hasArticulationPoints*/) {
|
||||||
statistics.numberOfPatternsWithADanglingEdgeOrNode++;
|
statistics.numberOfPatternsWithADanglingEdgeOrNode++;
|
||||||
if (debugIsOn) {
|
if (debugIsOn) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
auto danglingEdgesPath = std::filesystem::path(resultsPath).append("Dangling");
|
auto danglingEdgesPath = std::filesystem::path(resultsPath).append("Dangling");
|
||||||
std::filesystem::create_directory(danglingEdgesPath);
|
exportPattern(danglingEdgesPath, patternGeometry, exportTilledPattern);
|
||||||
patternGeometry.save(
|
|
||||||
std::filesystem::path(danglingEdgesPath).append(patternName).string()
|
|
||||||
+ ".ply");
|
|
||||||
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
|
||||||
patternGeometry); // the marked nodes of hasDanglingEdges are
|
|
||||||
tiledPatternGeometry.save(std::filesystem::path(danglingEdgesPath)
|
|
||||||
.append(patternName + "_tiled")
|
|
||||||
.string()
|
|
||||||
+ ".ply");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFloatingComponents && !hasArticulationPoints && !tiledPatternHasDanglingEdges) {
|
if (hasFloatingComponents /*&& !hasArticulationPoints && !tiledPatternHasDanglingEdges */) {
|
||||||
statistics.numberOfPatternsWithMoreThanASingleCC++;
|
statistics.numberOfPatternsWithMoreThanASingleCC++;
|
||||||
if (debugIsOn) {
|
if (debugIsOn) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
|
@ -599,34 +583,25 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
|
|
||||||
assert(colorsRegistered == eCC[0].first);
|
assert(colorsRegistered == eCC[0].first);
|
||||||
|
|
||||||
|
if (exportTilledPattern) {
|
||||||
tiledPatternGeometry.save(std::filesystem::path(moreThanOneCCPath)
|
tiledPatternGeometry.save(std::filesystem::path(moreThanOneCCPath)
|
||||||
.append(patternName + "_tiled")
|
.append(patternName + "_tiled")
|
||||||
.string()
|
.string()
|
||||||
+ ".ply");
|
+ ".ply");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasArticulationPoints && !hasFloatingComponents && !tiledPatternHasDanglingEdges) {
|
if (hasArticulationPoints /*&& !hasFloatingComponents && !tiledPatternHasDanglingEdges */) {
|
||||||
statistics.numberOfPatternsWithArticulationPoints++;
|
statistics.numberOfPatternsWithArticulationPoints++;
|
||||||
if (debugIsOn) {
|
if (debugIsOn) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
auto articulationPointsPath = std::filesystem::path(resultsPath)
|
auto articulationPointsPath = std::filesystem::path(resultsPath)
|
||||||
.append("ArticulationPoints");
|
.append("ArticulationPoints");
|
||||||
std::filesystem::create_directory(articulationPointsPath);
|
exportPattern(articulationPointsPath, patternGeometry, exportTilledPattern);
|
||||||
patternGeometry.save(
|
|
||||||
std::filesystem::path(articulationPointsPath).append(patternName).string()
|
|
||||||
+ ".ply");
|
|
||||||
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
|
||||||
patternGeometry); // the marked nodes of hasDanglingEdges are
|
|
||||||
tiledPatternGeometry.save(std::filesystem::path(articulationPointsPath)
|
|
||||||
.append(patternName + "_tiled")
|
|
||||||
.string()
|
|
||||||
+ ".ply");
|
|
||||||
|
|
||||||
// std::cout << "Pattern:" << patternName << std::endl;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -649,22 +624,9 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
statistics.numberOfValidPatterns++;
|
statistics.numberOfValidPatterns++;
|
||||||
validPatternsExist = true;
|
validPatternsExist = true;
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
// if (numberOfDesiredEdges == 4) {
|
exportPattern(validPatternsPath, patternGeometry, exportTilledPattern);
|
||||||
// std::cout << "Saving:"
|
|
||||||
// << std::filesystem::path(validPatternsPath)
|
|
||||||
// .append(patternName)
|
|
||||||
// .string() +
|
|
||||||
// ".ply"
|
|
||||||
// << std::endl;
|
|
||||||
// }
|
|
||||||
patternGeometry.save(
|
|
||||||
std::filesystem::path(validPatternsPath).append(patternName).string() + ".ply");
|
|
||||||
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
|
||||||
patternGeometry); // the marked nodes of hasDanglingEdges are
|
|
||||||
tiledPatternGeometry.save(
|
|
||||||
std::filesystem::path(validPatternsPath).append(patternName + "_tiled").string()
|
|
||||||
+ ".ply");
|
|
||||||
}
|
}
|
||||||
|
if (saveCompressedFormat) {
|
||||||
PatternIO::Pattern pattern;
|
PatternIO::Pattern pattern;
|
||||||
pattern.edges = patternEdges;
|
pattern.edges = patternEdges;
|
||||||
pattern.name = patternIndex;
|
pattern.name = patternIndex;
|
||||||
|
@ -677,11 +639,12 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
patternSet.patterns.reserve(patternSetBufferSize);
|
patternSet.patterns.reserve(patternSetBufferSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// assert(vcg_tiledPatternHasDangling == tiledPatternHasDanglingEdges);
|
// assert(vcg_tiledPatternHasDangling == tiledPatternHasDanglingEdges);
|
||||||
} while (std::next_permutation(patternBinaryRepresentation.begin(),
|
} while (std::next_permutation(patternBinaryRepresentation.begin(),
|
||||||
patternBinaryRepresentation.end()));
|
patternBinaryRepresentation.end()));
|
||||||
if (!patternSet.patterns.empty()) {
|
if (!patternSet.patterns.empty() && saveCompressedFormat) {
|
||||||
PatternIO::save(compressedPatternsFilePath, patternSet);
|
PatternIO::save(compressedPatternsFilePath, patternSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#ifndef TOPOLOGYENUMERATOR_HPP
|
#ifndef TOPOLOGYENUMERATOR_HPP
|
||||||
#define TOPOLOGYENUMERATOR_HPP
|
#define TOPOLOGYENUMERATOR_HPP
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
#include "patternIO.hpp"
|
#include "patternIO.hpp"
|
||||||
#include "trianglepatterngeometry.hpp"
|
#include "trianglepatterngeometry.hpp"
|
||||||
#include "trianglepattterntopology.hpp"
|
#include "trianglepattterntopology.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
//#include <nlohmann/json.hpp>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -63,28 +63,26 @@ class TopologyEnumerator {
|
||||||
size_t numberOfPatternsWithADanglingEdgeOrNode{0};
|
size_t numberOfPatternsWithADanglingEdgeOrNode{0};
|
||||||
size_t numberOfPatternsWithArticulationPoints{0};
|
size_t numberOfPatternsWithArticulationPoints{0};
|
||||||
size_t numberOfValidPatterns{0};
|
size_t numberOfValidPatterns{0};
|
||||||
// nlohmann::json convertToJson() const {
|
nlohmann::json convertToJson() const
|
||||||
// nlohmann::json json;
|
{
|
||||||
// json["numPossibleEdges"] = numberOfPossibleEdges;
|
nlohmann::json json;
|
||||||
// json["numCoincideEdges"] = numberOfCoincideEdges;
|
json["numPossibleEdges"] = numberOfPossibleEdges;
|
||||||
// json["numDuplicateEdges"] = numberOfDuplicateEdges;
|
json["numCoincideEdges"] = numberOfCoincideEdges;
|
||||||
// json["numValidEdges"] = numberOfValidEdges;
|
json["numDuplicateEdges"] = numberOfDuplicateEdges;
|
||||||
// json["numIntersectingEdgePairs"] = numberOfIntersectingEdgePairs;
|
json["numValidEdges"] = numberOfValidEdges;
|
||||||
// json["numPatterns"] = numberOfPatterns;
|
json["numIntersectingEdgePairs"] = numberOfIntersectingEdgePairs;
|
||||||
// // json["numIntersectingEdgesOverAllPatterns"] =
|
json["numPatterns"] = numberOfPatterns;
|
||||||
// // numberOfIntersectingEdgesOverAllPatterns;
|
// json["numIntersectingEdgesOverAllPatterns"] =
|
||||||
// json["numPatternsWithIntersectingEdges"] =
|
// numberOfIntersectingEdgesOverAllPatterns;
|
||||||
// numberOfPatternsWithIntersectingEdges;
|
json["numPatternsWithIntersectingEdges"] = numberOfPatternsWithIntersectingEdges;
|
||||||
// json["numPatternsWithNotASingleCC"] =
|
json["numPatternsWithNotASingleCC"] = numberOfPatternsWithMoreThanASingleCC;
|
||||||
// numberOfPatternsWithMoreThanASingleCC;
|
json["numPatternsWithDangling"] = numberOfPatternsWithADanglingEdgeOrNode;
|
||||||
// json["numPatternsWithDangling"] =
|
json["numPatternsWithArticulationPoints"] = numberOfPatternsWithArticulationPoints;
|
||||||
// numberOfPatternsWithADanglingEdgeOrNode;
|
json["numValidPatterns"] = numberOfValidPatterns;
|
||||||
// json["numPatternsWithArticulationPoints"] =
|
|
||||||
// numberOfPatternsWithArticulationPoints;
|
return json;
|
||||||
// json["numValidPatterns"] = numberOfValidPatterns;
|
}
|
||||||
|
|
||||||
// return json;
|
|
||||||
// }
|
|
||||||
void print(const std::string &setupString,
|
void print(const std::string &setupString,
|
||||||
const std::filesystem::path &directoryPath) const {
|
const std::filesystem::path &directoryPath) const {
|
||||||
std::cout << "The setup " << setupString << std::endl;
|
std::cout << "The setup " << setupString << std::endl;
|
||||||
|
@ -112,20 +110,37 @@ class TopologyEnumerator {
|
||||||
<< " patterns found with a dangling node or edge" << std::endl;
|
<< " patterns found with a dangling node or edge" << std::endl;
|
||||||
std::cout << numberOfPatternsWithArticulationPoints
|
std::cout << numberOfPatternsWithArticulationPoints
|
||||||
<< " patterns found with an articulation point" << std::endl;
|
<< " patterns found with an articulation point" << std::endl;
|
||||||
std::cout << numberOfValidPatterns << " valid patterns were found"
|
std::cout << numberOfValidPatterns << " valid patterns were found" << std::endl;
|
||||||
<< std::endl;
|
if (!directoryPath.empty()) {
|
||||||
// if (!directoryPath.empty()) {
|
auto json = convertToJson();
|
||||||
// auto json = convertToJson();
|
|
||||||
|
|
||||||
// std::ofstream file;
|
std::ofstream file;
|
||||||
// file.open(std::filesystem::path(directoryPath)
|
file.open(std::filesystem::path(directoryPath).append("statistics.csv").string());
|
||||||
// .append("statistics.csv")
|
file << "setup," << setupString << "\n";
|
||||||
// .string());
|
for (const auto &el : json.items()) {
|
||||||
// file << "setup," << setupString << "\n";
|
file << el.key() << ",";
|
||||||
// for (const auto &el : json.items()) {
|
}
|
||||||
// file << el.key() << "," << el.value() << "\n";
|
file << "\n";
|
||||||
// }
|
for (const auto &el : json.items()) {
|
||||||
// }
|
file << el.value() << ",";
|
||||||
|
}
|
||||||
|
file << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
numberOfPossibleEdges = 0;
|
||||||
|
numberOfCoincideEdges = 0;
|
||||||
|
numberOfDuplicateEdges = 0;
|
||||||
|
numberOfValidEdges = 0;
|
||||||
|
numberOfIntersectingEdgePairs = 0;
|
||||||
|
numberOfPatterns = 0;
|
||||||
|
numberOfPatternsWithIntersectingEdges = 0;
|
||||||
|
numberOfPatternsWithMoreThanASingleCC = 0;
|
||||||
|
numberOfPatternsWithADanglingEdgeOrNode = 0;
|
||||||
|
numberOfPatternsWithArticulationPoints = 0;
|
||||||
|
numberOfValidPatterns = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -173,8 +188,10 @@ private:
|
||||||
const size_t &numberOfDesiredEdges,
|
const size_t &numberOfDesiredEdges,
|
||||||
const std::filesystem::path &resultsPath,
|
const std::filesystem::path &resultsPath,
|
||||||
const std::vector<vcg::Point3d> &vertices,
|
const std::vector<vcg::Point3d> &vertices,
|
||||||
const std::unordered_map<size_t, std::unordered_set<size_t>>
|
const std::unordered_map<size_t, std::unordered_set<size_t>> &intersectingEdges,
|
||||||
&intersectingEdges,
|
|
||||||
const std::vector<vcg::Point2i> &validEdges);
|
const std::vector<vcg::Point2i> &validEdges);
|
||||||
|
void exportPattern(const std::filesystem::path &saveToPath,
|
||||||
|
PatternGeometry &patternGeometry,
|
||||||
|
const bool saveTilledPattern) const;
|
||||||
};
|
};
|
||||||
#endif // TOPOLOGYENUMERATOR_HPP
|
#endif // TOPOLOGYENUMERATOR_HPP
|
||||||
|
|
Loading…
Reference in New Issue