#ifndef SIMULATIONHISTORY_HPP #define SIMULATIONHISTORY_HPP #include "elementalmesh.hpp" struct SimulationHistory { SimulationHistory() {} size_t numberOfSteps{0}; std::string label; std::vector residualForces; std::vector kineticEnergy; std::vector potentialEnergies; std::vector redMarks; std::vector greenMarks; void markRed(const size_t &stepNumber) { redMarks.push_back(stepNumber); } void markGreen(const size_t &stepNumber) { greenMarks.push_back(stepNumber); } void stepPulse(const SimulationMesh &mesh) { kineticEnergy.push_back(log(mesh.currentTotalKineticEnergy)); // potentialEnergy.push_back(mesh.totalPotentialEnergykN); residualForces.push_back(mesh.totalResidualForcesNorm); } void clear() { residualForces.clear(); kineticEnergy.clear(); potentialEnergies.clear(); } }; struct SimulationJob { std::shared_ptr mesh; std::unordered_map> fixedVertices; std::unordered_map nodalExternalForces; std::unordered_map nodalForcedDisplacements; std::unordered_map nodalForcedNormals; void registerForDrawing() const { initPolyscope(); const std::string polyscopeName = mesh->getLabel() + "_Simulation Job"; polyscope::registerCurveNetwork(polyscopeName, mesh->getEigenVertices(), mesh->getEigenEdges()); // polyscope::registerPointCloud("Undeformed edge mesh PC", // job.edgeMesh.getEigenVertices()); std::vector> nodeColors(mesh->VN()); for (auto fixedVertex : fixedVertices) { nodeColors[fixedVertex.first] = {0, 0, 1}; } if (!nodalForcedDisplacements.empty()) { for (std::pair viDisplPair : nodalForcedDisplacements) { const VertexIndex vi = viDisplPair.first; nodeColors[vi][0] += 1; nodeColors[vi][0] /= 2; nodeColors[vi][1] += 0; nodeColors[vi][1] /= 2; nodeColors[vi][2] += 0; nodeColors[vi][2] /= 2; } } std::for_each(nodeColors.begin(), nodeColors.end(), [](std::array &color) { const double norm = sqrt(std::pow(color[0], 2) + std::pow(color[1], 2) + std::pow(color[2], 2)); if (norm > std::pow(10, -7)) { color[0] /= norm; color[1] /= norm; color[2] /= norm; } }); if (!nodeColors.empty()) { polyscope::getCurveNetwork(polyscopeName) ->addNodeColorQuantity("Boundary conditions", nodeColors); polyscope::getCurveNetwork(polyscopeName) ->getQuantity("Boundary conditions") ->setEnabled(true); } // per node external forces std::vector> externalForces(mesh->VN()); for (const auto &forcePair : nodalExternalForces) { auto index = forcePair.first; auto force = forcePair.second; externalForces[index] = {force[0], force[1], force[2]}; } if (!externalForces.empty()) { polyscope::getCurveNetwork(polyscopeName) ->addNodeVectorQuantity("External force", externalForces); polyscope::getCurveNetwork(polyscopeName) ->getQuantity("External force") ->setEnabled(true); } } static std::unordered_map> constructFixedVerticesSpanGrid(const size_t &spanGridSize, const size_t &gridVertices) { std::unordered_map> fixedVertices; for (size_t vi = 0; vi < spanGridSize - 1; vi++) { fixedVertices[vi] = {0, 1, 2}; } for (size_t vi = gridVertices - 1 - (spanGridSize - 2); vi < gridVertices; vi++) { fixedVertices[vi] = {0, 1, 2}; } for (size_t vi = spanGridSize - 1; vi < gridVertices - 1 - (spanGridSize - 2) - spanGridSize + 1; vi += spanGridSize + 1) { fixedVertices[vi] = {0, 1, 2}; fixedVertices[vi + spanGridSize] = {0, 1, 2}; } return fixedVertices; } }; struct SimulationResults { SimulationHistory history; std::vector displacements; double executionTime{0}; std::string simulationLabel{"NoLabel"}; void registerForDrawing(const SimulationJob &job) const { polyscope::options::groundPlaneEnabled = false; polyscope::view::upDir = polyscope::view::UpDir::ZUp; const std::string branchName = "Branch:Polyscope"; polyscope::options::programName = branchName; if (!polyscope::state::initialized) { polyscope::init(); } /* else { polyscope::removeAllStructures(); }*/ const std::string undeformedMeshName = "Undeformed_" + simulationLabel; polyscope::registerCurveNetwork(undeformedMeshName, job.mesh->getEigenVertices(), job.mesh->getEigenEdges()); const std::string deformedMeshName = "Deformed_" + simulationLabel; polyscope::registerCurveNetwork(deformedMeshName, job.mesh->getEigenVertices(), job.mesh->getEigenEdges()); Eigen::MatrixX3d nodalDisplacements(job.mesh->VN(), 3); for (VertexIndex vi = 0; vi < job.mesh->VN(); vi++) { const Vector6d &nodalDisplacement = displacements[vi]; nodalDisplacements.row(vi) = Eigen::Vector3d( nodalDisplacement[0], nodalDisplacement[1], nodalDisplacement[2]); } polyscope::getCurveNetwork(deformedMeshName) ->updateNodePositions(job.mesh->getEigenVertices() + nodalDisplacements); std::vector> nodeColors(job.mesh->VN()); for (auto fixedVertex : job.fixedVertices) { nodeColors[fixedVertex.first] = {0, 0, 1}; } if (!job.nodalForcedDisplacements.empty()) { for (std::pair viDisplPair : job.nodalForcedDisplacements) { const VertexIndex vi = viDisplPair.first; nodeColors[vi][0] += 1; nodeColors[vi][0] /= 2; nodeColors[vi][1] += 0; nodeColors[vi][1] /= 2; nodeColors[vi][2] += 0; nodeColors[vi][2] /= 2; } } std::for_each(nodeColors.begin(), nodeColors.end(), [](std::array &color) { const double norm = sqrt(std::pow(color[0], 2) + std::pow(color[1], 2) + std::pow(color[2], 2)); if (norm > std::pow(10, -7)) { color[0] /= norm; color[1] /= norm; color[2] /= norm; } }); // per node external forces std::vector> externalForces(job.mesh->VN()); std::vector> externalMoments(job.mesh->VN()); for (const auto &forcePair : job.nodalExternalForces) { auto index = forcePair.first; auto force = forcePair.second; externalForces[index] = {force[0], force[1], force[2]}; externalMoments[index] = {force[3], force[4], 0}; } polyscope::getCurveNetwork(undeformedMeshName) ->addNodeColorQuantity("Boundary conditions", nodeColors) ->setEnabled(true); polyscope::getCurveNetwork(undeformedMeshName) ->addNodeVectorQuantity("External force", externalForces) ->setEnabled(true); polyscope::getCurveNetwork(undeformedMeshName) ->addNodeVectorQuantity("External moments", externalMoments) ->setEnabled(true); polyscope::getCurveNetwork(deformedMeshName) ->addNodeColorQuantity("Boundary conditions", nodeColors) ->setEnabled(false); polyscope::getCurveNetwork(deformedMeshName) ->addNodeVectorQuantity("External force", externalForces) ->setEnabled(true); // polyscope::show(); } }; #endif // SIMULATIONHISTORY_HPP