Refactoring
This commit is contained in:
parent
c9fc6ccd08
commit
282e1609c8
|
@ -1,7 +1,10 @@
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(MySources)
|
project(MySources)
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
file(GLOB MySourcesFiles ${CMAKE_CURRENT_LIST_DIR}/*.hpp ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
|
||||||
|
add_library(${PROJECT_NAME} ${MySourcesFiles} )
|
||||||
|
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
||||||
|
|
||||||
#Download external dependencies NOTE: If the user has one of these libs it shouldn't be downloaded again.
|
#Download external dependencies NOTE: If the user has one of these libs it shouldn't be downloaded again.
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake/DownloadProject.cmake)
|
include(${CMAKE_CURRENT_LIST_DIR}/cmake/DownloadProject.cmake)
|
||||||
if (CMAKE_VERSION VERSION_LESS 3.2)
|
if (CMAKE_VERSION VERSION_LESS 3.2)
|
||||||
|
@ -26,16 +29,18 @@ if(${USE_POLYSCOPE})
|
||||||
)
|
)
|
||||||
add_subdirectory(${POLYSCOPE_SOURCE_DIR} ${POLYSCOPE_BINARY_DIR})
|
add_subdirectory(${POLYSCOPE_SOURCE_DIR} ${POLYSCOPE_BINARY_DIR})
|
||||||
add_compile_definitions(POLYSCOPE_DEFINED)
|
add_compile_definitions(POLYSCOPE_DEFINED)
|
||||||
|
target_sources(${PROJECT_NAME} PUBLIC ${POLYSCOPE_SOURCE_DIR}/deps/imgui/imgui/misc/cpp/imgui_stdlib.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
##vcglib devel branch
|
##vcglib devel branch
|
||||||
download_project(PROJ vcglib_devel
|
download_project(PROJ vcglib_devel
|
||||||
GIT_REPOSITORY https://github.com/IasonManolas/vcglib.git
|
GIT_REPOSITORY https://gitea-s2i2s.isti.cnr.it/manolas/vcglib.git
|
||||||
GIT_TAG devel
|
GIT_TAG devel
|
||||||
PREFIX ${EXTERNAL_DEPS_DIR}
|
PREFIX ${EXTERNAL_DEPS_DIR}
|
||||||
${UPDATE_DISCONNECTED_IF_AVAILABLE}
|
${UPDATE_DISCONNECTED_IF_AVAILABLE}
|
||||||
)
|
)
|
||||||
add_subdirectory(${vcglib_devel_SOURCE_DIR} ${vcglib_devel_BINARY_DIR})
|
add_subdirectory(${vcglib_devel_SOURCE_DIR} ${vcglib_devel_BINARY_DIR})
|
||||||
|
target_sources(${PROJECT_NAME} PUBLIC ${vcglib_devel_SOURCE_DIR}/wrap/ply/plylib.cpp)
|
||||||
|
|
||||||
##matplot++ lib
|
##matplot++ lib
|
||||||
set(MATPLOTPLUSPLUS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/matplot)
|
set(MATPLOTPLUSPLUS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/matplot)
|
||||||
|
@ -77,23 +82,26 @@ if(MSVC)
|
||||||
add_compile_definitions(_HAS_STD_BYTE=0)
|
add_compile_definitions(_HAS_STD_BYTE=0)
|
||||||
endif(MSVC)
|
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)
|
|
||||||
add_library(${PROJECT_NAME} ${MySourcesFiles} ${vcglib_devel_SOURCE_DIR}/wrap/ply/plylib.cpp)
|
|
||||||
target_include_directories(${PROJECT_NAME}
|
|
||||||
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/boost_graph
|
|
||||||
PUBLIC ${vcglib_devel_SOURCE_DIR}
|
|
||||||
PUBLIC ${threed-beam-fea_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
if(${MYSOURCES_STATIC_LINK})
|
if(${MYSOURCES_STATIC_LINK})
|
||||||
message("Linking statically")
|
message("Linking statically")
|
||||||
target_link_libraries(${PROJECT_NAME} -static Eigen3::Eigen matplot ThreedBeamFEA ${TBB_BINARY_DIR}/libtbb_static.a pthread gfortran quadmath)
|
target_link_libraries(${PROJECT_NAME} PUBLIC -static Eigen3::Eigen matplot ThreedBeamFEA ${TBB_BINARY_DIR}/libtbb_static.a #[[tbb_static]] pthread gfortran quadmath)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} Eigen3::Eigen matplot ThreedBeamFEA tbb pthread)
|
# set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC Eigen3::Eigen matplot ThreedBeamFEA tbb pthread)
|
||||||
if(${USE_POLYSCOPE})
|
if(${USE_POLYSCOPE})
|
||||||
target_link_libraries(${PROJECT_NAME} polyscope)
|
message("Using polyscope")
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC polyscope)
|
||||||
endif()
|
endif()
|
||||||
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)
|
||||||
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/boost_graph
|
||||||
|
PUBLIC ${vcglib_devel_SOURCE_DIR}
|
||||||
|
# PUBLIC ${threed-beam-fea_SOURCE_DIR}
|
||||||
|
PUBLIC ThreedBeamFEA
|
||||||
|
PUBLIC matplot
|
||||||
|
)
|
||||||
|
|
||||||
if(USE_ENSMALLEN)
|
if(USE_ENSMALLEN)
|
||||||
##ENSMALLEN
|
##ENSMALLEN
|
||||||
|
@ -113,5 +121,5 @@ if(USE_ENSMALLEN)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC armadillo ensmallen)
|
target_link_libraries(${PROJECT_NAME} PUBLIC armadillo ensmallen)
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${ARMADILLO_SOURCE_DIR}/include)
|
target_include_directories(${PROJECT_NAME} PUBLIC ${ARMADILLO_SOURCE_DIR}/include ${ENSMALLEN_SOURCE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1889,7 +1889,7 @@ void DRMSimulationModel::printCurrentState() const
|
||||||
void DRMSimulationModel::printDebugInfo() const
|
void DRMSimulationModel::printDebugInfo() const
|
||||||
{
|
{
|
||||||
std::cout << pMesh->elements[0].rigidity.toString() << std::endl;
|
std::cout << pMesh->elements[0].rigidity.toString() << std::endl;
|
||||||
std::cout << "Number of dampings:" << numOfDampings << endl;
|
std::cout << "Number of dampings:" << numOfDampings << std::endl;
|
||||||
printCurrentState();
|
printCurrentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ private:
|
||||||
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>> &fixedVertices);
|
const std::unordered_map<VertexIndex, std::unordered_set<DoFType>> &fixedVertices);
|
||||||
|
|
||||||
#ifdef POLYSCOPE_DEFINED
|
#ifdef POLYSCOPE_DEFINED
|
||||||
void draw(const string &screenshotsFolder= {});
|
void draw(const std::string &screenshotsFolder = {});
|
||||||
#endif
|
#endif
|
||||||
void
|
void
|
||||||
updateNodalInternalForce(Vector6d &nodalInternalForce,
|
updateNodalInternalForce(Vector6d &nodalInternalForce,
|
||||||
|
|
56
edgemesh.cpp
56
edgemesh.cpp
|
@ -25,7 +25,7 @@ Eigen::MatrixX3d VCGEdgeMesh::getEigenEdgeNormals() const {
|
||||||
return eigenEdgeNormals;
|
return eigenEdgeNormals;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCGEdgeMesh::save(const string &plyFilename)
|
bool VCGEdgeMesh::save(const std::string &plyFilename)
|
||||||
{
|
{
|
||||||
std::string filename = plyFilename;
|
std::string filename = plyFilename;
|
||||||
if (filename.empty()) {
|
if (filename.empty()) {
|
||||||
|
@ -197,36 +197,36 @@ bool VCGEdgeMesh::createSpanGrid(const size_t desiredWidth,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCGEdgeMesh::load(const string &plyFilename) {
|
bool VCGEdgeMesh::load(const std::string &plyFilename)
|
||||||
|
{
|
||||||
|
std::string usedPath = plyFilename;
|
||||||
|
if (std::filesystem::path(plyFilename).is_relative()) {
|
||||||
|
usedPath = std::filesystem::absolute(plyFilename).string();
|
||||||
|
}
|
||||||
|
assert(std::filesystem::exists(usedPath));
|
||||||
|
Clear();
|
||||||
|
// if (!loadUsingNanoply(usedPath)) {
|
||||||
|
// std::cerr << "Error: Unable to open " + usedPath << std::endl;
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
if (!loadUsingDefaultLoader(usedPath)) {
|
||||||
|
std::cerr << "Error: Unable to open " + usedPath << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::string usedPath = plyFilename;
|
getEdges(eigenEdges);
|
||||||
if (std::filesystem::path(plyFilename).is_relative()) {
|
getVertices(eigenVertices);
|
||||||
usedPath = std::filesystem::absolute(plyFilename).string();
|
vcg::tri::UpdateTopology<VCGEdgeMesh>::VertexEdge(*this);
|
||||||
}
|
label = std::filesystem::path(plyFilename).stem().string();
|
||||||
assert(std::filesystem::exists(usedPath));
|
|
||||||
Clear();
|
|
||||||
// if (!loadUsingNanoply(usedPath)) {
|
|
||||||
// std::cerr << "Error: Unable to open " + usedPath << std::endl;
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
if (!loadUsingDefaultLoader(usedPath)) {
|
|
||||||
std::cerr << "Error: Unable to open " + usedPath << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getEdges(eigenEdges);
|
const bool printDebugInfo = false;
|
||||||
getVertices(eigenVertices);
|
if (printDebugInfo) {
|
||||||
vcg::tri::UpdateTopology<VCGEdgeMesh>::VertexEdge(*this);
|
std::cout << plyFilename << " was loaded successfuly." << std::endl;
|
||||||
label = std::filesystem::path(plyFilename).stem().string();
|
std::cout << "Mesh has " << EN() << " edges." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
const bool printDebugInfo = false;
|
label = std::filesystem::path(plyFilename).stem().string();
|
||||||
if (printDebugInfo) {
|
return true;
|
||||||
std::cout << plyFilename << " was loaded successfuly." << std::endl;
|
|
||||||
std::cout << "Mesh has " << EN() << " edges." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
label=std::filesystem::path(plyFilename).stem().string();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool VCGEdgeMesh::loadUsingNanoply(const std::string &plyFilename) {
|
//bool VCGEdgeMesh::loadUsingNanoply(const std::string &plyFilename) {
|
||||||
|
|
|
@ -108,8 +108,6 @@ SimulationResults LinearSimulationModel::getResults(
|
||||||
Eigen::Quaternion<double> q_nz;
|
Eigen::Quaternion<double> q_nz;
|
||||||
q_nz = Eigen::AngleAxis<double>(nodalDisplacement[5], Eigen::Vector3d(0, 0, 1));
|
q_nz = Eigen::AngleAxis<double>(nodalDisplacement[5], Eigen::Vector3d(0, 0, 1));
|
||||||
results.rotationalDisplacementQuaternion[vi] = q_nx * q_ny * q_nz;
|
results.rotationalDisplacementQuaternion[vi] = q_nx * q_ny * q_nz;
|
||||||
// results.rotationalDisplacementQuaternion[vi] = q_nz * q_ny * q_nx;
|
|
||||||
// results.rotationalDisplacementQuaternion[vi] = q_nz * q_nx * q_ny;
|
|
||||||
}
|
}
|
||||||
results.setLabelPrefix("Linear");
|
results.setLabelPrefix("Linear");
|
||||||
|
|
||||||
|
@ -214,7 +212,11 @@ SimulationResults LinearSimulationModel::executeSimulation(
|
||||||
const std::shared_ptr<SimulationJob> &pSimulationJob)
|
const std::shared_ptr<SimulationJob> &pSimulationJob)
|
||||||
{
|
{
|
||||||
assert(pSimulationJob->pMesh->VN() != 0);
|
assert(pSimulationJob->pMesh->VN() != 0);
|
||||||
if (!simulator.wasInitialized()) {
|
const bool wasInitializedWithDifferentStructure = pSimulationJob->pMesh->EN()
|
||||||
|
!= simulator.structure.elems.size()
|
||||||
|
|| pSimulationJob->pMesh->VN()
|
||||||
|
!= simulator.structure.nodes.size();
|
||||||
|
if (!simulator.wasInitialized() || wasInitializedWithDifferentStructure) {
|
||||||
setStructure(pSimulationJob->pMesh);
|
setStructure(pSimulationJob->pMesh);
|
||||||
}
|
}
|
||||||
// printInfo(job);
|
// printInfo(job);
|
||||||
|
|
|
@ -34,9 +34,9 @@ struct Colors
|
||||||
|
|
||||||
struct xRange
|
struct xRange
|
||||||
{
|
{
|
||||||
std::string label;
|
std::string label{};
|
||||||
double min;
|
double min{0};
|
||||||
double max;
|
double max{0};
|
||||||
|
|
||||||
inline bool operator<(const xRange &other) { return label < other.label; }
|
inline bool operator<(const xRange &other) { return label < other.label; }
|
||||||
std::string toString() const
|
std::string toString() const
|
||||||
|
@ -60,120 +60,321 @@ struct xRange
|
||||||
{
|
{
|
||||||
return label == xrange.label && min == xrange.min && max == xrange.max;
|
return label == xrange.label && min == xrange.min && max == xrange.max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::tuple<std::string, double, double> toTuple() const
|
||||||
|
{
|
||||||
|
return std::make_tuple(label, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const std::tuple<std::string, double, double> &inputTuple)
|
||||||
|
{
|
||||||
|
if (std::get<1>(inputTuple) > std::get<2>(inputTuple)) {
|
||||||
|
std::cerr
|
||||||
|
<< "Invalid xRange tuple. Second argument(min) cant be smaller than the third(max)"
|
||||||
|
<< std::endl;
|
||||||
|
std::terminate();
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
std::tie(label, min, max) = inputTuple;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum OptimizationParameterIndex { E, A, I2, I3, J, R, Theta, NumberOfOptimizationParameters };
|
enum OptimizationParameterIndex { E, A, I2, I3, J, R, Theta, NumberOfOptimizationVariables };
|
||||||
|
|
||||||
|
inline int getParameterIndex(const std::string &s)
|
||||||
|
{
|
||||||
|
if ("E" == s) {
|
||||||
|
return E;
|
||||||
|
} else if ("A" == s) {
|
||||||
|
return A;
|
||||||
|
} else if ("I2" == s) {
|
||||||
|
return I2;
|
||||||
|
} else if ("I3" == s) {
|
||||||
|
return I3;
|
||||||
|
} else if ("J" == s) {
|
||||||
|
return J;
|
||||||
|
} else if ("R" == s || "HexSize" == s) {
|
||||||
|
return R;
|
||||||
|
} else if ("Theta" == s || "HexAngle" == s) {
|
||||||
|
return Theta;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Input is not recognized as a valid optimization variable index:" << s
|
||||||
|
<< std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Settings
|
struct Settings
|
||||||
{
|
{
|
||||||
std::filesystem::path intermediateResultsDirectoryPath;
|
inline static std::string defaultFilename{"OptimizationSettings.json"};
|
||||||
std::vector<std::vector<OptimizationParameterIndex>> optimizationVariables;
|
std::vector<std::vector<OptimizationParameterIndex>> optimizationStrategy;
|
||||||
|
std::optional<std::vector<double>>
|
||||||
|
optimizationVariablesGroupsWeights; //TODO:should be removed in the future if not a splitting strategy is used for the optimization
|
||||||
enum NormalizationStrategy { NonNormalized, Epsilon };
|
enum NormalizationStrategy { NonNormalized, Epsilon };
|
||||||
std::vector<xRange> parameterRanges;
|
inline static std::vector<std::string> normalizationStrategyStrings{"NonNormalized", "Epsilon"};
|
||||||
inline static vector<std::string> normalizationStrategyStrings{"NonNormalized", "Epsilon"};
|
|
||||||
int numberOfFunctionCalls{100000};
|
|
||||||
double solverAccuracy{1e-2};
|
|
||||||
NormalizationStrategy normalizationStrategy{Epsilon};
|
NormalizationStrategy normalizationStrategy{Epsilon};
|
||||||
double translationNormalizationParameter{0.003};
|
std::array<xRange, NumberOfOptimizationVariables> variablesRanges;
|
||||||
double rotationNormalizationParameter{3};
|
int numberOfFunctionCalls{100000};
|
||||||
|
double solverAccuracy{1e-3};
|
||||||
|
double translationNormalizationEpsilon{1e-4};
|
||||||
|
double rotationNormalizationEpsilon{vcg::math::ToRad(3.0)};
|
||||||
struct ObjectiveWeights
|
struct ObjectiveWeights
|
||||||
{
|
{
|
||||||
double translational{1};
|
double translational{1};
|
||||||
double rotational{1};
|
double rotational{1};
|
||||||
} objectiveWeights;
|
bool operator==(const ObjectiveWeights &other) const
|
||||||
|
{
|
||||||
|
return this->translational == other.translational
|
||||||
|
&& this->rotational == other.rotational;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::array<ObjectiveWeights, NumberOfBaseSimulationScenarios> perBaseScenarioObjectiveWeights;
|
||||||
|
std::array<std::pair<double, double>, NumberOfBaseSimulationScenarios>
|
||||||
|
convertObjectiveWeightsToPairs() const
|
||||||
|
{
|
||||||
|
std::array<std::pair<double, double>, NumberOfBaseSimulationScenarios> objectiveWeightsPairs;
|
||||||
|
for (int baseScenario = Axial; baseScenario != NumberOfBaseSimulationScenarios;
|
||||||
|
baseScenario++) {
|
||||||
|
objectiveWeightsPairs[baseScenario]
|
||||||
|
= std::make_pair(perBaseScenarioObjectiveWeights[baseScenario].translational,
|
||||||
|
perBaseScenarioObjectiveWeights[baseScenario].rotational);
|
||||||
|
}
|
||||||
|
return objectiveWeightsPairs;
|
||||||
|
}
|
||||||
|
|
||||||
struct JsonKeys
|
struct JsonKeys
|
||||||
{
|
{
|
||||||
inline static std::string filename{"OptimizationSettings.json"};
|
inline static std::string OptimizationStrategy{"OptimizationStrategy"};
|
||||||
|
inline static std::string OptimizationStrategyGroupWeights{
|
||||||
|
"OptimizationStrategyGroupWeights"};
|
||||||
inline static std::string OptimizationVariables{"OptimizationVariables"};
|
inline static std::string OptimizationVariables{"OptimizationVariables"};
|
||||||
inline static std::string NumberOfFunctionCalls{"NumberOfFunctionCalls"};
|
inline static std::string NumberOfFunctionCalls{"NumberOfFunctionCalls"};
|
||||||
inline static std::string SolverAccuracy{"SolverAccuracy"};
|
inline static std::string SolverAccuracy{"SolverAccuracy"};
|
||||||
inline static std::string TranslationalObjectiveWeight{"TransObjWeight"};
|
inline static std::string ObjectiveWeights{"ObjectiveWeight"};
|
||||||
inline static std::string OptimizationParameters{"OptimizationParameters"};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void setDefault()
|
||||||
|
{
|
||||||
|
ReducedPatternOptimization::xRange beamE{"E", 0.001, 1000};
|
||||||
|
ReducedPatternOptimization::xRange beamA{"A", 0.001, 1000};
|
||||||
|
ReducedPatternOptimization::xRange beamI2{"I2", 0.001, 1000};
|
||||||
|
ReducedPatternOptimization::xRange beamI3{"I3", 0.001, 1000};
|
||||||
|
ReducedPatternOptimization::xRange beamJ{"J", 0.001, 1000};
|
||||||
|
ReducedPatternOptimization::xRange innerHexagonSize{"R", 0.05, 0.95};
|
||||||
|
ReducedPatternOptimization::xRange innerHexagonAngle{"Theta", -30.0, 30.0};
|
||||||
|
variablesRanges = {beamE, beamA, beamI2, beamI3, beamJ, innerHexagonSize, innerHexagonAngle};
|
||||||
|
numberOfFunctionCalls = 100000;
|
||||||
|
|
||||||
|
enum OptimizationParameterComparisonScenarioIndex {
|
||||||
|
AllVar,
|
||||||
|
GeoYM,
|
||||||
|
MatGeo,
|
||||||
|
YMMat_Geo,
|
||||||
|
YM_MatGeo,
|
||||||
|
MatGeo_YM,
|
||||||
|
Geo_YM_Mat,
|
||||||
|
YM_Geo_Mat,
|
||||||
|
Geo_Mat,
|
||||||
|
YMGeo_Mat,
|
||||||
|
NumberOfScenarios
|
||||||
|
};
|
||||||
|
const std::vector<
|
||||||
|
std::vector<std::vector<ReducedPatternOptimization::OptimizationParameterIndex>>>
|
||||||
|
optimizationParameters = [&]() {
|
||||||
|
std::vector<
|
||||||
|
std::vector<std::vector<ReducedPatternOptimization::OptimizationParameterIndex>>>
|
||||||
|
optimizationParameters(NumberOfScenarios);
|
||||||
|
using namespace ReducedPatternOptimization;
|
||||||
|
optimizationParameters[AllVar] = {{E, A, I2, I3, J, R, Theta}};
|
||||||
|
optimizationParameters[GeoYM] = {{R, Theta, E}};
|
||||||
|
optimizationParameters[MatGeo] = {{A, I2, I3, J, R, Theta}};
|
||||||
|
optimizationParameters[YMMat_Geo] = {{E, A, I2, I3, J}, {R, Theta}};
|
||||||
|
optimizationParameters[YM_MatGeo] = {{E}, {A, I2, I3, J, R, Theta}};
|
||||||
|
optimizationParameters[MatGeo_YM] = {{A, I2, I3, J, R, Theta}, {E}};
|
||||||
|
optimizationParameters[Geo_YM_Mat] = {{R, Theta}, {E}, {A, I2, I3, J}};
|
||||||
|
optimizationParameters[YM_Geo_Mat] = {{E}, {R, Theta}, {A, I2, I3, J}};
|
||||||
|
optimizationParameters[Geo_Mat] = {{R, Theta}, {A, I2, I3, J}};
|
||||||
|
optimizationParameters[YMGeo_Mat] = {{E, R, Theta}, {A, I2, I3, J}};
|
||||||
|
return optimizationParameters;
|
||||||
|
}();
|
||||||
|
|
||||||
|
constexpr OptimizationParameterComparisonScenarioIndex scenario = MatGeo;
|
||||||
|
optimizationStrategy = optimizationParameters[scenario];
|
||||||
|
if (scenario == YMGeo_Mat) {
|
||||||
|
optimizationVariablesGroupsWeights = {0.15, 0.85};
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizationStrategy = ReducedPatternOptimization::Settings::NormalizationStrategy::Epsilon;
|
||||||
|
//#ifdef POLYSCOPE_DEFINED
|
||||||
|
//#else
|
||||||
|
translationNormalizationEpsilon = 4e-3;
|
||||||
|
rotationNormalizationEpsilon = vcg::math::ToRad(3.0);
|
||||||
|
|
||||||
|
// translationNormalizationParameter = 0;
|
||||||
|
// rotationNormalizationParameter = 0;
|
||||||
|
// translationNormalizationParameter = 1e-3;
|
||||||
|
// rotationNormalizationParameter = vcg::math::ToRad(3.0);
|
||||||
|
// translationNormalizationParameter = 5e-2;
|
||||||
|
// rotationNormalizationParameter = vcg::math::ToRad(3.0);
|
||||||
|
//#endif
|
||||||
|
solverAccuracy = 1e-2;
|
||||||
|
//TODO refactor that
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Axial].translational = 1.5;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Axial].rotational
|
||||||
|
= 2 - perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Axial].translational;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Shear].translational = 1.5;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Shear].rotational
|
||||||
|
= 2 - perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Shear].translational;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Bending].translational = 1.2;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Bending].rotational
|
||||||
|
= 2
|
||||||
|
- perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Bending].translational;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Dome].translational = 1.95;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Dome].rotational
|
||||||
|
= 2 - perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Dome].translational;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Saddle].translational = 1.2;
|
||||||
|
perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Saddle].rotational
|
||||||
|
= 2 - perBaseScenarioObjectiveWeights[ReducedPatternOptimization::Saddle].translational;
|
||||||
|
}
|
||||||
|
|
||||||
void save(const std::filesystem::path &saveToPath)
|
void save(const std::filesystem::path &saveToPath)
|
||||||
{
|
{
|
||||||
assert(std::filesystem::is_directory(saveToPath));
|
assert(std::filesystem::is_directory(saveToPath));
|
||||||
|
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
//write x ranges
|
json[JsonKeys::OptimizationStrategy] = optimizationStrategy;
|
||||||
for (size_t xRangeIndex = 0; xRangeIndex < parameterRanges.size(); xRangeIndex++) {
|
if (optimizationVariablesGroupsWeights.has_value()) {
|
||||||
const auto &xRange = parameterRanges[xRangeIndex];
|
json[JsonKeys::OptimizationStrategyGroupWeights] = optimizationVariablesGroupsWeights
|
||||||
json[JsonKeys::OptimizationVariables + "_" + std::to_string(xRangeIndex)]
|
.value();
|
||||||
= xRange.toString();
|
|
||||||
}
|
}
|
||||||
|
//write x ranges
|
||||||
|
const std::array<std::tuple<std::string, double, double>, NumberOfOptimizationVariables>
|
||||||
|
xRangesAsTuples = [=]() {
|
||||||
|
std::array<std::tuple<std::string, double, double>, NumberOfOptimizationVariables>
|
||||||
|
xRangesAsTuples;
|
||||||
|
for (int optimizationParameterIndex = E;
|
||||||
|
optimizationParameterIndex != NumberOfOptimizationVariables;
|
||||||
|
optimizationParameterIndex++) {
|
||||||
|
xRangesAsTuples[optimizationParameterIndex]
|
||||||
|
= variablesRanges[optimizationParameterIndex].toTuple();
|
||||||
|
}
|
||||||
|
return xRangesAsTuples;
|
||||||
|
}();
|
||||||
|
json[JsonKeys::OptimizationVariables] = xRangesAsTuples;
|
||||||
|
// for (size_t xRangeIndex = 0; xRangeIndex < variablesRanges.size(); xRangeIndex++) {
|
||||||
|
// const auto &xRange = variablesRanges[xRangeIndex];
|
||||||
|
// json[JsonKeys::OptimizationVariables + "_" + std::to_string(xRangeIndex)]
|
||||||
|
// = xRange.toString();
|
||||||
|
// }
|
||||||
|
|
||||||
json[JsonKeys::NumberOfFunctionCalls] = numberOfFunctionCalls;
|
json[JsonKeys::NumberOfFunctionCalls] = numberOfFunctionCalls;
|
||||||
json[JsonKeys::SolverAccuracy] = solverAccuracy;
|
json[JsonKeys::SolverAccuracy] = solverAccuracy;
|
||||||
json[JsonKeys::TranslationalObjectiveWeight] = objectiveWeights.translational;
|
//Objective weights
|
||||||
json[JsonKeys::OptimizationParameters] = optimizationVariables;
|
std::array<std::pair<double, double>, NumberOfBaseSimulationScenarios> objectiveWeightsPairs;
|
||||||
|
std::transform(perBaseScenarioObjectiveWeights.begin(),
|
||||||
|
perBaseScenarioObjectiveWeights.end(),
|
||||||
|
objectiveWeightsPairs.begin(),
|
||||||
|
[](const ObjectiveWeights &objectiveWeights) {
|
||||||
|
return std::make_pair(objectiveWeights.translational,
|
||||||
|
objectiveWeights.rotational);
|
||||||
|
});
|
||||||
|
json[JsonKeys::ObjectiveWeights] = objectiveWeightsPairs;
|
||||||
|
|
||||||
std::filesystem::path jsonFilePath(
|
std::filesystem::path jsonFilePath(
|
||||||
std::filesystem::path(saveToPath).append(JsonKeys::filename));
|
std::filesystem::path(saveToPath).append(defaultFilename));
|
||||||
std::ofstream jsonFile(jsonFilePath.string());
|
std::ofstream jsonFile(jsonFilePath.string());
|
||||||
jsonFile << json;
|
jsonFile << json;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load(const std::filesystem::path &loadFromPath)
|
bool load(const std::filesystem::path &jsonFilepath)
|
||||||
{
|
{
|
||||||
assert(std::filesystem::is_directory(loadFromPath));
|
|
||||||
//Load optimal X
|
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
std::filesystem::path jsonFilepath(
|
|
||||||
std::filesystem::path(loadFromPath).append(JsonKeys::filename));
|
|
||||||
if (!std::filesystem::exists(jsonFilepath)) {
|
if (!std::filesystem::exists(jsonFilepath)) {
|
||||||
|
std::cerr << "Optimization settings could not be loaded because input filepath does "
|
||||||
|
"not exist:"
|
||||||
|
<< jsonFilepath << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::ifstream ifs(jsonFilepath);
|
std::ifstream ifs(jsonFilepath);
|
||||||
ifs >> json;
|
ifs >> json;
|
||||||
|
|
||||||
|
if (json.contains(JsonKeys::OptimizationStrategy)) {
|
||||||
|
optimizationStrategy
|
||||||
|
= std::vector<std::vector<ReducedPatternOptimization::OptimizationParameterIndex>>(
|
||||||
|
(json.at(JsonKeys::OptimizationStrategy)));
|
||||||
|
}
|
||||||
|
if (json.contains(JsonKeys::OptimizationStrategyGroupWeights)) {
|
||||||
|
optimizationVariablesGroupsWeights = std::vector<double>(
|
||||||
|
json[JsonKeys::OptimizationStrategyGroupWeights]);
|
||||||
|
}
|
||||||
//read x ranges
|
//read x ranges
|
||||||
size_t xRangeIndex = 0;
|
if (json.contains(JsonKeys::OptimizationVariables)) {
|
||||||
while (true) {
|
const std::array<std::tuple<std::string, double, double>, NumberOfOptimizationVariables>
|
||||||
const std::string jsonXRangeKey = JsonKeys::OptimizationVariables + "_"
|
xRangesAsTuples = json.at(JsonKeys::OptimizationVariables);
|
||||||
+ std::to_string(xRangeIndex);
|
for (const auto &rangeTuple : xRangesAsTuples) {
|
||||||
if (!json.contains(jsonXRangeKey)) {
|
variablesRanges[getParameterIndex(std::get<0>(rangeTuple))].set(rangeTuple);
|
||||||
break;
|
}
|
||||||
|
} else { //NOTE:legacy compatibility
|
||||||
|
size_t xRangeIndex = 0;
|
||||||
|
while (true) {
|
||||||
|
const std::string jsonXRangeKey = JsonKeys::OptimizationVariables + "_"
|
||||||
|
+ std::to_string(xRangeIndex++);
|
||||||
|
if (!json.contains(jsonXRangeKey)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xRange x;
|
||||||
|
x.fromString(json.at(jsonXRangeKey));
|
||||||
|
variablesRanges[getParameterIndex(x.label)] = x;
|
||||||
}
|
}
|
||||||
xRange x;
|
|
||||||
x.fromString(json.at(jsonXRangeKey));
|
|
||||||
parameterRanges.push_back(x);
|
|
||||||
xRangeIndex++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optimizationVariables
|
|
||||||
= std::vector<std::vector<ReducedPatternOptimization::OptimizationParameterIndex>>(
|
|
||||||
(json.at(JsonKeys::OptimizationParameters)));
|
|
||||||
numberOfFunctionCalls = json.at(JsonKeys::NumberOfFunctionCalls);
|
numberOfFunctionCalls = json.at(JsonKeys::NumberOfFunctionCalls);
|
||||||
solverAccuracy = json.at(JsonKeys::SolverAccuracy);
|
solverAccuracy = json.at(JsonKeys::SolverAccuracy);
|
||||||
objectiveWeights.translational = json.at(JsonKeys::TranslationalObjectiveWeight);
|
//Objective weights
|
||||||
objectiveWeights.rotational = 2 - objectiveWeights.translational;
|
if (json.contains(JsonKeys::ObjectiveWeights)) {
|
||||||
|
std::array<std::pair<double, double>, NumberOfBaseSimulationScenarios>
|
||||||
|
objectiveWeightsPairs = json.at(JsonKeys::ObjectiveWeights);
|
||||||
|
std::transform(objectiveWeightsPairs.begin(),
|
||||||
|
objectiveWeightsPairs.end(),
|
||||||
|
perBaseScenarioObjectiveWeights.begin(),
|
||||||
|
[](const std::pair<double, double> &objectiveWeightsPair) {
|
||||||
|
return ObjectiveWeights{objectiveWeightsPair.first,
|
||||||
|
objectiveWeightsPair.second};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// perBaseScenarioObjectiveWeights = json.at(JsonKeys::ObjectiveWeights);
|
||||||
|
// objectiveWeights.translational = json.at(JsonKeys::ObjectiveWeights);
|
||||||
|
// objectiveWeights.rotational = 2 - objectiveWeights.translational;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString() const
|
std::string toString() const
|
||||||
{
|
{
|
||||||
std::string settingsString;
|
std::string settingsString;
|
||||||
if (!parameterRanges.empty()) {
|
if (!variablesRanges.empty()) {
|
||||||
std::string xRangesString;
|
std::string xRangesString;
|
||||||
for (const xRange &range : parameterRanges) {
|
for (const xRange &range : variablesRanges) {
|
||||||
xRangesString += range.toString() + " ";
|
xRangesString += range.toString() + " ";
|
||||||
}
|
}
|
||||||
settingsString += xRangesString;
|
settingsString += xRangesString;
|
||||||
}
|
}
|
||||||
settingsString += "FuncCalls=" + std::to_string(numberOfFunctionCalls)
|
settingsString += "FuncCalls=" + std::to_string(numberOfFunctionCalls)
|
||||||
+ " Accuracy=" + std::to_string(solverAccuracy)
|
+ " Accuracy=" + std::to_string(solverAccuracy);
|
||||||
+ " TransWeight=" + std::to_string(objectiveWeights.translational)
|
for (int baseScenario = Axial; baseScenario != NumberOfBaseSimulationScenarios;
|
||||||
+ " RotWeight=" + std::to_string(objectiveWeights.rotational);
|
baseScenario++) {
|
||||||
|
+" W_t=" + std::to_string(perBaseScenarioObjectiveWeights[baseScenario].translational)
|
||||||
|
+ " W_r="
|
||||||
|
+ std::to_string(perBaseScenarioObjectiveWeights[baseScenario].rotational);
|
||||||
|
}
|
||||||
|
|
||||||
return settingsString;
|
return settingsString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeHeaderTo(csvFile &os) const
|
void writeHeaderTo(csvFile &os) const
|
||||||
{
|
{
|
||||||
if (!parameterRanges.empty()) {
|
if (!variablesRanges.empty()) {
|
||||||
for (const xRange &range : parameterRanges) {
|
for (const xRange &range : variablesRanges) {
|
||||||
os << range.label + " max";
|
os << range.label + " max";
|
||||||
os << range.label + " min";
|
os << range.label + " min";
|
||||||
}
|
}
|
||||||
|
@ -181,16 +382,15 @@ struct Settings
|
||||||
os << "Function Calls";
|
os << "Function Calls";
|
||||||
os << "Solution Accuracy";
|
os << "Solution Accuracy";
|
||||||
os << "Normalization strategy";
|
os << "Normalization strategy";
|
||||||
os << "Trans weight";
|
os << JsonKeys::ObjectiveWeights;
|
||||||
os << "Rot weight";
|
|
||||||
os << "Optimization parameters";
|
os << "Optimization parameters";
|
||||||
// os << std::endl;
|
// os << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSettingsTo(csvFile &os) const
|
void writeSettingsTo(csvFile &os) const
|
||||||
{
|
{
|
||||||
if (!parameterRanges.empty()) {
|
if (!variablesRanges.empty()) {
|
||||||
for (const xRange &range : parameterRanges) {
|
for (const xRange &range : variablesRanges) {
|
||||||
os << range.max;
|
os << range.max;
|
||||||
os << range.min;
|
os << range.min;
|
||||||
}
|
}
|
||||||
|
@ -198,13 +398,22 @@ struct Settings
|
||||||
os << numberOfFunctionCalls;
|
os << numberOfFunctionCalls;
|
||||||
os << solverAccuracy;
|
os << solverAccuracy;
|
||||||
os << normalizationStrategyStrings[normalizationStrategy] + "_"
|
os << normalizationStrategyStrings[normalizationStrategy] + "_"
|
||||||
+ std::to_string(translationNormalizationParameter);
|
+ std::to_string(translationNormalizationEpsilon);
|
||||||
os << objectiveWeights.translational;
|
std::string objectiveWeightsString;
|
||||||
os << objectiveWeights.rotational;
|
objectiveWeightsString += "{";
|
||||||
|
for (int baseScenario = Axial; baseScenario != NumberOfBaseSimulationScenarios;
|
||||||
|
baseScenario++) {
|
||||||
|
objectiveWeightsString
|
||||||
|
+= "{" + std::to_string(perBaseScenarioObjectiveWeights[baseScenario].translational)
|
||||||
|
+ "," + std::to_string(perBaseScenarioObjectiveWeights[baseScenario].rotational)
|
||||||
|
+ "}";
|
||||||
|
}
|
||||||
|
objectiveWeightsString += "}";
|
||||||
|
os << objectiveWeightsString;
|
||||||
|
|
||||||
//export optimization parameters
|
//export optimization parameters
|
||||||
std::vector<std::vector<int>> vv;
|
std::vector<std::vector<int>> vv;
|
||||||
for (const std::vector<OptimizationParameterIndex> &v : optimizationVariables) {
|
for (const std::vector<OptimizationParameterIndex> &v : optimizationStrategy) {
|
||||||
std::vector<int> vi;
|
std::vector<int> vi;
|
||||||
vi.reserve(v.size());
|
vi.reserve(v.size());
|
||||||
for (const OptimizationParameterIndex ¶meter : v) {
|
for (const OptimizationParameterIndex ¶meter : v) {
|
||||||
|
@ -218,12 +427,17 @@ struct Settings
|
||||||
|
|
||||||
inline bool operator==(const Settings &settings1, const Settings &settings2) noexcept
|
inline bool operator==(const Settings &settings1, const Settings &settings2) noexcept
|
||||||
{
|
{
|
||||||
|
const bool haveTheSameObjectiveWeights
|
||||||
|
= std::mismatch(settings1.perBaseScenarioObjectiveWeights.begin(),
|
||||||
|
settings1.perBaseScenarioObjectiveWeights.end(),
|
||||||
|
settings2.perBaseScenarioObjectiveWeights.begin())
|
||||||
|
.first
|
||||||
|
!= settings1.perBaseScenarioObjectiveWeights.end();
|
||||||
return settings1.numberOfFunctionCalls == settings2.numberOfFunctionCalls
|
return settings1.numberOfFunctionCalls == settings2.numberOfFunctionCalls
|
||||||
&& settings1.parameterRanges == settings2.parameterRanges
|
&& settings1.variablesRanges == settings2.variablesRanges
|
||||||
&& settings1.solverAccuracy == settings2.solverAccuracy
|
&& settings1.solverAccuracy == settings2.solverAccuracy && haveTheSameObjectiveWeights
|
||||||
&& settings1.objectiveWeights.translational == settings2.objectiveWeights.translational
|
&& settings1.translationNormalizationEpsilon
|
||||||
&& settings1.translationNormalizationParameter
|
== settings2.translationNormalizationEpsilon;
|
||||||
== settings2.translationNormalizationParameter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void updateMeshWithOptimalVariables(const std::vector<double> &x, SimulationMesh &m)
|
inline void updateMeshWithOptimalVariables(const std::vector<double> &x, SimulationMesh &m)
|
||||||
|
@ -306,6 +520,7 @@ struct Settings
|
||||||
std::vector<double> perSimulationScenario_translational;
|
std::vector<double> perSimulationScenario_translational;
|
||||||
std::vector<double> perSimulationScenario_rotational;
|
std::vector<double> perSimulationScenario_rotational;
|
||||||
std::vector<double> perSimulationScenario_total;
|
std::vector<double> perSimulationScenario_total;
|
||||||
|
std::vector<double> perSimulationScenario_total_unweighted;
|
||||||
} objectiveValue;
|
} objectiveValue;
|
||||||
std::vector<double> perScenario_fullPatternPotentialEnergy;
|
std::vector<double> perScenario_fullPatternPotentialEnergy;
|
||||||
std::vector<double> objectiveValueHistory;
|
std::vector<double> objectiveValueHistory;
|
||||||
|
@ -332,7 +547,7 @@ struct Settings
|
||||||
inline static std::string fullPatternYoungsModulus{"youngsModulus"};
|
inline static std::string fullPatternYoungsModulus{"youngsModulus"};
|
||||||
};
|
};
|
||||||
|
|
||||||
void save(const string &saveToPath, const bool shouldExportDebugFiles = false)
|
void save(const std::string &saveToPath, const bool shouldExportDebugFiles = false)
|
||||||
{
|
{
|
||||||
//clear directory
|
//clear directory
|
||||||
if (std::filesystem::exists(saveToPath)) {
|
if (std::filesystem::exists(saveToPath)) {
|
||||||
|
@ -405,7 +620,8 @@ struct Settings
|
||||||
= fullPatternSimulationJobs[simulationScenarioIndex];
|
= fullPatternSimulationJobs[simulationScenarioIndex];
|
||||||
std::filesystem::path simulationJobFolderPath(
|
std::filesystem::path simulationJobFolderPath(
|
||||||
std::filesystem::path(simulationJobsPath)
|
std::filesystem::path(simulationJobsPath)
|
||||||
.append(pFullPatternSimulationJob->label));
|
.append(std::to_string(simulationScenarioIndex) + "_"
|
||||||
|
+ pFullPatternSimulationJob->label));
|
||||||
std::filesystem::create_directories(simulationJobFolderPath);
|
std::filesystem::create_directories(simulationJobFolderPath);
|
||||||
const auto fullPatternDirectoryPath
|
const auto fullPatternDirectoryPath
|
||||||
= std::filesystem::path(simulationJobFolderPath).append("Full");
|
= std::filesystem::path(simulationJobFolderPath).append("Full");
|
||||||
|
@ -435,7 +651,7 @@ struct Settings
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load(const string &loadFromPath, const bool &shouldLoadDebugFiles = false)
|
bool load(const std::string &loadFromPath, const bool &shouldLoadDebugFiles = false)
|
||||||
{
|
{
|
||||||
assert(std::filesystem::is_directory(loadFromPath));
|
assert(std::filesystem::is_directory(loadFromPath));
|
||||||
std::filesystem::path jsonFilepath(
|
std::filesystem::path jsonFilepath(
|
||||||
|
@ -496,40 +712,36 @@ struct Settings
|
||||||
if (shouldLoadDebugFiles) {
|
if (shouldLoadDebugFiles) {
|
||||||
const std::filesystem::path simulationJobsFolderPath(
|
const std::filesystem::path simulationJobsFolderPath(
|
||||||
std::filesystem::path(loadFromPath).append("SimulationJobs"));
|
std::filesystem::path(loadFromPath).append("SimulationJobs"));
|
||||||
for (const auto &directoryEntry :
|
|
||||||
filesystem::directory_iterator(simulationJobsFolderPath)) {
|
std::vector<std::filesystem::path> sortedByName;
|
||||||
const auto simulationScenarioPath = directoryEntry.path();
|
for (auto &entry : std::filesystem::directory_iterator(simulationJobsFolderPath))
|
||||||
|
sortedByName.push_back(entry.path());
|
||||||
|
|
||||||
|
std::sort(sortedByName.begin(), sortedByName.end(), &Utilities::compareNat);
|
||||||
|
|
||||||
|
for (const auto &simulationScenarioPath : sortedByName) {
|
||||||
if (!std::filesystem::is_directory(simulationScenarioPath)) {
|
if (!std::filesystem::is_directory(simulationScenarioPath)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Load full pattern files
|
|
||||||
for (const auto &fileEntry : filesystem::directory_iterator(
|
|
||||||
std::filesystem::path(simulationScenarioPath).append("Full"))) {
|
|
||||||
const auto filepath = fileEntry.path();
|
|
||||||
if (filepath.extension() == ".json") {
|
|
||||||
SimulationJob job;
|
|
||||||
job.load(filepath.string());
|
|
||||||
job.pMesh->setBeamMaterial(0.3, fullPatternYoungsModulus);
|
|
||||||
fullPatternSimulationJobs.push_back(std::make_shared<SimulationJob>(job));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load reduced pattern files and apply optimal parameters
|
const auto fullJobFilepath = Utilities::getFilepathWithExtension(
|
||||||
for (const auto &fileEntry : filesystem::directory_iterator(
|
std::filesystem::path(simulationScenarioPath).append("Full"), ".json");
|
||||||
std::filesystem::path(simulationScenarioPath).append("Reduced"))) {
|
SimulationJob fullJob;
|
||||||
const auto filepath = fileEntry.path();
|
fullJob.load(fullJobFilepath.string());
|
||||||
if (filepath.extension() == ".json") {
|
fullJob.pMesh->setBeamMaterial(0.3, fullPatternYoungsModulus);
|
||||||
SimulationJob job;
|
fullPatternSimulationJobs.push_back(std::make_shared<SimulationJob>(fullJob));
|
||||||
job.load(filepath.string());
|
|
||||||
// applyOptimizationResults_innerHexagon(*this, baseTriangle, *job.pMesh);
|
const auto reducedJobFilepath = Utilities::getFilepathWithExtension(
|
||||||
applyOptimizationResults_elements(*this, job.pMesh);
|
std::filesystem::path(simulationScenarioPath).append("Reduced"), ".json");
|
||||||
reducedPatternSimulationJobs.push_back(
|
SimulationJob reducedJob;
|
||||||
std::make_shared<SimulationJob>(job));
|
reducedJob.load(reducedJobFilepath.string());
|
||||||
}
|
// applyOptimizationResults_innerHexagon(*this, baseTriangle, *job.pMesh);
|
||||||
}
|
applyOptimizationResults_elements(*this, reducedJob.pMesh);
|
||||||
|
reducedPatternSimulationJobs.push_back(
|
||||||
|
std::make_shared<SimulationJob>(reducedJob));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings.load(loadFromPath);
|
settings.load(std::filesystem::path(loadFromPath).append(Settings::defaultFilename));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -543,9 +755,16 @@ struct Settings
|
||||||
std::unordered_map<std::string, double>
|
std::unordered_map<std::string, double>
|
||||||
optimalXVariables(reducedPattern_optimizationResults.optimalXNameValuePairs.begin(),
|
optimalXVariables(reducedPattern_optimizationResults.optimalXNameValuePairs.begin(),
|
||||||
reducedPattern_optimizationResults.optimalXNameValuePairs.end());
|
reducedPattern_optimizationResults.optimalXNameValuePairs.end());
|
||||||
assert(optimalXVariables.contains("HexSize") && optimalXVariables.contains("HexAngle"));
|
assert(optimalXVariables.contains("R") && optimalXVariables.contains("Theta"));
|
||||||
applyOptimizationResults_innerHexagon(optimalXVariables.at("HexSize"),
|
if (optimalXVariables.contains("HexSize")) {
|
||||||
optimalXVariables.at("HexAngle"),
|
applyOptimizationResults_innerHexagon(optimalXVariables.at("HexSize"),
|
||||||
|
optimalXVariables.at("HexAngle"),
|
||||||
|
patternBaseTriangle,
|
||||||
|
reducedPattern);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyOptimizationResults_innerHexagon(optimalXVariables.at("R"),
|
||||||
|
optimalXVariables.at("Theta"),
|
||||||
patternBaseTriangle,
|
patternBaseTriangle,
|
||||||
reducedPattern);
|
reducedPattern);
|
||||||
}
|
}
|
||||||
|
@ -589,7 +808,7 @@ struct Settings
|
||||||
|
|
||||||
static void applyOptimizationResults_elements(
|
static void applyOptimizationResults_elements(
|
||||||
const ReducedPatternOptimization::Results &reducedPattern_optimizationResults,
|
const ReducedPatternOptimization::Results &reducedPattern_optimizationResults,
|
||||||
const shared_ptr<SimulationMesh> &pTiledReducedPattern_simulationMesh)
|
const std::shared_ptr<SimulationMesh> &pTiledReducedPattern_simulationMesh)
|
||||||
{
|
{
|
||||||
assert(CrossSectionType::name == RectangularBeamDimensions::name);
|
assert(CrossSectionType::name == RectangularBeamDimensions::name);
|
||||||
// Set reduced parameters fron the optimization results
|
// Set reduced parameters fron the optimization results
|
||||||
|
|
|
@ -133,32 +133,32 @@ public:
|
||||||
return constrainedVertices.empty() && nodalExternalForces.empty()
|
return constrainedVertices.empty() && nodalExternalForces.empty()
|
||||||
&& nodalForcedDisplacements.empty() && pMesh == nullptr;
|
&& nodalForcedDisplacements.empty() && pMesh == nullptr;
|
||||||
}
|
}
|
||||||
void remap(const std::unordered_map<size_t, size_t> &thisToOtherViMap,
|
void remap(const std::unordered_map<size_t, size_t> &sourceToDestinationViMap,
|
||||||
SimulationJob &simulationJobMapped) const
|
SimulationJob &destination_simulationJob) const
|
||||||
{
|
{
|
||||||
assert(simulationJobMapped.pMesh->VN() != 0);
|
std::unordered_map<VertexIndex, std::unordered_set<int>> destination_fixedVertices;
|
||||||
std::unordered_map<VertexIndex, std::unordered_set<int>> reducedModelFixedVertices;
|
for (const auto &source_fixedVertex : this->constrainedVertices) {
|
||||||
for (auto fullModelFixedVertex : this->constrainedVertices) {
|
destination_fixedVertices[sourceToDestinationViMap.at(source_fixedVertex.first)]
|
||||||
reducedModelFixedVertices[thisToOtherViMap.at(fullModelFixedVertex.first)]
|
= source_fixedVertex.second;
|
||||||
= fullModelFixedVertex.second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<VertexIndex, Vector6d> reducedModelNodalForces;
|
std::unordered_map<VertexIndex, Vector6d> destination_nodalForces;
|
||||||
for (auto fullModelNodalForce : this->nodalExternalForces) {
|
for (const auto &source_nodalForces : this->nodalExternalForces) {
|
||||||
reducedModelNodalForces[thisToOtherViMap.at(fullModelNodalForce.first)]
|
destination_nodalForces[sourceToDestinationViMap.at(source_nodalForces.first)]
|
||||||
= fullModelNodalForce.second;
|
= source_nodalForces.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<VertexIndex, Eigen::Vector3d> reducedNodalForcedDisplacements;
|
std::unordered_map<VertexIndex, Eigen::Vector3d> destination_forcedDisplacements;
|
||||||
for (auto fullForcedDisplacement : this->nodalForcedDisplacements) {
|
for (const auto &source_forcedDisplacements : this->nodalForcedDisplacements) {
|
||||||
reducedNodalForcedDisplacements[thisToOtherViMap.at(fullForcedDisplacement.first)]
|
destination_forcedDisplacements[sourceToDestinationViMap.at(
|
||||||
= fullForcedDisplacement.second;
|
source_forcedDisplacements.first)]
|
||||||
|
= source_forcedDisplacements.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
simulationJobMapped.constrainedVertices = reducedModelFixedVertices;
|
destination_simulationJob.constrainedVertices = destination_fixedVertices;
|
||||||
simulationJobMapped.nodalExternalForces = reducedModelNodalForces;
|
destination_simulationJob.nodalExternalForces = destination_nodalForces;
|
||||||
simulationJobMapped.label = this->getLabel();
|
destination_simulationJob.label = this->getLabel();
|
||||||
simulationJobMapped.nodalForcedDisplacements = reducedNodalForcedDisplacements;
|
destination_simulationJob.nodalForcedDisplacements = destination_forcedDisplacements;
|
||||||
}
|
}
|
||||||
SimulationJob getCopy() const {
|
SimulationJob getCopy() const {
|
||||||
SimulationJob jobCopy;
|
SimulationJob jobCopy;
|
||||||
|
@ -377,7 +377,7 @@ json[jsonLabels.meshFilename]= std::filesystem::relative(std::filesystem::path(m
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<std::array<double, 3>> nodeColors(pMesh->VN());
|
std::vector<std::array<double, 3>> nodeColors(pMesh->VN());
|
||||||
for (auto fixedVertex : constrainedVertices) {
|
for (const auto &fixedVertex : constrainedVertices) {
|
||||||
const bool hasRotationalDoFConstrained = fixedVertex.second.contains(3)
|
const bool hasRotationalDoFConstrained = fixedVertex.second.contains(3)
|
||||||
|| fixedVertex.second.contains(4)
|
|| fixedVertex.second.contains(4)
|
||||||
|| fixedVertex.second.contains(5);
|
|| fixedVertex.second.contains(5);
|
||||||
|
@ -393,7 +393,8 @@ json[jsonLabels.meshFilename]= std::filesystem::relative(std::filesystem::path(m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!nodalForcedDisplacements.empty()) {
|
if (!nodalForcedDisplacements.empty()) {
|
||||||
for (std::pair<VertexIndex, Eigen::Vector3d> viDisplPair : nodalForcedDisplacements) {
|
for (const std::pair<VertexIndex, Eigen::Vector3d> &viDisplPair :
|
||||||
|
nodalForcedDisplacements) {
|
||||||
const VertexIndex vi = viDisplPair.first;
|
const VertexIndex vi = viDisplPair.first;
|
||||||
nodeColors[vi][0] += 1;
|
nodeColors[vi][0] += 1;
|
||||||
nodeColors[vi][0] /= 2;
|
nodeColors[vi][0] /= 2;
|
||||||
|
@ -712,21 +713,21 @@ struct SimulationResults
|
||||||
// /*polyscope::getNextUniqueColor()*/ glm::vec3(0, 0, 1));
|
// /*polyscope::getNextUniqueColor()*/ glm::vec3(0, 0, 1));
|
||||||
// //}
|
// //}
|
||||||
pJob->registerForDrawing(getLabel());
|
pJob->registerForDrawing(getLabel());
|
||||||
static bool wasExecuted = false;
|
// static bool wasExecuted =false;
|
||||||
if (!wasExecuted) {
|
// if (!wasExecuted) {
|
||||||
std::function<void()> callback = [&]() {
|
// std::function<void()> callback = [&]() {
|
||||||
static bool showFrames = shouldShowFrames;
|
// static bool showFrames = shouldShowFrames;
|
||||||
|
|
||||||
if (ImGui::Checkbox("Show Frames", &showFrames) && showFrames) {
|
// if (ImGui::Checkbox("Show Frames", &showFrames) && showFrames) {
|
||||||
polyscopeHandle_frameX->setEnabled(showFrames);
|
// polyscopeHandle_frameX->setEnabled(showFrames);
|
||||||
polyscopeHandle_frameY->setEnabled(showFrames);
|
// polyscopeHandle_frameY->setEnabled(showFrames);
|
||||||
polyscopeHandle_frameZ->setEnabled(showFrames);
|
// polyscopeHandle_frameZ->setEnabled(showFrames);
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
PolyscopeInterface::addUserCallback(callback);
|
// PolyscopeInterface::addUserCallback(callback);
|
||||||
wasExecuted = true;
|
// wasExecuted = true;
|
||||||
}
|
// }
|
||||||
return polyscopeHandle_deformedEdmeMesh;
|
return polyscopeHandle_deformedEdmeMesh;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -738,7 +739,7 @@ private:
|
||||||
//load job
|
//load job
|
||||||
//Use the first .eigenBin file for loading the displacements
|
//Use the first .eigenBin file for loading the displacements
|
||||||
for (auto const &entry : std::filesystem::recursive_directory_iterator(loadFromPath)) {
|
for (auto const &entry : std::filesystem::recursive_directory_iterator(loadFromPath)) {
|
||||||
if (filesystem::is_regular_file(entry) && entry.path().extension() == ".eigenBin") {
|
if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ".eigenBin") {
|
||||||
Eigen::MatrixXd displacements_eigen;
|
Eigen::MatrixXd displacements_eigen;
|
||||||
Eigen::read_binary(entry.path().string(), displacements_eigen);
|
Eigen::read_binary(entry.path().string(), displacements_eigen);
|
||||||
displacements = Utilities::fromEigenMatrix(displacements_eigen);
|
displacements = Utilities::fromEigenMatrix(displacements_eigen);
|
||||||
|
|
|
@ -15,27 +15,25 @@ struct SimulationResultsReporter {
|
||||||
|
|
||||||
void writeStatistics(const SimulationResults &results,
|
void writeStatistics(const SimulationResults &results,
|
||||||
const std::string &reportFolderPath) {
|
const std::string &reportFolderPath) {
|
||||||
|
std::ofstream file;
|
||||||
|
file.open(std::filesystem::path(reportFolderPath).append("results.txt").string());
|
||||||
|
|
||||||
ofstream file;
|
const size_t numberOfSteps = results.history.numberOfSteps;
|
||||||
file.open(
|
file << "Number of steps " << numberOfSteps << "\n";
|
||||||
std::filesystem::path(reportFolderPath).append("results.txt").string());
|
|
||||||
|
|
||||||
const size_t numberOfSteps = results.history.numberOfSteps;
|
// file << "Force threshold used " << 1000 << "\n";
|
||||||
file << "Number of steps " << numberOfSteps << "\n";
|
|
||||||
|
|
||||||
// file << "Force threshold used " << 1000 << "\n";
|
// assert(numberOfSteps == results.history.potentialEnergy.size() &&
|
||||||
|
// numberOfSteps == results.history.residualForces.size());
|
||||||
// assert(numberOfSteps == results.history.potentialEnergy.size() &&
|
// Write kinetic energies
|
||||||
// numberOfSteps == results.history.residualForces.size());
|
const SimulationHistory &history = results.history;
|
||||||
// Write kinetic energies
|
if (!history.kineticEnergy.empty()) {
|
||||||
const SimulationHistory &history = results.history;
|
file << "Kinetic energies"
|
||||||
if (!history.kineticEnergy.empty()) {
|
<< "\n";
|
||||||
file << "Kinetic energies"
|
for (size_t step = 0; step < numberOfSteps; step++) {
|
||||||
<< "\n";
|
file << history.kineticEnergy[step] << "\n";
|
||||||
for (size_t step = 0; step < numberOfSteps; step++) {
|
}
|
||||||
file << history.kineticEnergy[step] << "\n";
|
file << "\n";
|
||||||
}
|
|
||||||
file << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!history.logResidualForces.empty()) {
|
if (!history.logResidualForces.empty()) {
|
||||||
|
|
|
@ -284,85 +284,85 @@ std::vector<ElementMaterial> SimulationMesh::getBeamMaterial() {
|
||||||
return beamMaterial;
|
return beamMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimulationMesh::load(const string &plyFilename) {
|
bool SimulationMesh::load(const std::string &plyFilename)
|
||||||
this->Clear();
|
{
|
||||||
// assert(plyFileHasAllRequiredFields(plyFilename));
|
this->Clear();
|
||||||
// Load the ply file
|
// assert(plyFileHasAllRequiredFields(plyFilename));
|
||||||
// VCGEdgeMesh::PerEdgeAttributeHandle<CrossSectionType> handleBeamDimensions =
|
// Load the ply file
|
||||||
// vcg::tri::Allocator<SimulationMesh>::AddPerEdgeAttribute<
|
// VCGEdgeMesh::PerEdgeAttributeHandle<CrossSectionType> handleBeamDimensions =
|
||||||
// CrossSectionType>(*this, plyPropertyBeamDimensionsID);
|
// vcg::tri::Allocator<SimulationMesh>::AddPerEdgeAttribute<
|
||||||
// VCGEdgeMesh::PerEdgeAttributeHandle<ElementMaterial> handleBeamMaterial =
|
// CrossSectionType>(*this, plyPropertyBeamDimensionsID);
|
||||||
// vcg::tri::Allocator<SimulationMesh>::AddPerEdgeAttribute<ElementMaterial>(
|
// VCGEdgeMesh::PerEdgeAttributeHandle<ElementMaterial> handleBeamMaterial =
|
||||||
// *this, plyPropertyBeamMaterialID);
|
// vcg::tri::Allocator<SimulationMesh>::AddPerEdgeAttribute<ElementMaterial>(
|
||||||
// nanoply::NanoPlyWrapper<SimulationMesh>::CustomAttributeDescriptor
|
// *this, plyPropertyBeamMaterialID);
|
||||||
// customAttrib;
|
// nanoply::NanoPlyWrapper<SimulationMesh>::CustomAttributeDescriptor
|
||||||
// customAttrib.GetMeshAttrib(plyFilename);
|
// customAttrib;
|
||||||
// customAttrib.AddEdgeAttribDescriptor<CrossSectionType, double, 2>(
|
// customAttrib.GetMeshAttrib(plyFilename);
|
||||||
// plyPropertyBeamDimensionsID, nanoply::NNP_LIST_INT8_FLOAT64, nullptr);
|
// customAttrib.AddEdgeAttribDescriptor<CrossSectionType, double, 2>(
|
||||||
// /*FIXME: Since I allow CrossSectionType to take two types I should export the
|
// plyPropertyBeamDimensionsID, nanoply::NNP_LIST_INT8_FLOAT64, nullptr);
|
||||||
// * type as well such that that when loaded the correct type of cross section
|
// /*FIXME: Since I allow CrossSectionType to take two types I should export the
|
||||||
// * is used.
|
// * type as well such that that when loaded the correct type of cross section
|
||||||
// */
|
// * is used.
|
||||||
// customAttrib.AddEdgeAttribDescriptor<vcg::Point2d, double, 2>(
|
// */
|
||||||
// plyPropertyBeamMaterialID, nanoply::NNP_LIST_INT8_FLOAT64, nullptr);
|
// customAttrib.AddEdgeAttribDescriptor<vcg::Point2d, double, 2>(
|
||||||
|
// plyPropertyBeamMaterialID, nanoply::NNP_LIST_INT8_FLOAT64, nullptr);
|
||||||
|
|
||||||
// VCGEdgeMesh::PerEdgeAttributeHandle<std::array<double, 6>>
|
// VCGEdgeMesh::PerEdgeAttributeHandle<std::array<double, 6>>
|
||||||
// handleBeamProperties =
|
// handleBeamProperties =
|
||||||
// vcg::tri::Allocator<SimulationMesh>::AddPerEdgeAttribute<
|
// vcg::tri::Allocator<SimulationMesh>::AddPerEdgeAttribute<
|
||||||
// std::array<double, 6>>(*this, plyPropertyBeamProperties);
|
// std::array<double, 6>>(*this, plyPropertyBeamProperties);
|
||||||
// customAttrib.AddEdgeAttribDescriptor<std::array<double, 6>, double, 6>(
|
// customAttrib.AddEdgeAttribDescriptor<std::array<double, 6>, double, 6>(
|
||||||
// plyPropertyBeamProperties, nanoply::NNP_LIST_INT8_FLOAT64, nullptr);
|
// plyPropertyBeamProperties, nanoply::NNP_LIST_INT8_FLOAT64, nullptr);
|
||||||
|
|
||||||
// VCGEdgeMesh::PerEdgeAttributeHandle<ElementMaterial>
|
// VCGEdgeMesh::PerEdgeAttributeHandle<ElementMaterial>
|
||||||
// handleBeamRigidityContants;
|
// handleBeamRigidityContants;
|
||||||
// customAttrib.AddEdgeAttribDescriptor<vcg::Point4f, float, 4>(
|
// customAttrib.AddEdgeAttribDescriptor<vcg::Point4f, float, 4>(
|
||||||
// plyPropertyBeamRigidityConstantsID, nanoply::NNP_LIST_INT8_FLOAT32,
|
// plyPropertyBeamRigidityConstantsID, nanoply::NNP_LIST_INT8_FLOAT32,
|
||||||
// nullptr);
|
// nullptr);
|
||||||
// unsigned int mask = 0;
|
// unsigned int mask = 0;
|
||||||
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTCOORD;
|
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTCOORD;
|
||||||
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTNORMAL;
|
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTNORMAL;
|
||||||
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_EDGEINDEX;
|
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_EDGEINDEX;
|
||||||
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_EDGEATTRIB;
|
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_EDGEATTRIB;
|
||||||
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_MESHATTRIB;
|
// mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_MESHATTRIB;
|
||||||
if (!VCGEdgeMesh::load(plyFilename)) {
|
if (!VCGEdgeMesh::load(plyFilename)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// elements = vcg::tri::Allocator<SimulationMesh>::GetPerEdgeAttribute<Element>(
|
|
||||||
// *this, std::string("Elements"));
|
|
||||||
// nodes = vcg::tri::Allocator<SimulationMesh>::GetPerVertexAttribute<Node>(
|
|
||||||
// *this, std::string("Nodes"));
|
|
||||||
vcg::tri::UpdateTopology<SimulationMesh>::VertexEdge(*this);
|
|
||||||
initializeNodes();
|
|
||||||
initializeElements();
|
|
||||||
setBeamMaterial(0.3, 1 * 1e9);
|
|
||||||
updateEigenEdgeAndVertices();
|
|
||||||
|
|
||||||
// if (!handleBeamProperties._handle->data.empty()) {
|
|
||||||
// for (size_t ei = 0; ei < EN(); ei++) {
|
|
||||||
// elements[ei] =
|
|
||||||
// Element::Properties(handleBeamProperties[ei]);
|
|
||||||
// elements[ei].updateRigidity();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for (size_t ei = 0; ei < EN(); ei++) {
|
|
||||||
// elements[ei].setDimensions(handleBeamDimensions[ei]);
|
|
||||||
// elements[ei].setMaterial(handleBeamMaterial[ei]);
|
|
||||||
// elements[ei].updateRigidity();
|
|
||||||
// }
|
|
||||||
|
|
||||||
bool normalsAreAbsent = vert[0].cN().Norm() < 0.000001;
|
|
||||||
if (normalsAreAbsent) {
|
|
||||||
CoordType normalVector(0, 0, 1);
|
|
||||||
std::cout << "Warning: Normals are missing from " << plyFilename
|
|
||||||
<< ". Added normal vector:" << toString(normalVector)
|
|
||||||
<< std::endl;
|
|
||||||
for (auto &v : vert) {
|
|
||||||
v.N() = normalVector;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
// elements = vcg::tri::Allocator<SimulationMesh>::GetPerEdgeAttribute<Element>(
|
||||||
|
// *this, std::string("Elements"));
|
||||||
|
// nodes = vcg::tri::Allocator<SimulationMesh>::GetPerVertexAttribute<Node>(
|
||||||
|
// *this, std::string("Nodes"));
|
||||||
|
vcg::tri::UpdateTopology<SimulationMesh>::VertexEdge(*this);
|
||||||
|
initializeNodes();
|
||||||
|
initializeElements();
|
||||||
|
setBeamMaterial(0.3, 1 * 1e9);
|
||||||
|
updateEigenEdgeAndVertices();
|
||||||
|
|
||||||
|
// if (!handleBeamProperties._handle->data.empty()) {
|
||||||
|
// for (size_t ei = 0; ei < EN(); ei++) {
|
||||||
|
// elements[ei] =
|
||||||
|
// Element::Properties(handleBeamProperties[ei]);
|
||||||
|
// elements[ei].updateRigidity();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (size_t ei = 0; ei < EN(); ei++) {
|
||||||
|
// elements[ei].setDimensions(handleBeamDimensions[ei]);
|
||||||
|
// elements[ei].setMaterial(handleBeamMaterial[ei]);
|
||||||
|
// elements[ei].updateRigidity();
|
||||||
|
// }
|
||||||
|
|
||||||
|
bool normalsAreAbsent = vert[0].cN().Norm() < 0.000001;
|
||||||
|
if (normalsAreAbsent) {
|
||||||
|
CoordType normalVector(0, 0, 1);
|
||||||
|
std::cout << "Warning: Normals are missing from " << plyFilename
|
||||||
|
<< ". Added normal vector:" << toString(normalVector) << std::endl;
|
||||||
|
for (auto &v : vert) {
|
||||||
|
v.N() = normalVector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimulationMesh::save(const std::string &plyFilename)
|
bool SimulationMesh::save(const std::string &plyFilename)
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
std::vector<VCGEdgeMesh::EdgePointer>
|
std::vector<VCGEdgeMesh::EdgePointer>
|
||||||
getIncidentElements(const VCGEdgeMesh::VertexType &v);
|
getIncidentElements(const VCGEdgeMesh::VertexType &v);
|
||||||
virtual bool load(const string &plyFilename);
|
virtual bool load(const std::string &plyFilename);
|
||||||
std::vector<CrossSectionType> getBeamDimensions();
|
std::vector<CrossSectionType> getBeamDimensions();
|
||||||
std::vector<ElementMaterial> getBeamMaterial();
|
std::vector<ElementMaterial> getBeamMaterial();
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ PatternGeometry::PatternGeometry(PatternGeometry &other) {
|
||||||
vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(*this);
|
vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PatternGeometry::load(const string &plyFilename)
|
bool PatternGeometry::load(const std::string &plyFilename)
|
||||||
{
|
{
|
||||||
if (!VCGEdgeMesh::load(plyFilename)) {
|
if (!VCGEdgeMesh::load(plyFilename)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#include <Eigen/Dense>
|
#include <Eigen/Dense>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <chrono>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <numeric>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#define GET_VARIABLE_NAME(Variable) (#Variable)
|
#define GET_VARIABLE_NAME(Variable) (#Variable)
|
||||||
|
@ -140,16 +142,37 @@ struct Vector6d : public std::array<double, 6> {
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Utilities {
|
namespace Utilities {
|
||||||
//inline std::vector<std::string> split(std::string text, char delim)
|
inline bool compareNat(const std::string &a, const std::string &b)
|
||||||
//{
|
{
|
||||||
// std::string line;
|
if (a.empty())
|
||||||
// std::vector<std::string> vec;
|
return true;
|
||||||
// std::stringstream ss(text);
|
if (b.empty())
|
||||||
// while (std::getline(ss, line, delim)) {
|
return false;
|
||||||
// vec.push_back(line);
|
if (std::isdigit(a[0]) && !std::isdigit(b[0]))
|
||||||
// }
|
return true;
|
||||||
// return vec;
|
if (!std::isdigit(a[0]) && std::isdigit(b[0]))
|
||||||
//}
|
return false;
|
||||||
|
if (!std::isdigit(a[0]) && !std::isdigit(b[0])) {
|
||||||
|
if (std::toupper(a[0]) == std::toupper(b[0]))
|
||||||
|
return compareNat(a.substr(1), b.substr(1));
|
||||||
|
return (std::toupper(a[0]) < std::toupper(b[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both strings begin with digit --> parse both numbers
|
||||||
|
std::istringstream issa(a);
|
||||||
|
std::istringstream issb(b);
|
||||||
|
int ia, ib;
|
||||||
|
issa >> ia;
|
||||||
|
issb >> ib;
|
||||||
|
if (ia != ib)
|
||||||
|
return ia < ib;
|
||||||
|
|
||||||
|
// Numbers are the same --> remove numbers and recurse
|
||||||
|
std::string anew, bnew;
|
||||||
|
std::getline(issa, anew);
|
||||||
|
std::getline(issb, bnew);
|
||||||
|
return (compareNat(anew, bnew));
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string_view leftTrimSpaces(const std::string_view& str)
|
inline std::string_view leftTrimSpaces(const std::string_view& str)
|
||||||
{
|
{
|
||||||
|
@ -175,6 +198,21 @@ std::string_view trimmedString=str;
|
||||||
return trimmedString;
|
return trimmedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename InputIt>
|
||||||
|
inline void normalize(InputIt itBegin, InputIt itEnd)
|
||||||
|
{
|
||||||
|
const auto squaredSumOfElements = std::accumulate(itBegin,
|
||||||
|
itEnd,
|
||||||
|
0.0,
|
||||||
|
[](const auto &sum, const auto &el) {
|
||||||
|
return sum + el * el;
|
||||||
|
});
|
||||||
|
assert(squaredSumOfElements != 0);
|
||||||
|
std::transform(itBegin, itEnd, itBegin, [&](auto &element) {
|
||||||
|
return element / std::sqrt(squaredSumOfElements);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
inline std::vector<std::string> split(const std::string& text, std::string delim)
|
inline std::vector<std::string> split(const std::string& text, std::string delim)
|
||||||
{
|
{
|
||||||
std::vector<std::string> vec;
|
std::vector<std::string> vec;
|
||||||
|
@ -273,6 +311,19 @@ inline std::vector<Vector6d> fromEigenMatrix(const Eigen::MatrixXd &m)
|
||||||
// return true;
|
// return true;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
inline std::filesystem::path getFilepathWithExtension(const std::filesystem::path &folderPath,
|
||||||
|
const std::string &extension)
|
||||||
|
{
|
||||||
|
for (const std::filesystem::directory_entry &dirEntry :
|
||||||
|
std::filesystem::directory_iterator(folderPath)) {
|
||||||
|
if (dirEntry.is_regular_file() && std::filesystem::path(dirEntry).extension() == extension) {
|
||||||
|
return std::filesystem::path(dirEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Utilities
|
} // namespace Utilities
|
||||||
|
|
||||||
#ifdef POLYSCOPE_DEFINED
|
#ifdef POLYSCOPE_DEFINED
|
||||||
|
@ -293,7 +344,7 @@ inline void mainCallback()
|
||||||
// instead of full width. Must have
|
// instead of full width. Must have
|
||||||
// matching PopItemWidth() below.
|
// matching PopItemWidth() below.
|
||||||
|
|
||||||
for (std::function<void()> userCallback : globalPolyscopeData.userCallbacks) {
|
for (std::function<void()> &userCallback : globalPolyscopeData.userCallbacks) {
|
||||||
userCallback();
|
userCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,17 +469,4 @@ inline size_t computeHashOrdered(const std::vector<int> &v)
|
||||||
return std::hash<std::string>{}(elementsString);
|
return std::hash<std::string>{}(elementsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
//inline std::filesystem::path getFilepathWithExtension(const std::filesystem::path &folderPath,
|
|
||||||
// const std::string &extension)
|
|
||||||
//{
|
|
||||||
// for (const std::filesystem::directory_entry &dirEntry :
|
|
||||||
// std::filesystem::directory_iterator(folderPath)) {
|
|
||||||
// if (dirEntry.is_regular_file() && std::filesystem::path(dirEntry).extension() == extension) {
|
|
||||||
// return std::filesystem::path(dirEntry);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return "";
|
|
||||||
//}
|
|
||||||
|
|
||||||
#endif // UTILITIES_H
|
#endif // UTILITIES_H
|
||||||
|
|
Loading…
Reference in New Issue