diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e173489a1..6669804ccf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -213,7 +213,7 @@ jobs: id: first-try run: | cd build - ctest --output-on-failure + ctest --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the second try for failed cases @@ -221,7 +221,7 @@ jobs: if: ${{ steps.first-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure + ctest --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the third try for failed cases @@ -229,7 +229,7 @@ jobs: if: ${{ steps.second-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure + ctest --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the fourth try for failed cases @@ -237,14 +237,14 @@ jobs: if: ${{ steps.third-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure + ctest --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the last try for failed cases if: ${{ steps.fourth-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure + ctest --rerun-failed --output-on-failure --timeout 1000 ############################################################################### @@ -358,7 +358,7 @@ jobs: id: first-try run: | cd C:\build - ctest.exe --output-on-failure + ctest.exe --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the second try for failed cases @@ -366,7 +366,7 @@ jobs: if: ${{ steps.first-try.outcome == 'failure' }} run: | cd C:\build - ctest.exe --rerun-failed --output-on-failure + ctest.exe --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the third try for failed cases @@ -374,7 +374,7 @@ jobs: if: ${{ steps.second-try.outcome == 'failure' }} run: | cd C:\build - ctest.exe --rerun-failed --output-on-failure + ctest.exe --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the fourth try for failed cases @@ -382,14 +382,14 @@ jobs: if: ${{ steps.third-try.outcome == 'failure' }} run: | cd C:\build - ctest.exe --rerun-failed --output-on-failure + ctest.exe --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the last try for failed cases if: ${{ steps.fourth-try.outcome == 'failure' }} run: | cd C:\build - ctest.exe --rerun-failed --output-on-failure + ctest.exe --rerun-failed --output-on-failure --timeout 1000 ############################################################################### @@ -509,7 +509,7 @@ jobs: id: first-try run: | cd build - ctest --output-on-failure + ctest --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the second try for failed cases @@ -517,7 +517,7 @@ jobs: if: ${{ steps.first-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure + ctest --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the third try for failed cases @@ -525,7 +525,7 @@ jobs: if: ${{ steps.second-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure + ctest --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the fourth try for failed cases @@ -533,11 +533,11 @@ jobs: if: ${{ steps.third-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure + ctest --rerun-failed --output-on-failure --timeout 1000 continue-on-error: true - name: Test with the last try for failed cases if: ${{ steps.fourth-try.outcome == 'failure' }} run: | cd build - ctest --rerun-failed --output-on-failure \ No newline at end of file + ctest --rerun-failed --output-on-failure --timeout 1000 \ No newline at end of file diff --git a/modules/opencascade/opencascade/relax_dynamics_surface.cpp b/modules/opencascade/opencascade/relax_dynamics_surface.cpp index 46ebe52d21..ac154d26ad 100644 --- a/modules/opencascade/opencascade/relax_dynamics_surface.cpp +++ b/modules/opencascade/opencascade/relax_dynamics_surface.cpp @@ -7,12 +7,12 @@ namespace SPH { -//=====================================================================================================// namespace relax_dynamics { //=================================================================================================// ShapeSurfaceBounding2::ShapeSurfaceBounding2(RealBody &real_body_) - : LocalDynamics(real_body_), RelaxDataDelegateSimple(real_body_), pos_(particles_->pos_) + : LocalDynamics(real_body_), DataDelegateSimple(real_body_), + pos_(*particles_->getVariableByName("Position")) { shape_ = &real_body_.getInitialShape(); } @@ -52,9 +52,10 @@ void RelaxationStepInnerSecondHalf::exec(Real dt) //=================================================================================================// SurfaceNormalDirection::SurfaceNormalDirection(SPHBody &sph_body) - : RelaxDataDelegateSimple(sph_body), LocalDynamics(sph_body), + : DataDelegateSimple(sph_body), LocalDynamics(sph_body), surface_shape_(DynamicCast(this, &sph_body.getInitialShape())), - pos_(particles_->pos_), n_(*particles_->getVariableByName("NormalDirection")) {} + pos_(*particles_->getVariableByName("Position")), + n_(*particles_->registerSharedVariable("NormalDirection")) {} //=================================================================================================// void SurfaceNormalDirection::update(size_t index_i, Real dt) @@ -79,18 +80,5 @@ void SurfaceNormalDirection::update(size_t index_i, Real dt) n_[index_i] = normal_direction_.normalized(); } //=================================================================================================// -ConstrainSurfaceBodyRegion:: - ConstrainSurfaceBodyRegion(BodyPartByParticle &body_part) - : BaseLocalDynamics(body_part), RelaxDataDelegateSimple(sph_body_), - force_(particles_->force_) -{ -} -//=================================================================================================// -void ConstrainSurfaceBodyRegion::update(size_t index_i, Real dt) -{ - force_[index_i] = Vecd::Zero(); -} -//=================================================================================================// } // namespace relax_dynamics - //=================================================================================================// } // namespace SPH diff --git a/modules/opencascade/opencascade/relax_dynamics_surface.h b/modules/opencascade/opencascade/relax_dynamics_surface.h index 4fdca4b002..8fc2e81ad7 100644 --- a/modules/opencascade/opencascade/relax_dynamics_surface.h +++ b/modules/opencascade/opencascade/relax_dynamics_surface.h @@ -42,7 +42,7 @@ class SurfaceShape; namespace relax_dynamics { class ShapeSurfaceBounding2 : public LocalDynamics, - public RelaxDataDelegateSimple + public DataDelegateSimple { public: ShapeSurfaceBounding2(RealBody &real_body_); @@ -86,7 +86,7 @@ class RelaxationStepInnerSecondHalf : public BaseDynamics * @class SurfaceNormalDirection * @brief get the normal direction of surface particles. */ -class SurfaceNormalDirection : public RelaxDataDelegateSimple, public LocalDynamics +class SurfaceNormalDirection : public DataDelegateSimple, public LocalDynamics { public: explicit SurfaceNormalDirection(SPHBody &sph_body); @@ -98,20 +98,6 @@ class SurfaceNormalDirection : public RelaxDataDelegateSimple, public LocalDynam StdLargeVec &pos_, &n_; }; -/**@class ConstrainSuefaceBodyRegion - * @brief Fix the position surafce body part. - */ -class ConstrainSurfaceBodyRegion : public BaseLocalDynamics, public RelaxDataDelegateSimple -{ - public: - ConstrainSurfaceBodyRegion(BodyPartByParticle &body_part); - virtual ~ConstrainSurfaceBodyRegion(){}; - void update(size_t index_i, Real dt = 0.0); - - protected: - StdLargeVec &force_; -}; - } // namespace relax_dynamics } // namespace SPH #endif // RELAX_DYNAMICS_H diff --git a/modules/opencascade/tests/test_3d_aortic_valve/aortic_valve.cpp b/modules/opencascade/tests/test_3d_aortic_valve/aortic_valve.cpp index 423ff5d154..4311c651ae 100644 --- a/modules/opencascade/tests/test_3d_aortic_valve/aortic_valve.cpp +++ b/modules/opencascade/tests/test_3d_aortic_valve/aortic_valve.cpp @@ -29,6 +29,9 @@ Vec3d domain_upper_bound(15.0, 15.0, 26.0); // Domain bounds of the system. //---------------------------------------------------------------------- BoundingBox system_domain_bounds(domain_lower_bound, domain_upper_bound); + +namespace SPH +{ /** Define the boundary geometry. */ class BoundaryGeometry : public BodyPartByParticle { @@ -51,10 +54,12 @@ class BoundaryGeometry : public BodyPartByParticle }; }; -class LeafletParticleGenerator : public ParticleGenerator +class Leaflet; +template <> +class ParticleGenerator : public ParticleGenerator { public: - explicit LeafletParticleGenerator(SPHBody &sph_body) + explicit ParticleGenerator(SPHBody &sph_body) : ParticleGenerator(sph_body), sph_body_(sph_body){}; virtual void initializeGeometricVariables() override { @@ -112,6 +117,7 @@ class LeafletParticleGenerator : public ParticleGenerator } SPHBody &sph_body_; }; +} // namespace SPH //-------------------------------------------------------------------------- // Main program starts here. @@ -128,9 +134,8 @@ int main(int ac, char *av[]) //---------------------------------------------------------------------- SolidBody leaflet(sph_system, makeShared(full_path_to_geometry, "Leaflet")); // here dummy linear elastic solid is use because no solid dynamics in particle relaxation - leaflet.defineParticlesAndMaterial(1.0, 1.0, 0.0); - LeafletParticleGenerator leaflet_particle_generator(leaflet); - leaflet.generateParticles(leaflet_particle_generator); + leaflet.defineMaterial(); + leaflet.generateParticles(); //---------------------------------------------------------------------- // Define simple file input and outputs functions. //---------------------------------------------------------------------- @@ -153,7 +158,6 @@ int main(int ac, char *av[]) RelaxationStepInnerSecondHalf leaflet_relaxation_second_half(leaflet_inner); /** Constrain the boundary. */ BoundaryGeometry boundary_geometry(leaflet, "BoundaryGeometry"); - SimpleDynamics constrain_holder(boundary_geometry); SimpleDynamics surface_normal_direction(leaflet); //---------------------------------------------------------------------- // Particle relaxation starts here. @@ -169,7 +173,6 @@ int main(int ac, char *av[]) while (ite < relax_step) { leaflet_relaxation_first_half.exec(); - constrain_holder.exec(); leaflet_relaxation_second_half.exec(); ite += 1; if (ite % 100 == 0) diff --git a/modules/structural_simulation/structural_simulation_class.cpp b/modules/structural_simulation/structural_simulation_class.cpp index 85e4a57198..220768d5ec 100755 --- a/modules/structural_simulation/structural_simulation_class.cpp +++ b/modules/structural_simulation/structural_simulation_class.cpp @@ -27,8 +27,8 @@ SolidBodyFromMesh::SolidBodyFromMesh( { defineAdaptationRatios(1.15, system.resolution_ref_ / resolution); defineBodyLevelSetShape()->cleanLevelSet(); - defineParticlesWithMaterial(material_model.get()); - generateParticles(); + assignMaterial(material_model.get()); + generateParticles(); } SolidBodyForSimulation::SolidBodyForSimulation( @@ -110,8 +110,8 @@ std::tuple, StdLargeVec> generateAndRelaxParticlesFromMe SPHSystem system(bb, resolution); SolidBody model(system, triangle_mesh_shape); model.defineBodyLevelSetShape()->cleanLevelSet(); - model.defineParticlesAndMaterial(); - model.generateParticles(); + model.defineMaterial(); + model.generateParticles(); if (particle_relaxation) { @@ -120,7 +120,7 @@ std::tuple, StdLargeVec> generateAndRelaxParticlesFromMe relaxParticlesSingleResolution(write_particle_relaxation_data, model, inner_relation); } - return std::tuple, StdLargeVec>(model.getBaseParticles().pos_, model.getBaseParticles().Vol_); + return std::tuple, StdLargeVec>(model.getBaseParticles().ParticlePositions(), model.getBaseParticles().VolumetricMeasures()); } BodyPartByParticle *createBodyPartFromMesh(SPHBody &body, const StlList &stl_list, size_t body_index, SharedPtr tmesh) @@ -215,12 +215,7 @@ StructuralSimulation::StructuralSimulation(const StructuralSimulationInput &inpu translation_solid_body_part_tuple_(input.translation_solid_body_part_tuple_), // iterators - iteration_(0), - - // data storage - von_mises_stress_max_({}), - von_mises_stress_particles_({}) - + iteration_(0) { // scaling of translation and resolution scaleTranslationAndResolution(); @@ -906,12 +901,7 @@ void StructuralSimulation::runSimulation(Real end_time) runSimulationStep(dt, integration_time); } TickCount t2 = TickCount::now(); - // record data for test - von_mises_stress_max_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getVonMisesStressMax()); - von_mises_stress_particles_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getVonMisesStressVector()); - von_mises_strain_max_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getVonMisesStrainMax()); - von_mises_strain_particles_.push_back(solid_body_list_[0].get()->getElasticSolidParticles()->getVonMisesStrainVector()); // write data to file write_states.writeToFile(); TickCount t3 = TickCount::now(); @@ -957,12 +947,12 @@ double StructuralSimulation::runSimulationFixedDurationJS(int number_of_steps) Real StructuralSimulation::getMaxDisplacement(int body_index) { - StdLargeVec &pos_0 = solid_body_list_[body_index].get()->getElasticSolidParticles()->pos0_; - StdLargeVec &pos_n = solid_body_list_[body_index].get()->getElasticSolidParticles()->pos_; + StdLargeVec &pos = solid_body_list_[body_index].get()->getElasticSolidParticles()->ParticlePositions(); + StdLargeVec &pos0 = *solid_body_list_[body_index].get()->getElasticSolidParticles()->registerSharedVariableFrom("InitialPosition", "Position"); Real displ_max = 0; - for (size_t i = 0; i < pos_0.size(); i++) + for (size_t i = 0; i < pos0.size(); i++) { - Real displ = (pos_n[i] - pos_0[i]).norm(); + Real displ = (pos[i] - pos0[i]).norm(); if (displ > displ_max) displ_max = displ; } diff --git a/modules/structural_simulation/structural_simulation_class.h b/modules/structural_simulation/structural_simulation_class.h index c679eeb4ee..69e01b3b4e 100755 --- a/modules/structural_simulation/structural_simulation_class.h +++ b/modules/structural_simulation/structural_simulation_class.h @@ -104,7 +104,7 @@ class SolidBodyForSimulation ~SolidBodyForSimulation(){}; SolidBodyFromMesh *getSolidBodyFromMesh() { return &solid_body_from_mesh_; }; - ElasticSolidParticles *getElasticSolidParticles() { return DynamicCast(this, &solid_body_from_mesh_.getBaseParticles()); }; + BaseParticles *getElasticSolidParticles() { return DynamicCast(this, &solid_body_from_mesh_.getBaseParticles()); }; InnerRelation *getInnerBodyRelation() { return &inner_body_relation_; }; SimpleDynamics *getInitialNormalDirection() { return &initial_normal_direction_; }; @@ -118,7 +118,7 @@ void expandBoundingBox(BoundingBox *original, BoundingBox *additional); void relaxParticlesSingleResolution(bool write_particles_to_file, SolidBodyFromMesh &solid_body_from_mesh, - ElasticSolidParticles &solid_body_from_mesh_particles, + BaseParticles &solid_body_from_mesh_particles, InnerRelation &solid_body_from_mesh_inner); static inline Real getPhysicalViscosityGeneral(Real rho, Real youngs_modulus, Real length_scale, Real shape_constant = 1.0) @@ -249,13 +249,6 @@ class StructuralSimulation // iterators int iteration_; - // data storage - StdVec von_mises_stress_max_; - StdLargeVec> von_mises_stress_particles_; - - StdVec von_mises_strain_max_; - StdLargeVec> von_mises_strain_particles_; - // for constructor, the order is important void scaleTranslationAndResolution(); void setSystemResolutionMax(); diff --git a/src/for_2D_build/bodies/mesh_helper.cpp b/src/for_2D_build/bodies/mesh_helper.cpp deleted file mode 100644 index c38e688d30..0000000000 --- a/src/for_2D_build/bodies/mesh_helper.cpp +++ /dev/null @@ -1,335 +0,0 @@ -#include "mesh_helper.h" -namespace SPH -{ - void MeshFileHelpers::meshDimension(ifstream& mesh_file, size_t& dimension, string& text_line) - { - while (getline(mesh_file, text_line)) - { - text_line.erase(0, 1); - text_line.erase(1); - istringstream value(text_line); - if (text_line.find("2", 0) != string::npos) - { - dimension = atoi(text_line.c_str()); - break; - } - } - } - - void MeshFileHelpers::numberofNodes(ifstream& mesh_file, size_t& number_of_points, string& text_line) - { - while (getline(mesh_file, text_line)) - { - text_line.erase(0, 1); - string text1(text_line); - text_line.erase(3); - string text2(text_line); - text_line.erase(2); - if (atoi(text_line.c_str()) == 10 && text1.find("))", 0) != string::npos) - { - text1.erase(0, 8); - Real last_position = text1.find_last_of(")"); - text1.erase(last_position - 5); - number_of_points = stoi(text1, nullptr, 16); - break; - } - } - } - - void MeshFileHelpers::nodeCoordinates(ifstream& mesh_file, StdLargeVec& node_coordinates_, - string& text_line, size_t& dimension) - { - while (getline(mesh_file, text_line)) - { - if (text_line.find("(", 0) == string::npos && text_line.find("))", 0) == string::npos) - { - if (text_line.find(" ", 0) != string::npos) - { - size_t divide_position = text_line.find_first_of(" "); - std::string x_part = text_line; - std::string y_part = text_line; - std::string x_coordinate_string = x_part.erase(divide_position); - std::string y_coordinate_string = y_part.erase(0, divide_position); - - Vec2d coordinate = Vec2d::Zero(); - std::istringstream stream_x, stream_y; - stream_x.str(x_coordinate_string); - stream_y.str(y_coordinate_string); - stream_x >> coordinate[0]; - stream_y >> coordinate[1]; - node_coordinates_.push_back(coordinate); - - } - } - if (text_line.find("))", 0) != string::npos) - { - break; - } - } - } - - void MeshFileHelpers::numberofElements(ifstream& mesh_file, size_t& number_of_elements, string& text_line) - { - while (getline(mesh_file, text_line)) - { - text_line.erase(0, 1); - string text1(text_line); - text_line.erase(3); - string text2(text_line); - text_line.erase(2); - if (atoi(text_line.c_str()) == 12) - { - text1.erase(0, 8); - Real last_position = text1.find_last_of(")"); - text1.erase(last_position - 5); - number_of_elements = stoi(text1, nullptr, 16); - break; - } - } - } - /*--- Initialize mesh topology ---*/ - /** mesh_topology_ - * {[(neighbor_cell_index, bc_type, node1_of_face, node2_of_face), (....), (.....)], []..... }. - * {inner_neighbor1, inner_neighbor2, ..... }. - */ - /*--- Initialize the number of elements ---*/ - void MeshFileHelpers::dataStruct(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - size_t number_of_elements, size_t mesh_type, size_t dimension) - { - - mesh_topology_.resize(number_of_elements + 1); - for (std::size_t a = 0; a != number_of_elements + 1; ++a) - { - mesh_topology_[a].resize(mesh_type); - for (std::size_t b = 0; b != mesh_topology_[a].size(); ++b) - { - mesh_topology_[a][b].resize(dimension + 2); - for (std::size_t c = 0; c != mesh_topology_[a][b].size(); ++c) - { - mesh_topology_[a][b][c] = MaxSize_t; - } - } - } - /*--- Initialize the number of elements ---*/ - elements_nodes_connection_.resize(number_of_elements + 1); - mesh_topology_.resize(number_of_elements + 1); - for (std::size_t element = 0; element != number_of_elements + 1; ++element) - { - elements_nodes_connection_[element].resize(3); - for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) - { - elements_nodes_connection_[element][node] = MaxSize_t; - } - } - } - - size_t MeshFileHelpers::findBoundaryType(string& text_line, size_t boundary_type) - { - /*--- Read the elements of the problem (13 (id f1 f2 type 0) (---*/ - /*--- Read the elements of the problem ---*/ - /** boundary condition types - * bc-type==2, interior boundary condition. - * bc-type==3, wall boundary condition. - * bc-type==9, pressure-far-field boundary condition. - * Note that Cell 0 means boundary condition. - * mesh_type==3, unstructured mesh. - * mesh_type==4, structured mesh. - * mesh_topology_ - * {[(neighbor_cell_index, bc_type, node1_of_face, node2_of_face), (....), (.....)], []..... }. - * {inner_neighbor1, inner_neighbor2, ..... }. - */ - /*--- find the type of boundary condition ---*/ - size_t position = text_line.find(")", 0); - text_line = text_line.erase(0, position - 4); - text_line = text_line.erase(2); - boundary_type = stoi(text_line, nullptr, 16); - return boundary_type; - } - - Vecd MeshFileHelpers::nodeIndex(string& text_line) - { - /*--- find the node1 between two cells ---*/ - string node1_string_copy = text_line; - size_t first_divide_position = text_line.find_first_of(" ", 0); - string node1_index_string = node1_string_copy.erase(first_divide_position); - size_t node1_index_decimal = stoi(node1_index_string, nullptr, 16) - 1; - - /*--- find the node2 between two cells---*/ - string node2_string = text_line; - node2_string = node2_string.erase(0, first_divide_position + 1); - size_t second_divide_position = node2_string.find_first_of(" ", 0); - node2_string.erase(second_divide_position); - size_t node2_index_decimal = stoi(node2_string, nullptr, 16) - 1; - Vecd nodes = Vecd(node1_index_decimal, node2_index_decimal); - return nodes; - } - - Vec2d MeshFileHelpers::cellIndex(string& text_line) - { - - /*--- find the cell1---*/ - string cell1_string = text_line; - size_t first_divide_position = text_line.find_first_of(" ", 0); - cell1_string = cell1_string.erase(0, first_divide_position + 1); - size_t second_divide_position = cell1_string.find_first_of(" ", 0); - cell1_string = cell1_string.erase(0, second_divide_position + 1); - size_t third_divide_position = cell1_string.find_first_of(" ", 0); - cell1_string.erase(third_divide_position); - size_t cell1_index_decimal = stoi(cell1_string, nullptr, 16); - - /*--- find the cell2---*/ - string cell2_string = text_line; - cell2_string = cell2_string.erase(0, first_divide_position + 1); - cell2_string = cell2_string.erase(0, second_divide_position + 1); - cell2_string.erase(0, third_divide_position + 1); - size_t cell2_index_decimal = stoi(cell2_string, nullptr, 16); - Vecd cells = Vecd(cell1_index_decimal, cell2_index_decimal); - return cells; - } - - void MeshFileHelpers::updateElementsNodesConnection(StdLargeVec>& elements_nodes_connection_, Vecd nodes, Vec2d cells, - bool& check_neighbor_cell1, bool& check_neighbor_cell2) - { - - /*--- build up connection with element and nodes only---*/ - for (int node = 0; node != nodes.size(); ++node) - { - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][1] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][2] != nodes[node]) - { - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && (elements_nodes_connection_[cells[check_neighbor_cell2]][1] != static_cast>(-1)) && elements_nodes_connection_[cells[check_neighbor_cell2]][2] == static_cast>(-1)) - { - elements_nodes_connection_[cells[check_neighbor_cell2]][2] = nodes[node]; - } - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][1] == static_cast>(-1)) - { - elements_nodes_connection_[cells[check_neighbor_cell2]][1] = nodes[node]; - } - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] == static_cast>(-1)) - { - elements_nodes_connection_[cells[check_neighbor_cell2]][0] = nodes[node]; - } - } - else - continue; - } - } - - void MeshFileHelpers::updateCellLists(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, Vecd nodes, - Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type) - { - /*--- build up all connection data with element and neighbor and nodes---*/ - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][1][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][2][0] != cells[check_neighbor_cell1]) - { - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(-1)) - { - /*--- inner neighbor index---*/ - mesh_topology_[cells[check_neighbor_cell2]][0][0] = cells[check_neighbor_cell1]; - /*--- boundary type---*/ - mesh_topology_[cells[check_neighbor_cell2]][0][1] = boundary_type; - /*--- nodes of a face---*/ - mesh_topology_[cells[check_neighbor_cell2]][0][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][0][3] = nodes[1]; - - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][1][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][1][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][1][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][1][3] = nodes[1]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - } - - - } - - void MeshFileHelpers::updateBoundaryCellLists(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - Vecd nodes, Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type) - { - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - else - { - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - - } - - void MeshFileHelpers::cellCenterCoordinates(StdLargeVec>& elements_nodes_connection_, std::size_t& element, - StdLargeVec& node_coordinates_, StdLargeVec& elements_centroids_, Vecd& center_coordinate) - { - - for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) - { - center_coordinate += node_coordinates_[elements_nodes_connection_[element][node]] / 3.0; - } - elements_centroids_[element] = center_coordinate; - } - - void MeshFileHelpers::elementVolume(StdLargeVec>& elements_nodes_connection_, std::size_t& element, - StdLargeVec& node_coordinates_, StdLargeVec& elements_volumes_) - { - // calculating each volume of element - // get nodes position - Vecd node1_coordinate = node_coordinates_[elements_nodes_connection_[element][0]]; - Vecd node2_coordinate = node_coordinates_[elements_nodes_connection_[element][1]]; - Vecd node3_coordinate = node_coordinates_[elements_nodes_connection_[element][2]]; - // get each line length - Real first_side_length = (node1_coordinate - node2_coordinate).norm(); - Real second_side_length = (node1_coordinate - node3_coordinate).norm(); - Real third_side_length = (node2_coordinate - node3_coordinate).norm(); - // half perimeter - Real half_perimeter = (first_side_length + second_side_length + third_side_length) / 2.0; - // get element volume - Real element_volume = - pow(half_perimeter * (half_perimeter - first_side_length) * (half_perimeter - second_side_length) * (half_perimeter - third_side_length), 0.5); - elements_volumes_[element] = element_volume; - } - - void MeshFileHelpers::minimumdistance(vector& all_data_of_distance_between_nodes, StdLargeVec& elements_volumes_, vector>>& mesh_topology_, - StdLargeVec& node_coordinates_) - { - - for (size_t element_index = 0; element_index != elements_volumes_.size(); ++element_index) - { - - for (std::size_t neighbor = 0; neighbor != mesh_topology_[element_index].size(); ++neighbor) - { - - size_t interface_node1_index = mesh_topology_[element_index][neighbor][2]; - size_t interface_node2_index = mesh_topology_[element_index][neighbor][3]; - Vecd node1_position = node_coordinates_[interface_node1_index]; - Vecd node2_position = node_coordinates_[interface_node2_index]; - Vecd interface_area_vector = node1_position - node2_position; - Real interface_area_size = interface_area_vector.norm(); - all_data_of_distance_between_nodes.push_back(interface_area_size); - } - } - } -} \ No newline at end of file diff --git a/src/for_2D_build/bodies/mesh_helper_2d.cpp b/src/for_2D_build/bodies/mesh_helper_2d.cpp new file mode 100644 index 0000000000..f2efdadf00 --- /dev/null +++ b/src/for_2D_build/bodies/mesh_helper_2d.cpp @@ -0,0 +1,354 @@ +#include "mesh_helper.h" + +#include "base_particle_dynamics.h" +namespace SPH +{ +//=================================================================================================// +void MeshFileHelpers::meshDimension(std::ifstream &mesh_file, size_t &dimension, std::string &text_line) +{ + while (getline(mesh_file, text_line)) + { + text_line.erase(0, 1); + text_line.erase(1); + std::istringstream value(text_line); + if (text_line.find("2", 0) != std::string::npos) + { + dimension = atoi(text_line.c_str()); + break; + } + } +} +//=================================================================================================// +void MeshFileHelpers::numberOfNodes(std::ifstream &mesh_file, size_t &number_of_points, std::string &text_line) +{ + while (getline(mesh_file, text_line)) + { + text_line.erase(0, 1); + std::string text1(text_line); + text_line.erase(3); + std::string text2(text_line); + text_line.erase(2); + if (atoi(text_line.c_str()) == 10 && text1.find("))", 0) != std::string::npos) + { + text1.erase(0, 8); + Real last_position = text1.find_last_of(")"); + text1.erase(last_position - 5); + number_of_points = stoi(text1, nullptr, 16); + break; + } + } +} +//=================================================================================================// +void MeshFileHelpers::nodeCoordinates(std::ifstream &mesh_file, StdLargeVec &node_coordinates_, + std::string &text_line, size_t &dimension) +{ + while (getline(mesh_file, text_line)) + { + if (text_line.find("(", 0) == std::string::npos && text_line.find("))", 0) == std::string::npos) + { + if (text_line.find(" ", 0) != std::string::npos) + { + size_t divide_position = text_line.find_first_of(" "); + std::string x_part = text_line; + std::string y_part = text_line; + std::string x_coordinate_string = x_part.erase(divide_position); + std::string y_coordinate_string = y_part.erase(0, divide_position); + + Vec2d coordinate = Vec2d::Zero(); + std::istringstream stream_x, stream_y; + stream_x.str(x_coordinate_string); + stream_y.str(y_coordinate_string); + stream_x >> coordinate[0]; + stream_y >> coordinate[1]; + node_coordinates_.push_back(coordinate); + } + } + if (text_line.find("))", 0) != std::string::npos) + { + break; + } + } +} +//=================================================================================================// +void MeshFileHelpers::numberOfElements(std::ifstream &mesh_file, size_t &number_of_elements, std::string &text_line) +{ + while (getline(mesh_file, text_line)) + { + text_line.erase(0, 1); + std::string text1(text_line); + text_line.erase(3); + std::string text2(text_line); + text_line.erase(2); + if (atoi(text_line.c_str()) == 12) + { + text1.erase(0, 8); + Real last_position = text1.find_last_of(")"); + text1.erase(last_position - 5); + number_of_elements = stoi(text1, nullptr, 16); + break; + } + } +} +//=================================================================================================// +/*--- Initialize mesh topology ---*/ +/** mesh_topology_ + * {[(neighbor_cell_index, bc_type, node1_of_face, node2_of_face), (....), (.....)], []..... }. + * {inner_neighbor1, inner_neighbor2, ..... }. + */ +/*--- Initialize the number of elements ---*/ +void MeshFileHelpers::dataStruct(StdVec>> &mesh_topology_, + StdLargeVec> &elements_nodes_connection_, + size_t number_of_elements, size_t mesh_type, size_t dimension) +{ + + mesh_topology_.resize(number_of_elements + 1); + for (std::size_t a = 0; a != number_of_elements + 1; ++a) + { + mesh_topology_[a].resize(mesh_type); + for (std::size_t b = 0; b != mesh_topology_[a].size(); ++b) + { + mesh_topology_[a][b].resize(dimension + 2); + for (std::size_t c = 0; c != mesh_topology_[a][b].size(); ++c) + { + mesh_topology_[a][b][c] = MaxSize_t; + } + } + } + /*--- Initialize the number of elements ---*/ + elements_nodes_connection_.resize(number_of_elements + 1); + mesh_topology_.resize(number_of_elements + 1); + for (std::size_t element = 0; element != number_of_elements + 1; ++element) + { + elements_nodes_connection_[element].resize(3); + for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) + { + elements_nodes_connection_[element][node] = MaxSize_t; + } + } +} +//=================================================================================================// +size_t MeshFileHelpers::findBoundaryType(std::string &text_line, size_t boundary_type) +{ + /*--- Read the elements of the problem (13 (id f1 f2 type 0) (---*/ + /*--- Read the elements of the problem ---*/ + /** boundary condition types + * bc-type==2, interior boundary condition. + * bc-type==3, wall boundary condition. + * bc-type==9, pressure-far-field boundary condition. + * Note that Cell 0 means boundary condition. + * mesh_type==3, unstructured mesh. + * mesh_type==4, structured mesh. + * mesh_topology_ + * {[(neighbor_cell_index, bc_type, node1_of_face, node2_of_face), (....), (.....)], []..... }. + * {inner_neighbor1, inner_neighbor2, ..... }. + */ + /*--- find the type of boundary condition ---*/ + size_t position = text_line.find(")", 0); + text_line = text_line.erase(0, position - 4); + text_line = text_line.erase(2); + boundary_type = std::stoi(text_line, nullptr, 16); + return boundary_type; +} +//=================================================================================================// +Vecd MeshFileHelpers::nodeIndex(std::string &text_line) +{ + /*--- find the node1 between two cells ---*/ + std::string node1_string_copy = text_line; + size_t first_divide_position = text_line.find_first_of(" ", 0); + std::string node1_index_string = node1_string_copy.erase(first_divide_position); + size_t node1_index_decimal = stoi(node1_index_string, nullptr, 16) - 1; + + /*--- find the node2 between two cells---*/ + std::string node2_string = text_line; + node2_string = node2_string.erase(0, first_divide_position + 1); + size_t second_divide_position = node2_string.find_first_of(" ", 0); + node2_string.erase(second_divide_position); + size_t node2_index_decimal = stoi(node2_string, nullptr, 16) - 1; + Vecd nodes = Vecd(node1_index_decimal, node2_index_decimal); + return nodes; +} +//=================================================================================================// +Vec2d MeshFileHelpers::cellIndex(std::string &text_line) +{ + + /*--- find the cell1---*/ + std::string cell1_string = text_line; + size_t first_divide_position = text_line.find_first_of(" ", 0); + cell1_string = cell1_string.erase(0, first_divide_position + 1); + size_t second_divide_position = cell1_string.find_first_of(" ", 0); + cell1_string = cell1_string.erase(0, second_divide_position + 1); + size_t third_divide_position = cell1_string.find_first_of(" ", 0); + cell1_string.erase(third_divide_position); + size_t cell1_index_decimal = std::stoi(cell1_string, nullptr, 16); + + /*--- find the cell2---*/ + std::string cell2_string = text_line; + cell2_string = cell2_string.erase(0, first_divide_position + 1); + cell2_string = cell2_string.erase(0, second_divide_position + 1); + cell2_string.erase(0, third_divide_position + 1); + size_t cell2_index_decimal = stoi(cell2_string, nullptr, 16); + Vecd cells = Vecd(cell1_index_decimal, cell2_index_decimal); + return cells; +} +//=================================================================================================// +void MeshFileHelpers::updateElementsNodesConnection(StdLargeVec> &elements_nodes_connection_, + Vecd nodes, Vec2d cells, + bool &check_neighbor_cell1, bool &check_neighbor_cell2) +{ + + /*--- build up connection with element and nodes only---*/ + for (int node = 0; node != nodes.size(); ++node) + { + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != nodes[node] && + elements_nodes_connection_[cells[check_neighbor_cell2]][1] != nodes[node] && + elements_nodes_connection_[cells[check_neighbor_cell2]][2] != nodes[node]) + { + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && + (elements_nodes_connection_[cells[check_neighbor_cell2]][1] != static_cast>(-1)) && + elements_nodes_connection_[cells[check_neighbor_cell2]][2] == static_cast>(-1)) + { + elements_nodes_connection_[cells[check_neighbor_cell2]][2] = nodes[node]; + } + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && + elements_nodes_connection_[cells[check_neighbor_cell2]][1] == static_cast>(-1)) + { + elements_nodes_connection_[cells[check_neighbor_cell2]][1] = nodes[node]; + } + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] == static_cast>(-1)) + { + elements_nodes_connection_[cells[check_neighbor_cell2]][0] = nodes[node]; + } + } + else + continue; + } +} +//=================================================================================================// +void MeshFileHelpers::updateCellLists(StdVec>> &mesh_topology_, + StdLargeVec> &elements_nodes_connection_, Vecd nodes, + Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type) +{ + /*--- build up all connection data with element and neighbor and nodes---*/ + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != cells[check_neighbor_cell1] && + mesh_topology_[cells[check_neighbor_cell2]][1][0] != cells[check_neighbor_cell1] && + mesh_topology_[cells[check_neighbor_cell2]][2][0] != cells[check_neighbor_cell1]) + { + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(-1)) + { + /*--- inner neighbor index---*/ + mesh_topology_[cells[check_neighbor_cell2]][0][0] = cells[check_neighbor_cell1]; + /*--- boundary type---*/ + mesh_topology_[cells[check_neighbor_cell2]][0][1] = boundary_type; + /*--- nodes of a face---*/ + mesh_topology_[cells[check_neighbor_cell2]][0][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][0][3] = nodes[1]; + + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && + mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][1][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][1][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][1][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][1][3] = nodes[1]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && + mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && + mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + } +} +//=================================================================================================// +void MeshFileHelpers::updateBoundaryCellLists(StdVec>> &mesh_topology_, + StdLargeVec> &elements_nodes_connection_, + Vecd nodes, Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type) +{ + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != cells[check_neighbor_cell1] && + mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && + mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + else + { + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } +} +//=================================================================================================// +void MeshFileHelpers::cellCenterCoordinates(StdLargeVec> &elements_nodes_connection_, + std::size_t &element, StdLargeVec &node_coordinates_, + StdLargeVec &elements_centroids_, Vecd ¢er_coordinate) +{ + + for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) + { + center_coordinate += node_coordinates_[elements_nodes_connection_[element][node]] / 3.0; + } + elements_centroids_[element] = center_coordinate; +} +//=================================================================================================// +void MeshFileHelpers::elementVolume(StdLargeVec> &elements_nodes_connection_, std::size_t &element, + StdLargeVec &node_coordinates_, StdLargeVec &elements_volumes_) +{ + // calculating each volume of element + // get nodes position + Vecd node1_coordinate = node_coordinates_[elements_nodes_connection_[element][0]]; + Vecd node2_coordinate = node_coordinates_[elements_nodes_connection_[element][1]]; + Vecd node3_coordinate = node_coordinates_[elements_nodes_connection_[element][2]]; + // get each line length + Real first_side_length = (node1_coordinate - node2_coordinate).norm(); + Real second_side_length = (node1_coordinate - node3_coordinate).norm(); + Real third_side_length = (node2_coordinate - node3_coordinate).norm(); + // half perimeter + Real half_perimeter = (first_side_length + second_side_length + third_side_length) / 2.0; + // get element volume + Real element_volume = + pow(half_perimeter * (half_perimeter - first_side_length) * (half_perimeter - second_side_length) * (half_perimeter - third_side_length), 0.5); + elements_volumes_[element] = element_volume; +} +//=================================================================================================// +void MeshFileHelpers::minimumDistance(StdVec &all_data_of_distance_between_nodes, + StdLargeVec &elements_volumes_, StdVec>> &mesh_topology_, + StdLargeVec &node_coordinates_) +{ + + for (size_t element_index = 0; element_index != elements_volumes_.size(); ++element_index) + { + + for (std::size_t neighbor = 0; neighbor != mesh_topology_[element_index].size(); ++neighbor) + { + + size_t interface_node1_index = mesh_topology_[element_index][neighbor][2]; + size_t interface_node2_index = mesh_topology_[element_index][neighbor][3]; + Vecd node1_position = node_coordinates_[interface_node1_index]; + Vecd node2_position = node_coordinates_[interface_node2_index]; + Vecd interface_area_vector = node1_position - node2_position; + Real interface_area_size = interface_area_vector.norm(); + all_data_of_distance_between_nodes.push_back(interface_area_size); + } + } +} +//=================================================================================================// +} // namespace SPH diff --git a/src/for_2D_build/bodies/solid_body_supplementary.cpp b/src/for_2D_build/bodies/solid_body_2d.cpp similarity index 76% rename from src/for_2D_build/bodies/solid_body_supplementary.cpp rename to src/for_2D_build/bodies/solid_body_2d.cpp index 0ec816cb99..fc11636fb4 100644 --- a/src/for_2D_build/bodies/solid_body_supplementary.cpp +++ b/src/for_2D_build/bodies/solid_body_2d.cpp @@ -1,5 +1,6 @@ #include "solid_body.h" -#include "solid_particles.h" + +#include "base_particles.hpp" namespace SPH { @@ -11,8 +12,8 @@ void SolidBodyPartForSimbody::setMassProperties() for (size_t i = 0; i < body_part_particles_.size(); ++i) { size_t index_i = body_part_particles_[i]; - Real particle_volume = solid_particles_->Vol_[index_i]; - mass_center += particle_volume * solid_particles_->pos0_[index_i]; + Real particle_volume = Vol_[index_i]; + mass_center += particle_volume * pos_[index_i]; body_part_volume += particle_volume; } @@ -26,8 +27,8 @@ void SolidBodyPartForSimbody::setMassProperties() for (size_t i = 0; i < body_part_particles_.size(); ++i) { size_t index_i = body_part_particles_[i]; - Vecd particle_position = solid_particles_->pos0_[index_i]; - Real particle_volume = solid_particles_->Vol_[index_i]; + Vecd particle_position = pos_[index_i]; + Real particle_volume = Vol_[index_i]; Real r_x = (particle_position[1] - mass_center[1]); Ix += particle_volume * r_x * r_x; @@ -40,7 +41,7 @@ void SolidBodyPartForSimbody::setMassProperties() Iz /= body_part_volume; body_part_mass_properties_ = mass_properties_ptr_keeper_.createPtr( - body_part_volume * solid_body_density_, SimTKVec3(0), SimTK::UnitInertia(Ix, Iy, Iz)); + body_part_volume * rho0_, SimTKVec3(0), SimTK::UnitInertia(Ix, Iy, Iz)); } //=================================================================================================// } // namespace SPH diff --git a/src/for_2D_build/bodies/unstructured_mesh.cpp b/src/for_2D_build/bodies/unstructured_mesh.cpp deleted file mode 100644 index 2d364b8701..0000000000 --- a/src/for_2D_build/bodies/unstructured_mesh.cpp +++ /dev/null @@ -1,459 +0,0 @@ - -#include "unstructured_mesh.h" -#include "mesh_helper.h" - -namespace SPH -{ -//=================================================================================================// -ANSYSMesh::ANSYSMesh(const std::string &full_path) -{ - getDataFromMeshFile(full_path); - getElementCenterCoordinates(); - getMinimumDistanceBetweenNodes(); -} -//=================================================================================================// -void ANSYSMesh::getDataFromMeshFile(const std::string &full_path) -{ - ifstream mesh_file; /*!< \brief File object for the Ansys ASCII mesh file. */ - mesh_file.open(full_path); - if (mesh_file.fail()) - { - cout << "Error:Check if the file exists." << endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - } - string text_line; - /*--- Read the dimension of the problem ---*/ - size_t dimension(0); - MeshFileHelpers::meshDimension(mesh_file, dimension, text_line); - /*--- Check dimension ---*/ - if (dimension != Dimensions) - { - cout << "Error:the dimension of problem does not match input mesh." << endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - } - /*--- Read the total number node points ---*/ - size_t number_of_points(0); - MeshFileHelpers::numberofNodes(mesh_file, number_of_points, text_line); - - /*--- Read the node coordinates ---*/ - MeshFileHelpers::nodeCoordinates(mesh_file, node_coordinates_, text_line, dimension); - /*--- Check number of node points ---*/ - if (node_coordinates_.size() != number_of_points) - { - cout << "Error:Total number of node points does not match data!" << endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - } - size_t boundary_type(0); - size_t number_of_elements(0); - size_t mesh_type = 3; - /*--- Read the total number of elements ---*/ - MeshFileHelpers::numberofElements(mesh_file, number_of_elements, text_line); - - /*Preparing and initializing the data structure of mesh topology and element node connection*/ - MeshFileHelpers::dataStruct(mesh_topology_, elements_nodes_connection_, number_of_elements, mesh_type, dimension); - - while (getline(mesh_file, text_line)) - { - if (text_line.find("(13", 0) != string::npos && text_line.find(")(", 0) != string::npos) - { - /*--- find the type of boundary condition ---*/ - boundary_type = MeshFileHelpers::findBoundaryType(text_line, boundary_type); - types_of_boundary_condition_.push_back(boundary_type); - while (getline(mesh_file, text_line)) - { - if (text_line.find(")", 0) == string::npos) - { - Vecd nodes = MeshFileHelpers::nodeIndex(text_line); - Vec2d cells = MeshFileHelpers::cellIndex(text_line); - /*--- build up all topology---*/ - bool check_neighbor_cell1 = 1; - bool check_neighbor_cell2 = 0; - for (int cell1_cell2 = 0; cell1_cell2 != cells.size(); ++cell1_cell2) - { - if (mesh_type == 3) - { - if (cells[check_neighbor_cell2] != 0) - { - MeshFileHelpers::updateElementsNodesConnection(elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2); - MeshFileHelpers::updateCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); - MeshFileHelpers::updateBoundaryCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); - } - if (cells[check_neighbor_cell2] == 0) - { - break; - } - } - } - } - else - break; - } - } - if (text_line.find("Zone Sections", 0) != string::npos) - break; - if (text_line.find(")") != string::npos) - continue; - } - mesh_topology_.erase(mesh_topology_.begin()); -} -//=================================================================================================// -void ANSYSMesh::getElementCenterCoordinates() -{ - elements_centroids_.resize(elements_nodes_connection_.size()); - elements_volumes_.resize(elements_nodes_connection_.size()); - for (std::size_t element = 1; element != elements_nodes_connection_.size(); ++element) - { - Vecd center_coordinate = Vecd::Zero(); - MeshFileHelpers::cellCenterCoordinates(elements_nodes_connection_, element, node_coordinates_, elements_centroids_, center_coordinate); - MeshFileHelpers::elementVolume(elements_nodes_connection_, element, node_coordinates_, elements_volumes_); - } - elements_volumes_.erase(elements_volumes_.begin()); - elements_centroids_.erase(elements_centroids_.begin()); - elements_nodes_connection_.erase(elements_nodes_connection_.begin()); -} -//=================================================================================================// -void ANSYSMesh::getMinimumDistanceBetweenNodes() -{ - vector all_data_of_distance_between_nodes; - all_data_of_distance_between_nodes.resize(0); - MeshFileHelpers::minimumdistance(all_data_of_distance_between_nodes, elements_volumes_, mesh_topology_, node_coordinates_); - auto min_distance_iter = std::min_element(all_data_of_distance_between_nodes.begin(), all_data_of_distance_between_nodes.end()); - if (min_distance_iter != all_data_of_distance_between_nodes.end()) - { - min_distance_between_nodes_ = *min_distance_iter; - } - else - { - cout << "The array of all distance between nodes is empty " << endl; - } -} -//=================================================================================================// -void BaseInnerRelationInFVM::resetNeighborhoodCurrentSize() -{ - parallel_for( - IndexRange(0, base_particles_.total_real_particles_), - [&](const IndexRange &r) - { - for (size_t num = r.begin(); num != r.end(); ++num) - { - inner_configuration_[num].current_size_ = 0; - } - }, - ap); -} -//=================================================================================================// -BaseInnerRelationInFVM::BaseInnerRelationInFVM(RealBody &real_body, ANSYSMesh &ansys_mesh) - : BaseInnerRelation(real_body), real_body_(&real_body), - node_coordinates_(ansys_mesh.node_coordinates_), - mesh_topology_(ansys_mesh.mesh_topology_) -{ - subscribeToBody(); - inner_configuration_.resize(base_particles_.real_particles_bound_, Neighborhood()); -}; -//=================================================================================================// -void NeighborBuilderInFVM::createRelation(Neighborhood &neighborhood, Real &distance, - Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const -{ - neighborhood.j_.push_back(j_index); - neighborhood.r_ij_.push_back(distance); - neighborhood.e_ij_.push_back(interface_normal_direction); - neighborhood.dW_ij_.push_back(dW_ij); - neighborhood.allocated_size_++; -} -//=================================================================================================// -void NeighborBuilderInFVM::initializeRelation(Neighborhood &neighborhood, Real &distance, - Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const -{ - size_t current_size = neighborhood.current_size_; - neighborhood.j_[current_size] = j_index; - neighborhood.dW_ij_[current_size] = dW_ij; - neighborhood.r_ij_[current_size] = distance; - neighborhood.e_ij_[current_size] = interface_normal_direction; -} -//=================================================================================================// -InnerRelationInFVM::InnerRelationInFVM(RealBody &real_body, ANSYSMesh &ansys_mesh) - : BaseInnerRelationInFVM(real_body, ansys_mesh), get_inner_neighbor_(&real_body){}; -//=================================================================================================// -template -void InnerRelationInFVM::searchNeighborsByParticles(size_t total_particles, BaseParticles &source_particles, - ParticleConfiguration &particle_configuration, - GetParticleIndex &get_particle_index, GetNeighborRelation &get_neighbor_relation) -{ - parallel_for( - IndexRange(0, base_particles_.total_real_particles_), - [&](const IndexRange &r) - { - StdLargeVec &pos_n = source_particles.pos_; - StdLargeVec &Vol_n = source_particles.Vol_; - for (size_t num = r.begin(); num != r.end(); ++num) - { - size_t index_i = get_particle_index(num); - Vecd &particle_position = pos_n[index_i]; - Real &Vol_i = Vol_n[index_i]; - - Neighborhood &neighborhood = particle_configuration[index_i]; - for (std::size_t neighbor = 0; neighbor != mesh_topology_[index_i].size(); ++neighbor) - { - size_t index_j = mesh_topology_[index_i][neighbor][0] - 1; - size_t boundary_type = mesh_topology_[index_i][neighbor][1]; - size_t interface_node1_index = mesh_topology_[index_i][neighbor][2]; - size_t interface_node2_index = mesh_topology_[index_i][neighbor][3]; - Vecd node1_position = Vecd(node_coordinates_[interface_node1_index][0], node_coordinates_[interface_node1_index][1]); - Vecd node2_position = Vecd(node_coordinates_[interface_node2_index][0], node_coordinates_[interface_node2_index][1]); - Vecd interface_area_vector = node1_position - node2_position; - Real interface_area_size = interface_area_vector.norm(); - Vecd unit_vector = interface_area_vector / interface_area_size; - // normal unit vector - Vecd normal_vector = Vecd(unit_vector[1], -unit_vector[0]); - // judge the direction - Vecd node1_to_center_direction = particle_position - node1_position; - if (node1_to_center_direction.dot(normal_vector) < 0) - { - normal_vector = -normal_vector; - }; - Real r_ij = 0; // we need r_ij to calculate the viscous force - // boundary_type == 2 means both of them are inside of fluid - if (boundary_type == 2) - { - r_ij = (particle_position - pos_n[index_j]).dot(normal_vector); - } - //this refer to the different types of wall boundary condtions - if ((boundary_type == 3) | (boundary_type == 4) | (boundary_type == 5) | (boundary_type == 7) | (boundary_type == 9) | (boundary_type == 10) | (boundary_type == 36)) - { - r_ij = node1_to_center_direction.dot(normal_vector) * 2.0; - } - Real dW_ij = -interface_area_size / (2.0 * Vol_i * Vol_n[index_j]); - get_neighbor_relation(neighborhood, r_ij, dW_ij, normal_vector, index_j); - } - } - }, - ap); -} -//=================================================================================================// -void InnerRelationInFVM::updateConfiguration() -{ - resetNeighborhoodCurrentSize(); - searchNeighborsByParticles(base_particles_.total_real_particles_, - base_particles_, inner_configuration_, - get_particle_index_, get_inner_neighbor_); -} -//=================================================================================================// -GhostCreationFromMesh::GhostCreationFromMesh(RealBody &real_body, ANSYSMesh &ansys_mesh, - Ghost &ghost_boundary) - : GeneralDataDelegateSimple(real_body), - ghost_boundary_(ghost_boundary), - node_coordinates_(ansys_mesh.node_coordinates_), - mesh_topology_(ansys_mesh.mesh_topology_), - pos_(particles_->pos_), Vol_(particles_->Vol_), - ghost_bound_(ghost_boundary.GhostBound()) -{ - ghost_boundary.checkParticlesReserved(); - each_boundary_type_with_all_ghosts_index_.resize(50); - each_boundary_type_with_all_ghosts_eij_.resize(50); - each_boundary_type_contact_real_index_.resize(50); - addGhostParticleAndSetInConfiguration(); -} -//=================================================================================================// -void GhostCreationFromMesh::addGhostParticleAndSetInConfiguration() -{ - ghost_bound_.second = ghost_bound_.first; - - for (size_t index_i = 0; index_i != particles_->total_real_particles_; ++index_i) - { - for (size_t neighbor_index = 0; neighbor_index != mesh_topology_[index_i].size(); ++neighbor_index) - { - size_t boundary_type = mesh_topology_[index_i][neighbor_index][1]; - if (mesh_topology_[index_i][neighbor_index][1] != 2) - { - mutex_create_ghost_particle_.lock(); - size_t ghost_particle_index = ghost_bound_.second; - ghost_bound_.second++; - ghost_boundary_.checkWithinGhostSize(ghost_bound_); - - particles_->updateGhostParticle(ghost_particle_index, index_i); - size_t node1_index = mesh_topology_[index_i][neighbor_index][2]; - size_t node2_index = mesh_topology_[index_i][neighbor_index][3]; - Vecd node1_position = node_coordinates_[node1_index]; - Vecd node2_position = node_coordinates_[node2_index]; - Vecd ghost_particle_position = 0.5 * (node1_position + node2_position); - - mesh_topology_[index_i][neighbor_index][0] = ghost_particle_index + 1; - pos_[ghost_particle_index] = ghost_particle_position; - mutex_create_ghost_particle_.unlock(); - - std::vector> new_element; - // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element - std::vector sub_element1 = {index_i + 1, boundary_type, node1_index, node2_index}; - new_element.push_back(sub_element1); - // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element - std::vector sub_element2 = {index_i + 1, boundary_type, node1_index, node2_index}; - new_element.push_back(sub_element2); - // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element - std::vector sub_element3 = {index_i + 1, boundary_type, node1_index, node2_index}; - new_element.push_back(sub_element3); - // Add the new element to mesh_topology_ - mesh_topology_.push_back(new_element); - // creating the boundary files with ghost particle index - each_boundary_type_with_all_ghosts_index_[boundary_type].push_back(ghost_particle_index); - // creating the boundary files with contact real particle index - each_boundary_type_contact_real_index_[boundary_type].push_back(index_i); - - // creating the boundary files with ghost eij - Vecd interface_area_vector = node1_position - node2_position; - Real interface_area_size = interface_area_vector.norm(); - Vecd unit_vector = interface_area_vector / interface_area_size; - // normal unit vector - Vecd normal_vector = Vecd(unit_vector[1], -unit_vector[0]); - // judge the direction - Vecd particle_position = pos_[index_i]; - Vecd node1_to_center_direction = particle_position - node1_position; - if (node1_to_center_direction.dot(normal_vector) < 0) - { - normal_vector = -normal_vector; - }; - each_boundary_type_with_all_ghosts_eij_[boundary_type].push_back(normal_vector); - } - } - } -}; -//=================================================================================================// -BodyStatesRecordingInMeshToVtp::BodyStatesRecordingInMeshToVtp(SPHBody &body, ANSYSMesh &ansys_mesh) - : BodyStatesRecording(body), node_coordinates_(ansys_mesh.node_coordinates_), - elements_nodes_connection_(ansys_mesh.elements_nodes_connection_){}; -//=================================================================================================// -void BodyStatesRecordingInMeshToVtp::writeWithFileName(const std::string &sequence) -{ - for (SPHBody *body : bodies_) - { - if (body->checkNewlyUpdated() && state_recording_) - { - // TODO: we can short the file name by without using SPHBody - std::string filefullpath = io_environment_.output_folder_ + "/" + body->getName() + "_" + sequence + ".vtp"; - if (fs::exists(filefullpath)) - { - fs::remove(filefullpath); - } - std::ofstream out_file(filefullpath.c_str(), std::ios::trunc); - // begin of the XML file - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - - // Write point data - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - - size_t total_nodes = node_coordinates_.size(); - for (size_t node = 0; node != total_nodes; ++node) - { - Vec3d particle_position = upgradeToVec3d(node_coordinates_[node]); - out_file << particle_position[0] << " " << particle_position[1] << " " << particle_position[2] << "\n"; - - } - - out_file << "\n"; - out_file << "\n"; - - // Write face data - out_file << "\n"; - out_file << "\n"; - - for (const auto &element : elements_nodes_connection_) - { - for (const auto &vertex : element) - { - out_file << vertex << " "; - } - out_file << "\n"; - } - - out_file << "\n"; - out_file << "\n"; - - size_t offset = 0; - for (const auto &face : elements_nodes_connection_) - { - offset += face.size(); - out_file << offset << " "; - } - - out_file << "\n\n"; - out_file << "\n"; - - // Write face attribute data - out_file << "\n"; - body->writeParticlesToVtpFile(out_file); - - out_file << "\n"; - - // Write file footer - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - - out_file.close(); - } - body->setNotNewlyUpdated(); - } -} -//=================================================================================================// -BoundaryConditionSetupInFVM:: - BoundaryConditionSetupInFVM(BaseInnerRelationInFVM &inner_relation, GhostCreationFromMesh &ghost_creation) - : fluid_dynamics::FluidDataInner(inner_relation), rho_(particles_->rho_), - Vol_(particles_->Vol_), mass_(particles_->mass_), - p_(*particles_->getVariableByName("Pressure")), - vel_(particles_->vel_), pos_(particles_->pos_), - mom_(*particles_->getVariableByName("Momentum")), - ghost_bound_(ghost_creation.ghost_bound_), - each_boundary_type_with_all_ghosts_index_(ghost_creation.each_boundary_type_with_all_ghosts_index_), - each_boundary_type_with_all_ghosts_eij_(ghost_creation.each_boundary_type_with_all_ghosts_eij_), - each_boundary_type_contact_real_index_(ghost_creation.each_boundary_type_contact_real_index_){}; -//=================================================================================================// -void BoundaryConditionSetupInFVM::resetBoundaryConditions() -{ - for (size_t boundary_type = 0; boundary_type < each_boundary_type_with_all_ghosts_index_.size(); ++boundary_type) - { - if (!each_boundary_type_with_all_ghosts_index_[boundary_type].empty()) - { - for (size_t ghost_number = 0; ghost_number != each_boundary_type_with_all_ghosts_index_[boundary_type].size(); ++ghost_number) - { - size_t ghost_index = each_boundary_type_with_all_ghosts_index_[boundary_type][ghost_number]; - size_t index_i = each_boundary_type_contact_real_index_[boundary_type][ghost_number]; - Vecd e_ij = each_boundary_type_with_all_ghosts_eij_[boundary_type][ghost_number]; - - // Dispatch the appropriate boundary condition - switch (boundary_type) - { - case 3: // this refer to the different types of wall boundary conditions - applyNonSlipWallBoundary(ghost_index, index_i); - applyReflectiveWallBoundary(ghost_index, index_i, e_ij); - break; - case 4: - applyTopBoundary(ghost_index, index_i); - break; - case 5: - applyPressureOutletBC(ghost_index, index_i); - break; - case 7: - applySymmetryBoundary(ghost_index, index_i, e_ij); - break; - case 9: - applyFarFieldBoundary(ghost_index); - break; - case 10: - applyGivenValueInletFlow(ghost_index); - applyVelocityInletFlow(ghost_index, index_i); - break; - case 36: - applyOutletBoundary(ghost_index, index_i); - break; - } - } - } - } -} -//=============================================================================================// -} // namespace SPH diff --git a/src/for_2D_build/bodies/unstructured_mesh_2d.cpp b/src/for_2D_build/bodies/unstructured_mesh_2d.cpp new file mode 100644 index 0000000000..7e67b5996f --- /dev/null +++ b/src/for_2D_build/bodies/unstructured_mesh_2d.cpp @@ -0,0 +1,232 @@ + +#include "mesh_helper.h" +#include "unstructured_mesh.h" + +#include "base_particle_dynamics.h" +namespace SPH +{ +//=================================================================================================// +ANSYSMesh::ANSYSMesh(const std::string &full_path) +{ + getDataFromMeshFile(full_path); + getElementCenterCoordinates(); + getMinimumDistanceBetweenNodes(); +} +//=================================================================================================// +void ANSYSMesh::getDataFromMeshFile(const std::string &full_path) +{ + std::ifstream mesh_file; /*!< \brief File object for the Ansys ASCII mesh file. */ + mesh_file.open(full_path); + if (mesh_file.fail()) + { + std::cout << "Error:Check if the file exists." << std::endl; + std::cout << __FILE__ << ':' << __LINE__ << std::endl; + } + std::string text_line; + /*--- Read the dimension of the problem ---*/ + size_t dimension(0); + MeshFileHelpers::meshDimension(mesh_file, dimension, text_line); + /*--- Check dimension ---*/ + if (dimension != Dimensions) + { + std::cout << "Error:the dimension of problem does not match input mesh." << std::endl; + std::cout << __FILE__ << ':' << __LINE__ << std::endl; + } + /*--- Read the total number node points ---*/ + size_t number_of_points(0); + MeshFileHelpers::numberOfNodes(mesh_file, number_of_points, text_line); + + /*--- Read the node coordinates ---*/ + MeshFileHelpers::nodeCoordinates(mesh_file, node_coordinates_, text_line, dimension); + /*--- Check number of node points ---*/ + if (node_coordinates_.size() != number_of_points) + { + std::cout << "Error:Total number of node points does not match data!" << std::endl; + std::cout << __FILE__ << ':' << __LINE__ << std::endl; + } + size_t boundary_type(0); + size_t number_of_elements(0); + size_t mesh_type = 3; + /*--- Read the total number of elements ---*/ + MeshFileHelpers::numberOfElements(mesh_file, number_of_elements, text_line); + + /*Preparing and initializing the data structure of mesh topology and element node connection*/ + MeshFileHelpers::dataStruct(mesh_topology_, elements_nodes_connection_, number_of_elements, mesh_type, dimension); + + while (getline(mesh_file, text_line)) + { + if (text_line.find("(13", 0) != std::string::npos && text_line.find(")(", 0) != std::string::npos) + { + /*--- find the type of boundary condition ---*/ + boundary_type = MeshFileHelpers::findBoundaryType(text_line, boundary_type); + types_of_boundary_condition_.push_back(boundary_type); + while (getline(mesh_file, text_line)) + { + if (text_line.find(")", 0) == std::string::npos) + { + Vecd nodes = MeshFileHelpers::nodeIndex(text_line); + Vec2d cells = MeshFileHelpers::cellIndex(text_line); + /*--- build up all topology---*/ + bool check_neighbor_cell1 = 1; + bool check_neighbor_cell2 = 0; + for (int cell1_cell2 = 0; cell1_cell2 != cells.size(); ++cell1_cell2) + { + if (mesh_type == 3) + { + if (cells[check_neighbor_cell2] != 0) + { + MeshFileHelpers::updateElementsNodesConnection(elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2); + MeshFileHelpers::updateCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); + MeshFileHelpers::updateBoundaryCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); + } + if (cells[check_neighbor_cell2] == 0) + { + break; + } + } + } + } + else + break; + } + } + if (text_line.find("Zone Sections", 0) != std::string::npos) + break; + if (text_line.find(")") != std::string::npos) + continue; + } + mesh_topology_.erase(mesh_topology_.begin()); +} +//=================================================================================================// +void ANSYSMesh::getElementCenterCoordinates() +{ + elements_centroids_.resize(elements_nodes_connection_.size()); + elements_volumes_.resize(elements_nodes_connection_.size()); + for (std::size_t element = 1; element != elements_nodes_connection_.size(); ++element) + { + Vecd center_coordinate = Vecd::Zero(); + MeshFileHelpers::cellCenterCoordinates(elements_nodes_connection_, element, node_coordinates_, elements_centroids_, center_coordinate); + MeshFileHelpers::elementVolume(elements_nodes_connection_, element, node_coordinates_, elements_volumes_); + } + elements_volumes_.erase(elements_volumes_.begin()); + elements_centroids_.erase(elements_centroids_.begin()); + elements_nodes_connection_.erase(elements_nodes_connection_.begin()); +} +//=================================================================================================// +void ANSYSMesh::getMinimumDistanceBetweenNodes() +{ + StdVec all_data_of_distance_between_nodes; + all_data_of_distance_between_nodes.resize(0); + MeshFileHelpers::minimumDistance(all_data_of_distance_between_nodes, elements_volumes_, mesh_topology_, node_coordinates_); + auto min_distance_iter = std::min_element(all_data_of_distance_between_nodes.begin(), all_data_of_distance_between_nodes.end()); + if (min_distance_iter != all_data_of_distance_between_nodes.end()) + { + min_distance_between_nodes_ = *min_distance_iter; + } + else + { + std::cout << "The array of all distance between nodes is empty " << std::endl; + } +} +//=================================================================================================// +void BaseInnerRelationInFVM::resetNeighborhoodCurrentSize() +{ + parallel_for( + IndexRange(0, base_particles_.total_real_particles_), + [&](const IndexRange &r) + { + for (size_t num = r.begin(); num != r.end(); ++num) + { + inner_configuration_[num].current_size_ = 0; + } + }, + ap); +} +//=================================================================================================// +void NeighborBuilderInFVM::createRelation(Neighborhood &neighborhood, Real &distance, + Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const +{ + neighborhood.j_.push_back(j_index); + neighborhood.r_ij_.push_back(distance); + neighborhood.e_ij_.push_back(interface_normal_direction); + neighborhood.dW_ij_.push_back(dW_ij); + neighborhood.allocated_size_++; +} +//=================================================================================================// +void NeighborBuilderInFVM::initializeRelation(Neighborhood &neighborhood, Real &distance, + Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const +{ + size_t current_size = neighborhood.current_size_; + neighborhood.j_[current_size] = j_index; + neighborhood.dW_ij_[current_size] = dW_ij; + neighborhood.r_ij_[current_size] = distance; + neighborhood.e_ij_[current_size] = interface_normal_direction; +} +//=================================================================================================// +InnerRelationInFVM::InnerRelationInFVM(RealBody &real_body, ANSYSMesh &ansys_mesh) + : BaseInnerRelationInFVM(real_body, ansys_mesh), get_inner_neighbor_(&real_body){}; +//=================================================================================================// +template +void InnerRelationInFVM::searchNeighborsByParticles(size_t total_particles, BaseParticles &source_particles, + ParticleConfiguration &particle_configuration, + GetParticleIndex &get_particle_index, GetNeighborRelation &get_neighbor_relation) +{ + parallel_for( + IndexRange(0, base_particles_.total_real_particles_), + [&](const IndexRange &r) + { + for (size_t num = r.begin(); num != r.end(); ++num) + { + size_t index_i = get_particle_index(num); + Vecd &particle_position = pos_[index_i]; + + Neighborhood &neighborhood = particle_configuration[index_i]; + for (std::size_t neighbor = 0; neighbor != mesh_topology_[index_i].size(); ++neighbor) + { + size_t index_j = mesh_topology_[index_i][neighbor][0] - 1; + size_t boundary_type = mesh_topology_[index_i][neighbor][1]; + size_t interface_node1_index = mesh_topology_[index_i][neighbor][2]; + size_t interface_node2_index = mesh_topology_[index_i][neighbor][3]; + Vecd node1_position = Vecd(node_coordinates_[interface_node1_index][0], node_coordinates_[interface_node1_index][1]); + Vecd node2_position = Vecd(node_coordinates_[interface_node2_index][0], node_coordinates_[interface_node2_index][1]); + Vecd interface_area_StdVec = node1_position - node2_position; + Real interface_area_size = interface_area_StdVec.norm(); + Vecd unit_StdVec = interface_area_StdVec / interface_area_size; + // normal unit StdVec + Vecd normal_StdVec = Vecd(unit_StdVec[1], -unit_StdVec[0]); + // judge the direction + Vecd node1_to_center_direction = particle_position - node1_position; + if (node1_to_center_direction.dot(normal_StdVec) < 0) + { + normal_StdVec = -normal_StdVec; + }; + Real r_ij = 0; // we need r_ij to calculate the viscous force + // boundary_type == 2 means both of them are inside of fluid + if (boundary_type == 2) + { + r_ij = (particle_position - pos_[index_j]).dot(normal_StdVec); + } + // this refer to the different types of wall boundary conditions + if ((boundary_type == 3) | (boundary_type == 4) | (boundary_type == 5) | + (boundary_type == 7) | (boundary_type == 9) | (boundary_type == 10) | + (boundary_type == 36)) + { + r_ij = node1_to_center_direction.dot(normal_StdVec) * 2.0; + } + Real dW_ij = -interface_area_size / (2.0 * Vol_[index_i] * Vol_[index_j]); + get_neighbor_relation(neighborhood, r_ij, dW_ij, normal_StdVec, index_j); + } + } + }, + ap); +} +//=================================================================================================// +void InnerRelationInFVM::updateConfiguration() +{ + resetNeighborhoodCurrentSize(); + searchNeighborsByParticles(base_particles_.total_real_particles_, + base_particles_, inner_configuration_, + get_particle_index_, get_inner_neighbor_); +} +//=============================================================================================// +} // namespace SPH diff --git a/src/for_2D_build/common/scalar_functions_supplementary.cpp b/src/for_2D_build/common/scalar_functions_2d.cpp similarity index 100% rename from src/for_2D_build/common/scalar_functions_supplementary.cpp rename to src/for_2D_build/common/scalar_functions_2d.cpp diff --git a/src/for_2D_build/common/vector_functions_supplementary.cpp b/src/for_2D_build/common/vector_functions_2d.cpp similarity index 100% rename from src/for_2D_build/common/vector_functions_supplementary.cpp rename to src/for_2D_build/common/vector_functions_2d.cpp diff --git a/src/for_2D_build/geometries/level_set_supplementary.cpp b/src/for_2D_build/geometries/level_set_2d.cpp similarity index 100% rename from src/for_2D_build/geometries/level_set_supplementary.cpp rename to src/for_2D_build/geometries/level_set_2d.cpp diff --git a/src/for_2D_build/io_system/io_vtk_fvm_2d.cpp b/src/for_2D_build/io_system/io_vtk_fvm_2d.cpp new file mode 100644 index 0000000000..78e3bd2844 --- /dev/null +++ b/src/for_2D_build/io_system/io_vtk_fvm_2d.cpp @@ -0,0 +1,92 @@ +#include "io_vtk_fvm.h" + +namespace SPH +{ +//=================================================================================================// +void BodyStatesRecordingInMeshToVtp::writeWithFileName(const std::string &sequence) +{ + for (SPHBody *body : bodies_) + { + if (body->checkNewlyUpdated() && state_recording_) + { + // TODO: we can short the file name by without using SPHBody + std::string filefullpath = io_environment_.output_folder_ + "/" + body->getName() + "_" + sequence + ".vtp"; + if (fs::exists(filefullpath)) + { + fs::remove(filefullpath); + } + std::ofstream out_file(filefullpath.c_str(), std::ios::trunc); + // begin of the XML file + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + + // Write point data + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + + size_t total_nodes = node_coordinates_.size(); + for (size_t node = 0; node != total_nodes; ++node) + { + Vec3d particle_position = upgradeToVec3d(node_coordinates_[node]); + out_file << particle_position[0] << " " << particle_position[1] << " " << particle_position[2] << "\n"; + } + + out_file << "\n"; + out_file << "\n"; + + // Write face data + out_file << "\n"; + out_file << "\n"; + + for (const auto &element : elements_nodes_connection_) + { + for (const auto &vertex : element) + { + out_file << vertex << " "; + } + out_file << "\n"; + } + + out_file << "\n"; + out_file << "\n"; + + size_t offset = 0; + for (const auto &face : elements_nodes_connection_) + { + offset += face.size(); + out_file << offset << " "; + } + + out_file << "\n\n"; + out_file << "\n"; + + // Write face attribute data + out_file << "\n"; + body->writeParticlesToVtpFile(out_file); + + out_file << "\n"; + + // Write file footer + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + + out_file.close(); + } + body->setNotNewlyUpdated(); + } +} +//=================================================================================================// +void BodyStatesRecordingInMeshToVtu::writeWithFileName(const std::string &sequence) +{ + std::cout << "For 2D build:" + << "The method BodyStatesRecordingInMeshToVtu::writeWithFileName not implemented yet." + << std::endl; + exit(1); +} +//=================================================================================================// +} // namespace SPH diff --git a/src/for_2D_build/materials/elastic_solid_supplementary.cpp b/src/for_2D_build/materials/elastic_solid_2d.cpp similarity index 100% rename from src/for_2D_build/materials/elastic_solid_supplementary.cpp rename to src/for_2D_build/materials/elastic_solid_2d.cpp diff --git a/src/for_2D_build/meshes/base_mesh_supplementary.cpp b/src/for_2D_build/meshes/base_mesh_2d.cpp similarity index 100% rename from src/for_2D_build/meshes/base_mesh_supplementary.cpp rename to src/for_2D_build/meshes/base_mesh_2d.cpp diff --git a/src/for_2D_build/meshes/cell_linked_list.hpp b/src/for_2D_build/meshes/cell_linked_list.hpp index 4c34cd24d5..222c64fb9a 100644 --- a/src/for_2D_build/meshes/cell_linked_list.hpp +++ b/src/for_2D_build/meshes/cell_linked_list.hpp @@ -22,7 +22,7 @@ void CellLinkedList::searchNeighborsByParticles( DynamicsRange &dynamics_range, ParticleConfiguration &particle_configuration, GetSearchDepth &get_search_depth, GetNeighborRelation &get_neighbor_relation) { - StdLargeVec &pos = dynamics_range.getBaseParticles().pos_; + StdLargeVec &pos = dynamics_range.getBaseParticles().ParticlePositions(); particle_for(execution::ParallelPolicy(), dynamics_range.LoopRange(), [&](size_t index_i) { diff --git a/src/for_2D_build/meshes/cell_linked_list_supplementary.cpp b/src/for_2D_build/meshes/cell_linked_list_2d.cpp similarity index 99% rename from src/for_2D_build/meshes/cell_linked_list_supplementary.cpp rename to src/for_2D_build/meshes/cell_linked_list_2d.cpp index a9f5bd2973..e22acfc657 100644 --- a/src/for_2D_build/meshes/cell_linked_list_supplementary.cpp +++ b/src/for_2D_build/meshes/cell_linked_list_2d.cpp @@ -36,7 +36,7 @@ void CellLinkedList::clearCellLists() //=================================================================================================// void CellLinkedList::UpdateCellListData(BaseParticles &base_particles) { - StdLargeVec &pos = base_particles.pos_; + StdLargeVec &pos = base_particles.ParticlePositions(); mesh_parallel_for( MeshRange(Array2i::Zero(), all_cells_), [&](int i, int j) diff --git a/src/for_2D_build/particle_dynamics/general_dynamics/fvm_ghost_boundary_2d.cpp b/src/for_2D_build/particle_dynamics/general_dynamics/fvm_ghost_boundary_2d.cpp new file mode 100644 index 0000000000..c597a873f4 --- /dev/null +++ b/src/for_2D_build/particle_dynamics/general_dynamics/fvm_ghost_boundary_2d.cpp @@ -0,0 +1,115 @@ +#include "fvm_ghost_boundary.h" + +#include "base_particles.hpp" + +namespace SPH +{ +//=================================================================================================// +void GhostCreationFromMesh::addGhostParticleAndSetInConfiguration() +{ + ghost_bound_.second = ghost_bound_.first; + + for (size_t index_i = 0; index_i != particles_->total_real_particles_; ++index_i) + { + for (size_t neighbor_index = 0; neighbor_index != mesh_topology_[index_i].size(); ++neighbor_index) + { + size_t boundary_type = mesh_topology_[index_i][neighbor_index][1]; + if (mesh_topology_[index_i][neighbor_index][1] != 2) + { + mutex_create_ghost_particle_.lock(); + size_t ghost_particle_index = ghost_bound_.second; + ghost_bound_.second++; + ghost_boundary_.checkWithinGhostSize(ghost_bound_); + + particles_->updateGhostParticle(ghost_particle_index, index_i); + size_t node1_index = mesh_topology_[index_i][neighbor_index][2]; + size_t node2_index = mesh_topology_[index_i][neighbor_index][3]; + Vecd node1_position = node_coordinates_[node1_index]; + Vecd node2_position = node_coordinates_[node2_index]; + Vecd ghost_particle_position = 0.5 * (node1_position + node2_position); + + mesh_topology_[index_i][neighbor_index][0] = ghost_particle_index + 1; + pos_[ghost_particle_index] = ghost_particle_position; + mutex_create_ghost_particle_.unlock(); + + std::vector> new_element; + // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element + std::vector sub_element1 = {index_i + 1, boundary_type, node1_index, node2_index}; + new_element.push_back(sub_element1); + // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element + std::vector sub_element2 = {index_i + 1, boundary_type, node1_index, node2_index}; + new_element.push_back(sub_element2); + // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element + std::vector sub_element3 = {index_i + 1, boundary_type, node1_index, node2_index}; + new_element.push_back(sub_element3); + // Add the new element to mesh_topology_ + mesh_topology_.push_back(new_element); + // creating the boundary files with ghost particle index + each_boundary_type_with_all_ghosts_index_[boundary_type].push_back(ghost_particle_index); + // creating the boundary files with contact real particle index + each_boundary_type_contact_real_index_[boundary_type].push_back(index_i); + + // creating the boundary files with ghost eij + Vecd interface_area_vector = node1_position - node2_position; + Real interface_area_size = interface_area_vector.norm(); + Vecd unit_vector = interface_area_vector / interface_area_size; + // normal unit vector + Vecd normal_vector = Vecd(unit_vector[1], -unit_vector[0]); + // judge the direction + Vecd particle_position = pos_[index_i]; + Vecd node1_to_center_direction = particle_position - node1_position; + if (node1_to_center_direction.dot(normal_vector) < 0) + { + normal_vector = -normal_vector; + }; + each_boundary_type_with_all_ghosts_eij_[boundary_type].push_back(normal_vector); + } + } + } +} +//=================================================================================================// +void BoundaryConditionSetupInFVM::resetBoundaryConditions() +{ + for (size_t boundary_type = 0; boundary_type < each_boundary_type_with_all_ghosts_index_.size(); ++boundary_type) + { + if (!each_boundary_type_with_all_ghosts_index_[boundary_type].empty()) + { + for (size_t ghost_number = 0; ghost_number != each_boundary_type_with_all_ghosts_index_[boundary_type].size(); ++ghost_number) + { + size_t ghost_index = each_boundary_type_with_all_ghosts_index_[boundary_type][ghost_number]; + size_t index_i = each_boundary_type_contact_real_index_[boundary_type][ghost_number]; + Vecd e_ij = each_boundary_type_with_all_ghosts_eij_[boundary_type][ghost_number]; + + // Dispatch the appropriate boundary condition + switch (boundary_type) + { + case 3: // this refer to the different types of wall boundary conditions + applyNonSlipWallBoundary(ghost_index, index_i); + applyReflectiveWallBoundary(ghost_index, index_i, e_ij); + break; + case 4: + applyTopBoundary(ghost_index, index_i); + break; + case 5: + applyPressureOutletBC(ghost_index, index_i); + break; + case 7: + applySymmetryBoundary(ghost_index, index_i, e_ij); + break; + case 9: + applyFarFieldBoundary(ghost_index); + break; + case 10: + applyGivenValueInletFlow(ghost_index); + applyVelocityInletFlow(ghost_index, index_i); + break; + case 36: + applyOutletBoundary(ghost_index, index_i); + break; + } + } + } + } +} +//=================================================================================================// +} // namespace SPH diff --git a/src/for_2D_build/particle_dynamics/solid_dynamics/solid_dynamics_2d.cpp b/src/for_2D_build/particle_dynamics/solid_dynamics/solid_dynamics_2d.cpp new file mode 100644 index 0000000000..15fad55e60 --- /dev/null +++ b/src/for_2D_build/particle_dynamics/solid_dynamics/solid_dynamics_2d.cpp @@ -0,0 +1,38 @@ +#include "all_solid_dynamics.h" +#include "base_data_package.h" +#include "base_kernel.h" +#include "base_particles.hpp" +#include "cell_linked_list.h" +#include "elastic_solid.h" +#include "external_force.h" +#include "neighborhood.h" +#include "solid_body.h" +#include "weakly_compressible_fluid.h" + +#include "SimTKcommon.h" +#include "SimTKmath.h" +#include "Simbody.h" + +namespace SPH +{ +namespace solid_dynamics +{ +//=========================================================================================// +Vec2d UpdateElasticNormalDirection::getRotatedNormalDirection(const Mat2d &F, const Vec2d &n0) +{ + // deformation tensor in 2D + Real F00 = F(0, 0); + Real F01 = F(0, 1); + Real F10 = F(1, 0); + Real F11 = F(1, 1); + // polar decomposition + Mat2d R{ + {F00 + F11, F01 - F10}, + {F10 - F01, F00 + F11}, + }; + + return R * n0 / sqrt(pow(F00 + F11, 2) + pow(F01 - F10, 2)); +} +//=================================================================================================// +} // namespace solid_dynamics +} // namespace SPH diff --git a/src/for_2D_build/particles/solid_particles_supplementary.cpp b/src/for_2D_build/particle_dynamics/solid_dynamics/solid_dynamics_variable_2d.cpp similarity index 61% rename from src/for_2D_build/particles/solid_particles_supplementary.cpp rename to src/for_2D_build/particle_dynamics/solid_dynamics/solid_dynamics_variable_2d.cpp index 9a22db999e..03f7ea8644 100644 --- a/src/for_2D_build/particles/solid_particles_supplementary.cpp +++ b/src/for_2D_build/particle_dynamics/solid_dynamics/solid_dynamics_variable_2d.cpp @@ -1,38 +1,36 @@ #include "base_body.h" -#include "solid_particles.h" -#include "solid_particles_variable.h" +#include "solid_dynamics_variable.h" namespace SPH { //=================================================================================================// -Real ElasticSolidParticles::getVonMisesStrain(size_t particle_i) // not tested in 2D +void VonMisesStrain::update(size_t index_i, Real dt) { + Mat2d F = F_[index_i]; + Mat2d green_lagrange_strain = 0.5 * (F.transpose() * F - Matd::Identity()); - Matd F = F_[particle_i]; - Matd epsilon = 0.5 * (F.transpose() * F - Matd::Identity()); // calculation of the Green-Lagrange strain tensor - - Real epsilonxx = epsilon(0, 0); - Real epsilonyy = epsilon(1, 1); + Real epsilonxx = green_lagrange_strain(0, 0); + Real epsilonyy = green_lagrange_strain(1, 1); Real epsilonzz = 0; // z-components zero for 2D measures - Real epsilonxy = epsilon(0, 1); + Real epsilonxy = green_lagrange_strain(0, 1); Real epsilonxz = 0; // z-components zero for 2D measures Real epsilonyz = 0; // z-components zero for 2D measures - return sqrt((1.0 / 3.0) * (pow(epsilonxx - epsilonyy, 2) + pow(epsilonyy - epsilonzz, 2) + - pow(epsilonzz - epsilonxx, 2)) + - 2.0 * (pow(epsilonxy, 2) + pow(epsilonyz, 2) + pow(epsilonxz, 2))); + derived_variable_[index_i] = sqrt((1.0 / 3.0) * (pow(epsilonxx - epsilonyy, 2) + pow(epsilonyy - epsilonzz, 2) + + pow(epsilonzz - epsilonxx, 2)) + + 2.0 * (pow(epsilonxy, 2) + pow(epsilonyz, 2) + pow(epsilonxz, 2))); } //=================================================================================================// -Real ElasticSolidParticles::getVonMisesStrainDynamic(size_t particle_i, Real poisson) // not tested in 2D +void VonMisesStrainDynamic::update(size_t index_i, Real dt) { - Mat2d F = F_[particle_i]; - Mat2d epsilon = 0.5 * (F.transpose() * F - Matd::Identity()); // calculation of the Green-Lagrange strain tensor - Vec2d principal_strains = getPrincipalValuesFromMatrix(epsilon); + Mat2d F = F_[index_i]; + Mat2d green_lagrange_strain = 0.5 * (F.transpose() * F - Matd::Identity()); + Vec2d principal_strains = getPrincipalValuesFromMatrix(green_lagrange_strain); Real eps_1 = principal_strains[0]; Real eps_2 = principal_strains[1]; - return 1.0 / (1.0 + poisson) * sqrt(0.5 * (pow(eps_1 - eps_2, 2))); + derived_variable_[index_i] = 1.0 / (1.0 + poisson_ratio_) * sqrt(0.5 * (pow(eps_1 - eps_2, 2))); } //=============================================================================================// void VonMisesStress::update(size_t index_i, Real dt) diff --git a/src/for_2D_build/particle_generator/particle_generator_lattice_supplementary.cpp b/src/for_2D_build/particle_generator/particle_generator_lattice_2d.cpp similarity index 100% rename from src/for_2D_build/particle_generator/particle_generator_lattice_supplementary.cpp rename to src/for_2D_build/particle_generator/particle_generator_lattice_2d.cpp diff --git a/src/for_3D_build/bodies/mesh_helper.cpp b/src/for_3D_build/bodies/mesh_helper.cpp deleted file mode 100644 index 27cb469695..0000000000 --- a/src/for_3D_build/bodies/mesh_helper.cpp +++ /dev/null @@ -1,639 +0,0 @@ -#include "mesh_helper.h" -namespace SPH -{ - - void MeshFileHelpers::meshDimension(ifstream& mesh_file, size_t& dimension, string& text_line) - { - while (getline(mesh_file, text_line)) - { - (getline(mesh_file, text_line)); - text_line.erase(0, 1); - text_line.erase(0, 2); - istringstream value(text_line); - if (text_line.find("3", 0) != string::npos) - { - dimension = atoi(text_line.c_str()); - break; - } - - } - - } - - void MeshFileHelpers::numberofNodes(ifstream& mesh_file, size_t& number_of_points, string& text_line) - { - while (getline(mesh_file, text_line)) - { - text_line.erase(0, 1); - string text1(text_line); - text_line.erase(3); - string text2(text_line); - text_line.erase(2); - if (atoi(text_line.c_str()) == 10 && text1.find("))", 0) != string::npos) - { - text1.erase(0, 8); - Real last_position = text1.find_last_of(")"); - text1.erase(last_position - 5); - number_of_points = stoi(text1, nullptr, 16); - break; - } - } - } - - void MeshFileHelpers::nodeCoordinates(ifstream& mesh_file, StdLargeVec& node_coordinates_, string& text_line, size_t& dimension) - { - while (getline(mesh_file, text_line)) - { - if (text_line.find("(", 0) == string::npos && text_line.find("))", 0) == string::npos) - { - if (text_line.find(" ", 0) != string::npos) - { - if (dimension == 3) - { - size_t first_devide_position = text_line.find_first_of(" "); - size_t last_devide_position = text_line.find_last_of(" "); - string x_part = text_line; - string y_part = text_line; - string z_part = text_line; - string x_coordinate_string = x_part.erase(first_devide_position); - string y_coordinate_string = y_part.erase(last_devide_position); - y_coordinate_string = y_coordinate_string.erase(0, first_devide_position); - string z_coordinate_string = z_part.erase(0, last_devide_position); - istringstream streamx, streamy, streamz; - Vecd Coords = Vecd::Zero(); - streamx.str(x_coordinate_string); - streamy.str(y_coordinate_string); - streamz.str(z_coordinate_string); - streamx >> Coords[0]; - streamy >> Coords[1]; - streamz >> Coords[2]; - - node_coordinates_.push_back(Coords); - } - } - } - if (text_line.find("))", 0) != string::npos) - { - break; - } - } - } - - void MeshFileHelpers::numberofElements(ifstream& mesh_file, size_t& number_of_elements, string& text_line) - { - - while (getline(mesh_file, text_line)) - { - text_line.erase(0, 1); - string text1(text_line); - text_line.erase(3); - string text2(text_line); - text_line.erase(2); - if (atoi(text_line.c_str()) == 12) - { - text1.erase(0, 8); - Real last_position = text1.find_last_of(")"); - text1.erase(last_position - 5); - number_of_elements = stoi(text1, nullptr, 16); - break; - } - } - } - - void MeshFileHelpers::dataStruct(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - size_t number_of_elements, size_t mesh_type, size_t dimension) - { - - mesh_topology_.resize(number_of_elements + 1); - for (std::size_t a = 0; a != number_of_elements + 1; ++a) - { - mesh_topology_[a].resize(mesh_type); - for (std::vector>::size_type b = 0; b != mesh_topology_[a].size(); ++b) - { - mesh_topology_[a][b].resize(dimension + 2); - for (std::vector::size_type c = 0; c != mesh_topology_[a][b].size(); ++c) - { - mesh_topology_[a][b][c] = -1; - } - } - } - /*--- reinitialize the number of elements ---*/ - elements_nodes_connection_.resize(number_of_elements + 1); - mesh_topology_.resize(number_of_elements + 1); - for (std::size_t element = 0; element != number_of_elements + 1; ++element) - { - elements_nodes_connection_[element].resize(4); - for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) - { - elements_nodes_connection_[element][node] = -1; - } - } - } - - size_t MeshFileHelpers::findBoundaryType(string& text_line, size_t boundary_type) - { - /*--- Read the elements of the problem (13 (id f1 f2 type 0) (---*/ - /** differnet boundary conditions - * bc-type==2, interior boundary condition. - * bc-type==3, wall boundary condition. - * bc-type==4, Pressure Inlet boundary condition - * bc-type==5, Pressure Outlet boundary condition - * bc-type==7, Symmetry boundary condition - * bc-type==9, pressure-far-field boundary condition. - * bc-type==a, Velocity Inlet boundary condition. - * bc-type==c, Periodic boundary condition. - * bc-type==e, porous jumps boundary condition. - * bc-type==14,Mass Flow Inlet boundary condition. - * Note that Cell0 means boundary condition. - * mesh_type==4, unstructured mesh. - * mesh_type==6, structured mesh. - * cell_lists_ - * {[(neighbor_cell_index, bc_type, node1_of_face, node2_of_face, node3_of_face), (....), (.....)], []..... }. - * {inner_neighbor1, inner_neighbor2,inner_neighbor3, inner_neighbor4 ..... }. - */ - /*--- find the type of boundary condition ---*/ - size_t position = text_line.find(")", 0); - text_line = text_line.erase(0, position - 4); - text_line = text_line.erase(2); - boundary_type = stoi(text_line, nullptr, 16); - return boundary_type; - } - - Vecd MeshFileHelpers::nodeIndex(string& text_line) - - { - /*--- find the node1 between two cells ---*/ - string node1_string_copy = text_line; - size_t first_devide_position = text_line.find_first_of(" ", 0); - string node1_index_string = node1_string_copy.erase(first_devide_position); - size_t node1_index_decimal = stoi(node1_index_string, nullptr, 16) - 1; - - /*--- find the node2 between two cells---*/ - string node2_string = text_line; - string node3_string = text_line; - node2_string = node2_string.erase(0, first_devide_position + 1); - node3_string = node2_string; - size_t second_devide_position = node2_string.find_first_of(" ", 0); - node2_string.erase(second_devide_position); - size_t node2_index_decimal = stoi(node2_string, nullptr, 16) - 1; - - /*--- find the node3 between two cells---*/ - node3_string = node3_string.erase(0, second_devide_position + 1); - size_t third_devide_position = node3_string.find_first_of(" ", 0); - node3_string.erase(third_devide_position); - size_t node3_index_decimal = stoi(node3_string, nullptr, 16) - 1; - - Vecd nodes = Vecd(node1_index_decimal, node2_index_decimal, node3_index_decimal); - return nodes; - } - - Vec2d MeshFileHelpers::cellIndex(string& text_line) - { - - /*--- find the cell1---*/ - string cell1_string = text_line; - string cell2_string = text_line; - string cell3_string = text_line; - size_t first_devide_position = text_line.find_first_of(" ", 0); - cell1_string = cell1_string.erase(0, first_devide_position + 1); - size_t second_devide_position = cell1_string.find_first_of(" ", 0); - cell2_string = cell1_string.erase(0, second_devide_position + 1); - size_t third_devide_position = cell2_string.find_first_of(" ", 0); - cell3_string = cell2_string.erase(0, third_devide_position + 1); - size_t fourth_devide_position = cell3_string.find_first_of(" ", 0); - cell3_string.erase(fourth_devide_position); - size_t cell1_index_decimal = stoi(cell3_string, nullptr, 16); - - /*--- find the cell2---*/ - string cell4_string = text_line; - cell4_string = cell4_string.erase(0, first_devide_position + 1); - cell4_string = cell4_string.erase(0, second_devide_position + 1); - cell4_string = cell4_string.erase(0, third_devide_position + 1); - cell4_string.erase(0, fourth_devide_position + 1); - size_t cell2_index_decimal = stoi(cell4_string, nullptr, 16); - Vec2d cells = Vec2d(cell1_index_decimal, cell2_index_decimal); - return cells; - } - - void MeshFileHelpers::updateElementsNodesConnection(StdLargeVec>& elements_nodes_connection_, Vecd nodes, Vec2d cells, - bool& check_neighbor_cell1, bool& check_neighbor_cell2) - { - - /*--- build up connection with element and nodes only---*/ - for (int node = 0; node != nodes.size(); ++node) - { - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][1] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][2] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][3] != nodes[node]) - { - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && (elements_nodes_connection_[cells[check_neighbor_cell2]][1] != static_cast>(-1)) && elements_nodes_connection_[cells[check_neighbor_cell2]][2] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][3] == static_cast>(-1)) - { - elements_nodes_connection_[cells[check_neighbor_cell2]][3] = nodes[node]; - } - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][1] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][2] == static_cast>(-1)) - { - elements_nodes_connection_[cells[check_neighbor_cell2]][2] = nodes[node]; - } - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][1] == static_cast>(-1)) - { - elements_nodes_connection_[cells[check_neighbor_cell2]][1] = nodes[node]; - } - if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] == static_cast>(-1)) - { - elements_nodes_connection_[cells[check_neighbor_cell2]][0] = nodes[node]; - } - - } - else - continue; - } - } - - void MeshFileHelpers::updateCellLists(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, Vecd nodes, - Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type) - { - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][1][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][2][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][3][0] != cells[check_neighbor_cell1]) - { - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(-1)) - { - /*--- inner neighbor index---*/ - mesh_topology_[cells[check_neighbor_cell2]][0][0] = cells[check_neighbor_cell1]; - /*--- boundary type---*/ - mesh_topology_[cells[check_neighbor_cell2]][0][1] = boundary_type; - /*--- nodes of a face---*/ - mesh_topology_[cells[check_neighbor_cell2]][0][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][0][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][0][4] = nodes[2]; - - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][1][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][1][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][1][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][1][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][1][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][2][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][3][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][3][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][3][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][3][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][3][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - } - - - } - - void MeshFileHelpers::updateBoundaryCellLists(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - Vecd nodes, Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type) - { - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][2][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][3][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][3][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][3][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][3][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][3][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][3][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][3][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][3][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][3][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][3][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - else - { - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - - } - - void MeshFileHelpers::cellCenterCoordinates(StdLargeVec>& elements_nodes_connection_, std::size_t& element, - StdLargeVec& node_coordinates_, StdLargeVec& elements_centroids_, Vecd& center_coordinate) - { - - for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) - { - center_coordinate += node_coordinates_[elements_nodes_connection_[element][node]] / 4.0; - } - elements_centroids_[element] = center_coordinate; - } - - void MeshFileHelpers::elementVolume(StdLargeVec>& elements_nodes_connection_, std::size_t& element, - StdLargeVec& node_coordinates_, StdLargeVec& elements_volumes_) - { - // get nodes position - Real Total_volume = 0; - using Vec4d = Eigen::Matrix; - Vec4d nodes = Vec4d(elements_nodes_connection_[element][0], elements_nodes_connection_[element][1], elements_nodes_connection_[element][2], elements_nodes_connection_[element][3]); - Vecd node1_coordinate = Vecd(node_coordinates_[nodes[0]][0], node_coordinates_[nodes[0]][1], node_coordinates_[nodes[0]][2]); - Vecd node2_coordinate = Vecd(node_coordinates_[nodes[1]][0], node_coordinates_[nodes[1]][1], node_coordinates_[nodes[1]][2]); - Vecd node3_coordinate = Vecd(node_coordinates_[nodes[2]][0], node_coordinates_[nodes[2]][1], node_coordinates_[nodes[2]][2]); - Vecd node4_coordinate = Vecd(node_coordinates_[nodes[3]][0], node_coordinates_[nodes[3]][1], node_coordinates_[nodes[3]][2]); - Matd M; - M << node2_coordinate - node1_coordinate, node3_coordinate - node1_coordinate, node4_coordinate - node1_coordinate; - Real determinant = abs(M.determinant()); - Real element_volume = (static_cast(1) / 6) * determinant; - Total_volume += element_volume; - elements_volumes_[element] = element_volume; - } - - void MeshFileHelpers::minimumdistance(vector& all_data_of_distance_between_nodes, StdLargeVec& elements_volumes_, vector>>& mesh_topology_, - StdLargeVec& node_coordinates_) - { - - for (size_t element_index = 0; element_index != elements_volumes_.size(); ++element_index) - { - - for (std::size_t neighbor = 0; neighbor != mesh_topology_[element_index].size(); ++neighbor) - { - - size_t interface_node1_index = mesh_topology_[element_index][neighbor][2]; - size_t interface_node2_index = mesh_topology_[element_index][neighbor][3]; - size_t interface_node3_index = mesh_topology_[element_index][neighbor][4]; - Vecd node1_position = node_coordinates_[interface_node1_index]; - Vecd node2_position = node_coordinates_[interface_node2_index]; - Vecd node3_position = node_coordinates_[interface_node3_index]; - Vecd interface_area_vector1 = node2_position - node1_position; - Vecd interface_area_vector2 = node3_position - node1_position; - Vecd area_vector = interface_area_vector1.cross(interface_area_vector2); - Real triangle_area = 0.5 * area_vector.norm(); - Real distance = sqrt(triangle_area); - all_data_of_distance_between_nodes.push_back(distance); - } - } - } - - void MeshFileHelpers::vtuFileHeader(std::ofstream& out_file) - { - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "0\n"; - out_file << "\n"; - out_file << "\n"; - } - - - void MeshFileHelpers::vtuFileNodeCoordinates(std::ofstream& out_file, StdLargeVec& node_coordinates_, - StdLargeVec>& elements_nodes_connection_, SPHBody& bounds_, Real& rangemax) - { - // Write point data - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - BoundingBox bounds = bounds_.getSPHSystemBounds(); - Real first_max = bounds.first_.cwiseAbs().maxCoeff(); - Real second_max = bounds.second_.cwiseAbs().maxCoeff(); - rangemax = 1.03075 * (std::max(first_max, second_max)); - out_file << "\n"; - - size_t total_nodes = node_coordinates_.size(); - for (size_t node = 0; node != total_nodes; ++node) - { - out_file << node_coordinates_[node][0] << " " << node_coordinates_[node][1] << " " << node_coordinates_[node][2] << " \n"; - } - - } - - void MeshFileHelpers::vtuFileInformationKey(std::ofstream& out_file, Real& rangemax) - { - out_file << "\n"; - out_file << "\n"; - out_file << "0\n"; - out_file << "\n"; - out_file << "\n"; - out_file << rangemax << " \n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "0\n"; - out_file << "\n"; - out_file << "\n"; - out_file << rangemax << " \n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - - } - - void MeshFileHelpers::vtuFileCellConnectivity(std::ofstream& out_file, StdLargeVec>& elements_nodes_connection_, StdLargeVec& node_coordinates_) - { - out_file << "\n"; - // Write Cell data - out_file << "\n"; - - for (const auto& cell : elements_nodes_connection_) - { - for (const auto& vertex : cell) - { - out_file << vertex << " "; - } - out_file << "\n"; - } - - out_file << "\n"; - } - - - void MeshFileHelpers::vtuFileOffsets(std::ofstream& out_file, StdLargeVec>& elements_nodes_connection_) - { - out_file << "\n"; - - size_t offset = 0; - for (const auto& face : elements_nodes_connection_) - { - offset += face.size(); - out_file << offset << " "; - } - out_file << "\n\n"; - } - - void MeshFileHelpers::vtuFileTypeOfCell(std::ofstream& out_file, StdLargeVec>& elements_nodes_connection_) - { - size_t type = 10; - //Specifies type of cell 10 = tetrahedral - out_file << "\n"; - for (const auto& types : elements_nodes_connection_) - { - for (size_t i = 0; i < types.size(); ++i) - { - out_file << type << " "; - } - out_file << "\n"; - } - // Write face attribute data - out_file << "\n"; - out_file << "\n"; - } - - void MeshFileHelpers::numberofNodesFluent(ifstream& mesh_file, size_t& number_of_points, string& text_line) - { - - while (getline(mesh_file, text_line)) - - { - text_line.erase(0, 1); - if (atoi(text_line.c_str()) == 10 && text_line.find("))", 0) != string::npos) - { - string text1(text_line); - text1.erase(0, 8); - Real last_position = text1.find_last_of(")"); - text1.erase(last_position - 3); - number_of_points = stoi(text1, nullptr, 16); - break; - } - } - } - - void MeshFileHelpers::numberofElementsFluent(ifstream& mesh_file, size_t& number_of_elements, string& text_line) - { - - while (getline(mesh_file, text_line)) - { - text_line.erase(0, 1); - string text1(text_line); - text_line.erase(3); - string text2(text_line); - text_line.erase(2); - if (atoi(text_line.c_str()) == 12) - { - text1.erase(0, 8); - Real last_position = text1.find_last_of(")"); - text1.erase(last_position - 3); - number_of_elements = stoi(text1, nullptr, 16); - break; - } - } - } - - void MeshFileHelpers::nodeCoordinatesFluent(ifstream& mesh_file, StdLargeVec& node_coordinates_, string& text_line, - size_t& dimension) - { - while (getline(mesh_file, text_line)) - { - text_line.erase(0, 1); - if (atoi(text_line.c_str()) == 10 && text_line.find(") (", 0) != string::npos) - { - while (getline(mesh_file, text_line)) - { - if (text_line.find("(", 0) == string::npos && text_line.find("))", 0) == string::npos && text_line.find(" ", 0) != string::npos) - { - if (dimension == 3) - { - size_t first_devide_position = text_line.find_first_of(" "); - size_t last_devide_position = text_line.find_last_of(" "); - string x_part = text_line; - string y_part = text_line; - string z_part = text_line; - string x_coordinate_string = x_part.erase(first_devide_position); - string y_coordinate_string = y_part.erase(last_devide_position); - y_coordinate_string = y_coordinate_string.erase(0, first_devide_position); - string z_coordinate_string = z_part.erase(0, last_devide_position); - Vecd Coords = Vecd::Zero(); - istringstream streamx, streamy, streamz; - streamx.str(x_coordinate_string); - streamy.str(y_coordinate_string); - streamz.str(z_coordinate_string); - streamx >> Coords[0]; - streamy >> Coords[1]; - streamz >> Coords[2]; - node_coordinates_.push_back(Coords); - } - } - text_line.erase(0, 1); - if (atoi(text_line.c_str()) == 11 || atoi(text_line.c_str()) == 13 || atoi(text_line.c_str()) == 12) - { - break; - } - } - - } - - if ((atoi(text_line.c_str()) == 11 && text_line.find(") (") != string::npos) || (atoi(text_line.c_str()) == 13 && text_line.find(") (") != string::npos) || (atoi(text_line.c_str()) == 12 && text_line.find(") (") != string::npos)) - break; - } - } - - void MeshFileHelpers::updateBoundaryCellListsFluent(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - Vecd nodes, Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type) - { - - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][1][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][1][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][1][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][1][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][1][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) - { - mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; - mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; - mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; - mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; - mesh_topology_[cells[check_neighbor_cell2]][2][4] = nodes[2]; - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - else - { - check_neighbor_cell1 = false; - check_neighbor_cell2 = true; - return; - } - } -} \ No newline at end of file diff --git a/src/for_3D_build/bodies/mesh_helper_3d.cpp b/src/for_3D_build/bodies/mesh_helper_3d.cpp new file mode 100644 index 0000000000..fa5506765b --- /dev/null +++ b/src/for_3D_build/bodies/mesh_helper_3d.cpp @@ -0,0 +1,631 @@ +#include "mesh_helper.h" +#include "unstructured_mesh.h" + +#include "base_particle_dynamics.h" +namespace SPH +{ + +void MeshFileHelpers::meshDimension(std::ifstream &mesh_file, size_t &dimension, std::string &text_line) +{ + while (getline(mesh_file, text_line)) + { + (getline(mesh_file, text_line)); + text_line.erase(0, 1); + text_line.erase(0, 2); + std::istringstream value(text_line); + if (text_line.find("3", 0) != std::string::npos) + { + dimension = atoi(text_line.c_str()); + break; + } + } +} + +void MeshFileHelpers::numberOfNodes(std::ifstream &mesh_file, size_t &number_of_points, std::string &text_line) +{ + while (getline(mesh_file, text_line)) + { + text_line.erase(0, 1); + std::string text1(text_line); + text_line.erase(3); + std::string text2(text_line); + text_line.erase(2); + if (atoi(text_line.c_str()) == 10 && text1.find("))", 0) != std::string::npos) + { + text1.erase(0, 8); + Real last_position = text1.find_last_of(")"); + text1.erase(last_position - 5); + number_of_points = stoi(text1, nullptr, 16); + break; + } + } +} + +void MeshFileHelpers::nodeCoordinates(std::ifstream &mesh_file, StdLargeVec &node_coordinates_, std::string &text_line, size_t &dimension) +{ + while (getline(mesh_file, text_line)) + { + if (text_line.find("(", 0) == std::string::npos && text_line.find("))", 0) == std::string::npos) + { + if (text_line.find(" ", 0) != std::string::npos) + { + if (dimension == 3) + { + size_t first_devide_position = text_line.find_first_of(" "); + size_t last_devide_position = text_line.find_last_of(" "); + std::string x_part = text_line; + std::string y_part = text_line; + std::string z_part = text_line; + std::string x_coordinate_string = x_part.erase(first_devide_position); + std::string y_coordinate_string = y_part.erase(last_devide_position); + y_coordinate_string = y_coordinate_string.erase(0, first_devide_position); + std::string z_coordinate_string = z_part.erase(0, last_devide_position); + std::istringstream streamx, streamy, streamz; + Vecd Coords = Vecd::Zero(); + streamx.str(x_coordinate_string); + streamy.str(y_coordinate_string); + streamz.str(z_coordinate_string); + streamx >> Coords[0]; + streamy >> Coords[1]; + streamz >> Coords[2]; + + node_coordinates_.push_back(Coords); + } + } + } + if (text_line.find("))", 0) != std::string::npos) + { + break; + } + } +} + +void MeshFileHelpers::numberOfElements(std::ifstream &mesh_file, size_t &number_of_elements, std::string &text_line) +{ + + while (getline(mesh_file, text_line)) + { + text_line.erase(0, 1); + std::string text1(text_line); + text_line.erase(3); + std::string text2(text_line); + text_line.erase(2); + if (atoi(text_line.c_str()) == 12) + { + text1.erase(0, 8); + Real last_position = text1.find_last_of(")"); + text1.erase(last_position - 5); + number_of_elements = stoi(text1, nullptr, 16); + break; + } + } +} + +void MeshFileHelpers::dataStruct(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, + size_t number_of_elements, size_t mesh_type, size_t dimension) +{ + + mesh_topology_.resize(number_of_elements + 1); + for (std::size_t a = 0; a != number_of_elements + 1; ++a) + { + mesh_topology_[a].resize(mesh_type); + for (std::vector>::size_type b = 0; b != mesh_topology_[a].size(); ++b) + { + mesh_topology_[a][b].resize(dimension + 2); + for (std::vector::size_type c = 0; c != mesh_topology_[a][b].size(); ++c) + { + mesh_topology_[a][b][c] = -1; + } + } + } + /*--- reinitialize the number of elements ---*/ + elements_nodes_connection_.resize(number_of_elements + 1); + mesh_topology_.resize(number_of_elements + 1); + for (std::size_t element = 0; element != number_of_elements + 1; ++element) + { + elements_nodes_connection_[element].resize(4); + for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) + { + elements_nodes_connection_[element][node] = -1; + } + } +} + +size_t MeshFileHelpers::findBoundaryType(std::string &text_line, size_t boundary_type) +{ + /*--- Read the elements of the problem (13 (id f1 f2 type 0) (---*/ + /** differnet boundary conditions + * bc-type==2, interior boundary condition. + * bc-type==3, wall boundary condition. + * bc-type==4, Pressure Inlet boundary condition + * bc-type==5, Pressure Outlet boundary condition + * bc-type==7, Symmetry boundary condition + * bc-type==9, pressure-far-field boundary condition. + * bc-type==a, Velocity Inlet boundary condition. + * bc-type==c, Periodic boundary condition. + * bc-type==e, porous jumps boundary condition. + * bc-type==14,Mass Flow Inlet boundary condition. + * Note that Cell0 means boundary condition. + * mesh_type==4, unstructured mesh. + * mesh_type==6, structured mesh. + * cell_lists_ + * {[(neighbor_cell_index, bc_type, node1_of_face, node2_of_face, node3_of_face), (....), (.....)], []..... }. + * {inner_neighbor1, inner_neighbor2,inner_neighbor3, inner_neighbor4 ..... }. + */ + /*--- find the type of boundary condition ---*/ + size_t position = text_line.find(")", 0); + text_line = text_line.erase(0, position - 4); + text_line = text_line.erase(2); + boundary_type = stoi(text_line, nullptr, 16); + return boundary_type; +} + +Vecd MeshFileHelpers::nodeIndex(std::string &text_line) + +{ + /*--- find the node1 between two cells ---*/ + std::string node1_string_copy = text_line; + size_t first_devide_position = text_line.find_first_of(" ", 0); + std::string node1_index_string = node1_string_copy.erase(first_devide_position); + size_t node1_index_decimal = stoi(node1_index_string, nullptr, 16) - 1; + + /*--- find the node2 between two cells---*/ + std::string node2_string = text_line; + std::string node3_string = text_line; + node2_string = node2_string.erase(0, first_devide_position + 1); + node3_string = node2_string; + size_t second_devide_position = node2_string.find_first_of(" ", 0); + node2_string.erase(second_devide_position); + size_t node2_index_decimal = stoi(node2_string, nullptr, 16) - 1; + + /*--- find the node3 between two cells---*/ + node3_string = node3_string.erase(0, second_devide_position + 1); + size_t third_devide_position = node3_string.find_first_of(" ", 0); + node3_string.erase(third_devide_position); + size_t node3_index_decimal = stoi(node3_string, nullptr, 16) - 1; + + Vecd nodes = Vecd(node1_index_decimal, node2_index_decimal, node3_index_decimal); + return nodes; +} + +Vec2d MeshFileHelpers::cellIndex(std::string &text_line) +{ + + /*--- find the cell1---*/ + std::string cell1_string = text_line; + std::string cell2_string = text_line; + std::string cell3_string = text_line; + size_t first_devide_position = text_line.find_first_of(" ", 0); + cell1_string = cell1_string.erase(0, first_devide_position + 1); + size_t second_devide_position = cell1_string.find_first_of(" ", 0); + cell2_string = cell1_string.erase(0, second_devide_position + 1); + size_t third_devide_position = cell2_string.find_first_of(" ", 0); + cell3_string = cell2_string.erase(0, third_devide_position + 1); + size_t fourth_devide_position = cell3_string.find_first_of(" ", 0); + cell3_string.erase(fourth_devide_position); + size_t cell1_index_decimal = stoi(cell3_string, nullptr, 16); + + /*--- find the cell2---*/ + std::string cell4_string = text_line; + cell4_string = cell4_string.erase(0, first_devide_position + 1); + cell4_string = cell4_string.erase(0, second_devide_position + 1); + cell4_string = cell4_string.erase(0, third_devide_position + 1); + cell4_string.erase(0, fourth_devide_position + 1); + size_t cell2_index_decimal = stoi(cell4_string, nullptr, 16); + Vec2d cells = Vec2d(cell1_index_decimal, cell2_index_decimal); + return cells; +} + +void MeshFileHelpers::updateElementsNodesConnection(StdLargeVec> &elements_nodes_connection_, Vecd nodes, Vec2d cells, + bool &check_neighbor_cell1, bool &check_neighbor_cell2) +{ + + /*--- build up connection with element and nodes only---*/ + for (int node = 0; node != nodes.size(); ++node) + { + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][1] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][2] != nodes[node] && elements_nodes_connection_[cells[check_neighbor_cell2]][3] != nodes[node]) + { + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && (elements_nodes_connection_[cells[check_neighbor_cell2]][1] != static_cast>(-1)) && elements_nodes_connection_[cells[check_neighbor_cell2]][2] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][3] == static_cast>(-1)) + { + elements_nodes_connection_[cells[check_neighbor_cell2]][3] = nodes[node]; + } + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][1] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][2] == static_cast>(-1)) + { + elements_nodes_connection_[cells[check_neighbor_cell2]][2] = nodes[node]; + } + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] != static_cast>(-1) && elements_nodes_connection_[cells[check_neighbor_cell2]][1] == static_cast>(-1)) + { + elements_nodes_connection_[cells[check_neighbor_cell2]][1] = nodes[node]; + } + if (elements_nodes_connection_[cells[check_neighbor_cell2]][0] == static_cast>(-1)) + { + elements_nodes_connection_[cells[check_neighbor_cell2]][0] = nodes[node]; + } + } + else + continue; + } +} + +void MeshFileHelpers::updateCellLists(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, Vecd nodes, + Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type) +{ + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][1][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][2][0] != cells[check_neighbor_cell1] && mesh_topology_[cells[check_neighbor_cell2]][3][0] != cells[check_neighbor_cell1]) + { + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(-1)) + { + /*--- inner neighbor index---*/ + mesh_topology_[cells[check_neighbor_cell2]][0][0] = cells[check_neighbor_cell1]; + /*--- boundary type---*/ + mesh_topology_[cells[check_neighbor_cell2]][0][1] = boundary_type; + /*--- nodes of a face---*/ + mesh_topology_[cells[check_neighbor_cell2]][0][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][0][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][0][4] = nodes[2]; + + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][1][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][1][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][1][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][1][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][1][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][2][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][3][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][3][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][3][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][3][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][3][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + } +} + +void MeshFileHelpers::updateBoundaryCellLists(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, + Vecd nodes, Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type) +{ + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][2][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][3][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][3][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][3][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][3][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][3][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][1][0] != static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][3][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][3][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][3][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][3][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][3][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + else + { + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } +} + +void MeshFileHelpers::cellCenterCoordinates(StdLargeVec> &elements_nodes_connection_, std::size_t &element, + StdLargeVec &node_coordinates_, StdLargeVec &elements_centroids_, Vecd ¢er_coordinate) +{ + + for (std::size_t node = 0; node != elements_nodes_connection_[element].size(); ++node) + { + center_coordinate += node_coordinates_[elements_nodes_connection_[element][node]] / 4.0; + } + elements_centroids_[element] = center_coordinate; +} + +void MeshFileHelpers::elementVolume(StdLargeVec> &elements_nodes_connection_, std::size_t &element, + StdLargeVec &node_coordinates_, StdLargeVec &elements_volumes_) +{ + // get nodes position + Real Total_volume = 0; + using Vec4d = Eigen::Matrix; + Vec4d nodes = Vec4d(elements_nodes_connection_[element][0], elements_nodes_connection_[element][1], elements_nodes_connection_[element][2], elements_nodes_connection_[element][3]); + Vecd node1_coordinate = Vecd(node_coordinates_[nodes[0]][0], node_coordinates_[nodes[0]][1], node_coordinates_[nodes[0]][2]); + Vecd node2_coordinate = Vecd(node_coordinates_[nodes[1]][0], node_coordinates_[nodes[1]][1], node_coordinates_[nodes[1]][2]); + Vecd node3_coordinate = Vecd(node_coordinates_[nodes[2]][0], node_coordinates_[nodes[2]][1], node_coordinates_[nodes[2]][2]); + Vecd node4_coordinate = Vecd(node_coordinates_[nodes[3]][0], node_coordinates_[nodes[3]][1], node_coordinates_[nodes[3]][2]); + Matd M; + M << node2_coordinate - node1_coordinate, node3_coordinate - node1_coordinate, node4_coordinate - node1_coordinate; + Real determinant = abs(M.determinant()); + Real element_volume = (static_cast(1) / 6) * determinant; + Total_volume += element_volume; + elements_volumes_[element] = element_volume; +} + +void MeshFileHelpers::minimumDistance(StdVec &all_data_of_distance_between_nodes, StdLargeVec &elements_volumes_, StdVec>> &mesh_topology_, + StdLargeVec &node_coordinates_) +{ + + for (size_t element_index = 0; element_index != elements_volumes_.size(); ++element_index) + { + + for (std::size_t neighbor = 0; neighbor != mesh_topology_[element_index].size(); ++neighbor) + { + + size_t interface_node1_index = mesh_topology_[element_index][neighbor][2]; + size_t interface_node2_index = mesh_topology_[element_index][neighbor][3]; + size_t interface_node3_index = mesh_topology_[element_index][neighbor][4]; + Vecd node1_position = node_coordinates_[interface_node1_index]; + Vecd node2_position = node_coordinates_[interface_node2_index]; + Vecd node3_position = node_coordinates_[interface_node3_index]; + Vecd interface_area_vector1 = node2_position - node1_position; + Vecd interface_area_vector2 = node3_position - node1_position; + Vecd area_vector = interface_area_vector1.cross(interface_area_vector2); + Real triangle_area = 0.5 * area_vector.norm(); + Real distance = sqrt(triangle_area); + all_data_of_distance_between_nodes.push_back(distance); + } + } +} + +void MeshFileHelpers::vtuFileHeader(std::ofstream &out_file) +{ + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "0\n"; + out_file << "\n"; + out_file << "\n"; +} + +void MeshFileHelpers::vtuFileNodeCoordinates(std::ofstream &out_file, StdLargeVec &node_coordinates_, + StdLargeVec> &elements_nodes_connection_, SPHBody &bounds_, Real &rangemax) +{ + // Write point data + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + BoundingBox bounds = bounds_.getSPHSystemBounds(); + Real first_max = bounds.first_.cwiseAbs().maxCoeff(); + Real second_max = bounds.second_.cwiseAbs().maxCoeff(); + rangemax = 1.03075 * (std::max(first_max, second_max)); + out_file << "\n"; + + size_t total_nodes = node_coordinates_.size(); + for (size_t node = 0; node != total_nodes; ++node) + { + out_file << node_coordinates_[node][0] << " " << node_coordinates_[node][1] << " " << node_coordinates_[node][2] << " \n"; + } +} + +void MeshFileHelpers::vtuFileInformationKey(std::ofstream &out_file, Real &rangemax) +{ + out_file << "\n"; + out_file << "\n"; + out_file << "0\n"; + out_file << "\n"; + out_file << "\n"; + out_file << rangemax << " \n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "0\n"; + out_file << "\n"; + out_file << "\n"; + out_file << rangemax << " \n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; +} + +void MeshFileHelpers::vtuFileCellConnectivity(std::ofstream &out_file, StdLargeVec> &elements_nodes_connection_, StdLargeVec &node_coordinates_) +{ + out_file << "\n"; + // Write Cell data + out_file << "\n"; + + for (const auto &cell : elements_nodes_connection_) + { + for (const auto &vertex : cell) + { + out_file << vertex << " "; + } + out_file << "\n"; + } + + out_file << "\n"; +} + +void MeshFileHelpers::vtuFileOffsets(std::ofstream &out_file, StdLargeVec> &elements_nodes_connection_) +{ + out_file << "\n"; + + size_t offset = 0; + for (const auto &face : elements_nodes_connection_) + { + offset += face.size(); + out_file << offset << " "; + } + out_file << "\n\n"; +} + +void MeshFileHelpers::vtuFileTypeOfCell(std::ofstream &out_file, StdLargeVec> &elements_nodes_connection_) +{ + size_t type = 10; + // Specifies type of cell 10 = tetrahedral + out_file << "\n"; + for (const auto &types : elements_nodes_connection_) + { + for (size_t i = 0; i < types.size(); ++i) + { + out_file << type << " "; + } + out_file << "\n"; + } + // Write face attribute data + out_file << "\n"; + out_file << "\n"; +} + +void MeshFileHelpers::numberOfNodesFluent(std::ifstream &mesh_file, size_t &number_of_points, std::string &text_line) +{ + + while (getline(mesh_file, text_line)) + + { + text_line.erase(0, 1); + if (atoi(text_line.c_str()) == 10 && text_line.find("))", 0) != std::string::npos) + { + std::string text1(text_line); + text1.erase(0, 8); + Real last_position = text1.find_last_of(")"); + text1.erase(last_position - 3); + number_of_points = stoi(text1, nullptr, 16); + break; + } + } +} + +void MeshFileHelpers::numberOfElementsFluent(std::ifstream &mesh_file, size_t &number_of_elements, std::string &text_line) +{ + + while (getline(mesh_file, text_line)) + { + text_line.erase(0, 1); + std::string text1(text_line); + text_line.erase(3); + std::string text2(text_line); + text_line.erase(2); + if (atoi(text_line.c_str()) == 12) + { + text1.erase(0, 8); + Real last_position = text1.find_last_of(")"); + text1.erase(last_position - 3); + number_of_elements = stoi(text1, nullptr, 16); + break; + } + } +} + +void MeshFileHelpers::nodeCoordinatesFluent(std::ifstream &mesh_file, StdLargeVec &node_coordinates_, std::string &text_line, + size_t &dimension) +{ + while (getline(mesh_file, text_line)) + { + text_line.erase(0, 1); + if (atoi(text_line.c_str()) == 10 && text_line.find(") (", 0) != std::string::npos) + { + while (getline(mesh_file, text_line)) + { + if (text_line.find("(", 0) == std::string::npos && text_line.find("))", 0) == std::string::npos && text_line.find(" ", 0) != std::string::npos) + { + if (dimension == 3) + { + size_t first_devide_position = text_line.find_first_of(" "); + size_t last_devide_position = text_line.find_last_of(" "); + std::string x_part = text_line; + std::string y_part = text_line; + std::string z_part = text_line; + std::string x_coordinate_string = x_part.erase(first_devide_position); + std::string y_coordinate_string = y_part.erase(last_devide_position); + y_coordinate_string = y_coordinate_string.erase(0, first_devide_position); + std::string z_coordinate_string = z_part.erase(0, last_devide_position); + Vecd Coords = Vecd::Zero(); + std::istringstream streamx, streamy, streamz; + streamx.str(x_coordinate_string); + streamy.str(y_coordinate_string); + streamz.str(z_coordinate_string); + streamx >> Coords[0]; + streamy >> Coords[1]; + streamz >> Coords[2]; + node_coordinates_.push_back(Coords); + } + } + text_line.erase(0, 1); + if (atoi(text_line.c_str()) == 11 || atoi(text_line.c_str()) == 13 || atoi(text_line.c_str()) == 12) + { + break; + } + } + } + + if ((atoi(text_line.c_str()) == 11 && text_line.find(") (") != std::string::npos) || (atoi(text_line.c_str()) == 13 && text_line.find(") (") != std::string::npos) || (atoi(text_line.c_str()) == 12 && text_line.find(") (") != std::string::npos)) + break; + } +} + +void MeshFileHelpers::updateBoundaryCellListsFluent(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, + Vecd nodes, Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type) +{ + + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][1][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][1][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][1][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][1][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][1][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + if (mesh_topology_[cells[check_neighbor_cell2]][0][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][1][0] == static_cast>(0) && mesh_topology_[cells[check_neighbor_cell2]][2][0] == static_cast>(-1) && mesh_topology_[cells[check_neighbor_cell2]][3][0] == static_cast>(-1)) + { + mesh_topology_[cells[check_neighbor_cell2]][2][0] = cells[check_neighbor_cell1]; + mesh_topology_[cells[check_neighbor_cell2]][2][1] = boundary_type; + mesh_topology_[cells[check_neighbor_cell2]][2][2] = nodes[0]; + mesh_topology_[cells[check_neighbor_cell2]][2][3] = nodes[1]; + mesh_topology_[cells[check_neighbor_cell2]][2][4] = nodes[2]; + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } + else + { + check_neighbor_cell1 = false; + check_neighbor_cell2 = true; + return; + } +} +} // namespace SPH \ No newline at end of file diff --git a/src/for_3D_build/bodies/solid_body_supplementary.cpp b/src/for_3D_build/bodies/solid_body_3d.cpp similarity index 84% rename from src/for_3D_build/bodies/solid_body_supplementary.cpp rename to src/for_3D_build/bodies/solid_body_3d.cpp index 7380a898c1..169a991083 100644 --- a/src/for_3D_build/bodies/solid_body_supplementary.cpp +++ b/src/for_3D_build/bodies/solid_body_3d.cpp @@ -1,6 +1,6 @@ #include "solid_body.h" -#include "solid_particles.h" +#include "base_particles.hpp" namespace SPH { //=================================================================================================// @@ -11,8 +11,8 @@ void SolidBodyPartForSimbody::setMassProperties() for (size_t i = 0; i < body_part_particles_.size(); ++i) { size_t index_i = body_part_particles_[i]; - Vecd particle_position = solid_particles_->pos0_[index_i]; - Real particle_volume = solid_particles_->Vol_[index_i]; + Vecd particle_position = pos_[index_i]; + Real particle_volume = Vol_[index_i]; initial_mass_center_ += particle_volume * particle_position; body_part_volume += particle_volume; @@ -26,8 +26,8 @@ void SolidBodyPartForSimbody::setMassProperties() for (size_t i = 0; i < body_part_particles_.size(); ++i) { size_t index_i = body_part_particles_[i]; - Vecd particle_position = solid_particles_->pos0_[index_i]; - Real particle_volume = solid_particles_->Vol_[index_i]; + Vecd particle_position = pos_[index_i]; + Real particle_volume = Vol_[index_i]; Vec3d displacement = particle_position - initial_mass_center_; @@ -42,7 +42,7 @@ void SolidBodyPartForSimbody::setMassProperties() inertia_products /= body_part_volume; body_part_mass_properties_ = mass_properties_ptr_keeper_.createPtr( - body_part_volume * solid_body_density_, SimTKVec3(0), + body_part_volume * rho0_, SimTKVec3(0), SimTK::UnitInertia(SimTKVec3(inertia_moments[0], inertia_moments[1], inertia_moments[2]), SimTKVec3(inertia_products[0], inertia_products[1], inertia_products[2]))); } diff --git a/src/for_3D_build/bodies/unstructured_mesh.cpp b/src/for_3D_build/bodies/unstructured_mesh.cpp deleted file mode 100644 index e2bf5cab48..0000000000 --- a/src/for_3D_build/bodies/unstructured_mesh.cpp +++ /dev/null @@ -1,507 +0,0 @@ - -#include "unstructured_mesh.h" -#include "mesh_helper.h" -namespace SPH -{ - //=================================================================================================// - ANSYSMesh::ANSYSMesh(const std::string &full_path) - { - getDataFromMeshFile(full_path); - getElementCenterCoordinates(); - getMinimumDistanceBetweenNodes(); - } -//=== - //=================================================================================================// - void ANSYSMesh::getDataFromMeshFile(const std::string &full_path) - { - Real ICEM = 0; - ifstream mesh_file; /*!< \brief File object for the Ansys ASCII mesh file. */ - mesh_file.open(full_path); - if (mesh_file.fail()) - { - cout << "Error:Check if the file exists." << endl; - } - string text_line; - /*Check mesh file generation software*/ - (getline(mesh_file, text_line)); - text_line.erase(0, 4); - istringstream value(text_line); - if (text_line.find("Created by", 0) != string::npos) - { - ICEM = 1; - cout << "Reading 3D ICEM mesh." << endl; - } - - if (ICEM == 1) - { - - /*--- Read the dimension of the mesh ---*/ - size_t dimension(0); - MeshFileHelpers::meshDimension(mesh_file, dimension, text_line); - - /*--- Read the node data (index is starting from zero) ---*/ - size_t number_of_points(0); - MeshFileHelpers::numberofNodes(mesh_file, number_of_points, text_line); - MeshFileHelpers::nodeCoordinates(mesh_file, node_coordinates_, text_line, dimension); - - size_t boundary_type(0); - size_t number_of_elements(0); - size_t mesh_type = 4; - MeshFileHelpers::numberofElements(mesh_file, number_of_elements, text_line); - - /*Preparing and initializing the data structure of mesh topology and element node connection*/ - MeshFileHelpers::dataStruct(mesh_topology_, elements_nodes_connection_, number_of_elements, mesh_type, dimension); - - /*--- find the elements lines ---*/ - while (getline(mesh_file, text_line)) - { - if (text_line.find("(13", 0) != string::npos && text_line.find(")(", 0) != string::npos) - { - boundary_type = MeshFileHelpers::findBoundaryType(text_line, boundary_type); - types_of_boundary_condition_.push_back(boundary_type); - while (getline(mesh_file, text_line)) - { - if (text_line.find(")", 0) == string::npos) - { - Vecd nodes = MeshFileHelpers::nodeIndex(text_line); - Vec2d cells = MeshFileHelpers::cellIndex(text_line); - - /*--- build up all topology---*/ - bool check_neighbor_cell1 = 1; - bool check_neighbor_cell2 = 0; - for (int cell1_cell2 = 0; cell1_cell2 != cells.size(); ++cell1_cell2) - { - if (mesh_type == 4) - { - if (cells[check_neighbor_cell2] != 0) - { - MeshFileHelpers::updateElementsNodesConnection(elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2); - MeshFileHelpers::updateCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); - MeshFileHelpers::updateBoundaryCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); - } - if (cells[check_neighbor_cell2] == 0) - { - break; - } - } - } - } - else - break; - } - } - if (text_line.find("Zone Sections", 0) != string::npos) - break; - if (text_line.find(")") != string::npos) - continue; - } - mesh_topology_.erase(mesh_topology_.begin()); - } - else /*This section is for mesh files created from fluent*/ - { - cout << "Reading 3D Fluent mesh." << endl; - size_t dimension(0); - MeshFileHelpers::meshDimension(mesh_file, dimension, text_line); - - /*--- Read the node data (index is starting from zero) ---*/ - size_t number_of_points(0); - MeshFileHelpers::numberofNodesFluent(mesh_file, number_of_points, text_line); - - size_t boundary_type(0); - size_t number_of_elements(0); - size_t mesh_type = 4; - - MeshFileHelpers::numberofElementsFluent(mesh_file, number_of_elements, text_line); - MeshFileHelpers::dataStruct(mesh_topology_, elements_nodes_connection_, number_of_elements, mesh_type, dimension); - MeshFileHelpers::nodeCoordinatesFluent( mesh_file, node_coordinates_, text_line, dimension); - - while (getline(mesh_file, text_line)) - { - - if (text_line.find("(13", 0) != string::npos && text_line.find(") (", 0) != string::npos) - { - boundary_type = MeshFileHelpers::findBoundaryType(text_line, boundary_type); - types_of_boundary_condition_.push_back(boundary_type); - while (getline(mesh_file, text_line)) - { - - if (text_line.find(")", 0) == string::npos) - { - Vecd nodes = MeshFileHelpers::nodeIndex(text_line); - Vec2d cells = MeshFileHelpers::cellIndex(text_line); - /*--- build up all topology---*/ - bool check_neighbor_cell1 = 1; - bool check_neighbor_cell2 = 0; - for (int cell1_cell2 = 0; cell1_cell2 != cells.size(); ++cell1_cell2) - { - if (mesh_type == 4) - { - if (cells[check_neighbor_cell2] != 0) - { - MeshFileHelpers::updateElementsNodesConnection(elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2); - MeshFileHelpers::updateCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, - check_neighbor_cell2, boundary_type); - MeshFileHelpers::updateBoundaryCellListsFluent(mesh_topology_, elements_nodes_connection_, nodes, cells, - check_neighbor_cell1, check_neighbor_cell2, boundary_type); - } - if (cells[check_neighbor_cell2] == 0) - { - break; - } - } - } - - - } - else - break; - - } - - } - if (text_line.find("(12", 0) != string::npos && text_line.find("))", 0) != string::npos) - break; - if (text_line.find(")") != string::npos) - continue; - } - mesh_topology_.erase(mesh_topology_.begin()); - - } - - } - //=================================================================================================// - - void ANSYSMesh::getElementCenterCoordinates() - { - elements_centroids_.resize(elements_nodes_connection_.size()); - elements_volumes_.resize(elements_nodes_connection_.size()); - for (std::size_t element = 1; element != elements_nodes_connection_.size(); ++element) - { - Vecd center_coordinate = Vecd::Zero(); - MeshFileHelpers::cellCenterCoordinates(elements_nodes_connection_, element, node_coordinates_, elements_centroids_, center_coordinate); - MeshFileHelpers::elementVolume(elements_nodes_connection_, element, node_coordinates_, elements_volumes_); - } - elements_volumes_.erase(elements_volumes_.begin()); - elements_centroids_.erase(elements_centroids_.begin()); - elements_nodes_connection_.erase(elements_nodes_connection_.begin()); - } - //=================================================================================================// - - void ANSYSMesh::getMinimumDistanceBetweenNodes() - { - vector all_data_of_distance_between_nodes; - all_data_of_distance_between_nodes.resize(0); - MeshFileHelpers::minimumdistance(all_data_of_distance_between_nodes, elements_volumes_, mesh_topology_, node_coordinates_); - auto min_distance_iter = std::min_element(all_data_of_distance_between_nodes.begin(), all_data_of_distance_between_nodes.end()); - if (min_distance_iter != all_data_of_distance_between_nodes.end()) - { - min_distance_between_nodes_ = *min_distance_iter; - } - else - { - cout << "The array of all distance between nodes is empty " << endl; - } - } - //=================================================================================================// - BaseInnerRelationInFVM::BaseInnerRelationInFVM(RealBody& real_body, ANSYSMesh& ansys_mesh) - : BaseInnerRelation(real_body), real_body_(&real_body), node_coordinates_(ansys_mesh.node_coordinates_), - mesh_topology_(ansys_mesh.mesh_topology_) - { - subscribeToBody(); - inner_configuration_.resize(base_particles_.real_particles_bound_, Neighborhood()); - }; - //=================================================================================================// - void BaseInnerRelationInFVM::resetNeighborhoodCurrentSize() - { - parallel_for( - IndexRange(0, base_particles_.total_real_particles_), - [&](const IndexRange &r) - { - for (size_t num = r.begin(); num != r.end(); ++num) - { - inner_configuration_[num].current_size_ = 0; - } - }, - ap); - } - //=================================================================================================// - void NeighborBuilderInFVM::createRelation(Neighborhood &neighborhood, Real &distance, - Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const - { - neighborhood.j_.push_back(j_index); - neighborhood.r_ij_.push_back(distance); - neighborhood.e_ij_.push_back(interface_normal_direction); - neighborhood.dW_ij_.push_back(dW_ij); - neighborhood.allocated_size_++; - } - //=================================================================================================// - void NeighborBuilderInFVM::initializeRelation(Neighborhood &neighborhood, Real &distance, - Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const - { - size_t current_size = neighborhood.current_size_; - neighborhood.j_[current_size] = j_index; - neighborhood.dW_ij_[current_size] = dW_ij; - neighborhood.r_ij_[current_size] = distance; - neighborhood.e_ij_[current_size] = interface_normal_direction; - } - - //=================================================================================================// - InnerRelationInFVM::InnerRelationInFVM(RealBody &real_body, ANSYSMesh& ansys_mesh) - : BaseInnerRelationInFVM(real_body, ansys_mesh), get_inner_neighbor_(&real_body){}; - //=================================================================================================// - template - void InnerRelationInFVM::searchNeighborsByParticles(size_t total_particles, BaseParticles &source_particles, - ParticleConfiguration &particle_configuration, GetParticleIndex &get_particle_index, GetNeighborRelation &get_neighbor_relation) - { - parallel_for( - IndexRange(0, base_particles_.total_real_particles_), - [&](const IndexRange &r) - { - StdLargeVec &pos_n = source_particles.pos_; - StdLargeVec &Vol_n = source_particles.Vol_; - for (size_t num = r.begin(); num != r.end(); ++num) - { - size_t index_i = get_particle_index(num); - Vecd &particle_position = pos_n[index_i]; - Real &Vol_i = Vol_n[index_i]; - - Neighborhood &neighborhood = particle_configuration[index_i]; - for (std::vector>::size_type neighbor = 0; neighbor != mesh_topology_[index_i].size(); ++neighbor) - { - size_t index_j = mesh_topology_[index_i][neighbor][0] - 1; - size_t boundary_type = mesh_topology_[index_i][neighbor][1]; - size_t interface_node1_index = mesh_topology_[index_i][neighbor][2]; - size_t interface_node2_index = mesh_topology_[index_i][neighbor][3]; - size_t interface_node3_index = mesh_topology_[index_i][neighbor][4]; - Vecd node1_position = Vecd(node_coordinates_[interface_node1_index][0], node_coordinates_[interface_node1_index][1], node_coordinates_[interface_node1_index][2]); - Vecd node2_position = Vecd(node_coordinates_[interface_node2_index][0], node_coordinates_[interface_node2_index][1], node_coordinates_[interface_node2_index][2]); - Vecd node3_position = Vecd(node_coordinates_[interface_node3_index][0], node_coordinates_[interface_node3_index][1], node_coordinates_[interface_node3_index][2]); - Vecd interface_area_vector1 = node1_position - node2_position; - Vecd interface_area_vector2 = node1_position - node3_position; - Vecd normal_vector = interface_area_vector1.cross(interface_area_vector2); - Real magnitude = normal_vector.norm(); - Vecd normalized_normal_vector = normal_vector / magnitude; - Vecd node1_to_center_direction = particle_position - node1_position; - if (node1_to_center_direction.dot(normalized_normal_vector) < 0) - { - normalized_normal_vector = -normalized_normal_vector; - }; - Real r_ij = 0; // we need r_ij to calculate the viscous force - // boundary_type == 2 means both of them are inside of fluid - if (boundary_type == 2) - { - r_ij = (particle_position - pos_n[index_j]).dot(normalized_normal_vector); - } - // this refer to the different types of wall boundary condtions - if ((boundary_type == 3) | (boundary_type == 4) | (boundary_type == 5) | (boundary_type == 7) | (boundary_type == 9) | - (boundary_type == 10) | (boundary_type == 36)) - { - r_ij = node1_to_center_direction.dot(normalized_normal_vector) * 2.0; - } - Real dW_ij = (-0.5 * magnitude) / (2.0 * Vol_i * Vol_n[index_j]); - get_neighbor_relation(neighborhood, r_ij, dW_ij, normalized_normal_vector, index_j); - } - } - }, - ap); - } - //=================================================================================================// - void InnerRelationInFVM::updateConfiguration() - { - resetNeighborhoodCurrentSize(); - searchNeighborsByParticles(base_particles_.total_real_particles_, - base_particles_, inner_configuration_, - get_particle_index_, get_inner_neighbor_); - } - //=================================================================================================// - GhostCreationFromMesh::GhostCreationFromMesh(RealBody& real_body, ANSYSMesh& ansys_mesh, Ghost& ghost_boundary) - : GeneralDataDelegateSimple(real_body), - ghost_boundary_(ghost_boundary), - node_coordinates_(ansys_mesh.node_coordinates_), - mesh_topology_(ansys_mesh.mesh_topology_), - pos_(particles_->pos_), Vol_(particles_->Vol_), - ghost_bound_(ghost_boundary.GhostBound()) - { - ghost_boundary.checkParticlesReserved(); - each_boundary_type_with_all_ghosts_index_.resize(50); - each_boundary_type_with_all_ghosts_eij_.resize(50); - each_boundary_type_contact_real_index_.resize(50); - addGhostParticleAndSetInConfiguration(); - } - //=================================================================================================// - void GhostCreationFromMesh::addGhostParticleAndSetInConfiguration() - { - ghost_bound_.second = ghost_bound_.first; - - for (size_t index_i = 0; index_i != particles_->total_real_particles_; ++index_i) - { - for (size_t neighbor_index = 0; neighbor_index != mesh_topology_[index_i].size(); ++neighbor_index) - { - size_t boundary_type = mesh_topology_[index_i][neighbor_index][1]; - if (mesh_topology_[index_i][neighbor_index][1] != 2) - { - mutex_create_ghost_particle_.lock(); - size_t ghost_particle_index = ghost_bound_.second; - ghost_bound_.second++; - ghost_boundary_.checkWithinGhostSize(ghost_bound_); - - particles_->updateGhostParticle(ghost_particle_index, index_i); - size_t node1_index = mesh_topology_[index_i][neighbor_index][2]; - size_t node2_index = mesh_topology_[index_i][neighbor_index][3]; - size_t node3_index = mesh_topology_[index_i][neighbor_index][4]; - Vecd node1_position = node_coordinates_[node1_index]; - Vecd node2_position = node_coordinates_[node2_index]; - Vecd node3_position = node_coordinates_[node3_index]; - Vecd ghost_particle_position = (1.0 / 3.0) * (node1_position + node2_position + node3_position); - - mesh_topology_[index_i][neighbor_index][0] = ghost_particle_index + 1; - pos_[ghost_particle_index] = ghost_particle_position; - mutex_create_ghost_particle_.unlock(); - - mesh_topology_.resize(ghost_particle_index); - std::vector> new_element; - - // Add (corresponding_index_i,boundary_type,node1_index,node2_index, node3_index) to the new element - std::vector sub_element1 = { index_i + 1, boundary_type, node1_index, node2_index, node3_index }; - new_element.push_back(sub_element1); - - // Add (correspon ding_index_i,boundary_type,node1_index,node2_index, node3_index) to the new element - std::vector sub_element2 = { index_i + 1, boundary_type, node1_index, node2_index, node3_index }; - new_element.push_back(sub_element2); - - // Add (corresponding_index_i,boundary_type,node1_index,node2_index, node3_index) to the new element - std::vector sub_element3 = { index_i + 1, boundary_type, node1_index, node2_index, node3_index }; - new_element.push_back(sub_element3); - - // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element - std::vector sub_element4 = { index_i + 1, boundary_type, node1_index, node2_index, node3_index }; - new_element.push_back(sub_element4); - - // Add the new element to all_needed_data_from_mesh_file_ - mesh_topology_.push_back(new_element); - // all_needed_data_from_mesh_file_[ghost_particle_index][0][0].push_back(size_t(0); - - // creating the boundary files with ghost particle index - each_boundary_type_with_all_ghosts_index_[boundary_type].push_back(ghost_particle_index); - - // creating the boundary files with contact real particle index - each_boundary_type_contact_real_index_[boundary_type].push_back(index_i); - - // creating the boundary files with ghost eij - Vecd interface_area_vector1 = node2_position - node1_position; - Vecd interface_area_vector2 = node3_position - node1_position; - Vecd normal_vector = interface_area_vector1.cross(interface_area_vector2); - Real magnitude = normal_vector.norm(); - //Real interface_area_size = interface_area_vector.norm(); - Vecd normalized_normal_vector = normal_vector / magnitude; - // judge the direction - Vecd particle_position = pos_[index_i]; - Vecd node1_to_center_direction = particle_position - node1_position; - if (node1_to_center_direction.dot(normalized_normal_vector) < 0) - { - normalized_normal_vector = -normalized_normal_vector; - }; - each_boundary_type_with_all_ghosts_eij_[boundary_type].push_back(normalized_normal_vector); - } - } - } - }; - //=================================================================================================// - BodyStatesRecordingInMeshToVtu::BodyStatesRecordingInMeshToVtu(SPHBody& body, ANSYSMesh& ansys_mesh) - : BodyStatesRecording(body), node_coordinates_(ansys_mesh.node_coordinates_), - elements_nodes_connection_(ansys_mesh.elements_nodes_connection_), bounds_(body) {}; - //=================================================================================================// - void BodyStatesRecordingInMeshToVtu::writeWithFileName(const std::string & sequence) - { - for (SPHBody* body : bodies_) - { - if (body->checkNewlyUpdated() && state_recording_) - { - std::string filefullpath = io_environment_.output_folder_ + "/SPHBody_" + body->getName() + "_" + sequence + ".vtu"; - if (fs::exists(filefullpath)) - { - fs::remove(filefullpath); - } - std::ofstream out_file(filefullpath.c_str(), std::ios::trunc); - - MeshFileHelpers::vtuFileHeader(out_file); - Real rangemax = 0.0; - MeshFileHelpers::vtuFileNodeCoordinates(out_file, node_coordinates_, elements_nodes_connection_, bounds_, rangemax); - - MeshFileHelpers::vtuFileInformationKey(out_file, rangemax); - - MeshFileHelpers::vtuFileCellConnectivity(out_file, elements_nodes_connection_, node_coordinates_); - - MeshFileHelpers::vtuFileOffsets(out_file, elements_nodes_connection_); - - MeshFileHelpers::vtuFileTypeOfCell(out_file, elements_nodes_connection_); - - //write Particle data to vtu file - out_file << "\n"; - body->writeParticlesToVtuFile(out_file); - out_file << "\n"; - // Write VTU file footer - out_file << "\n"; - out_file << "\n"; - out_file << "\n"; - out_file.close(); - } - body->setNotNewlyUpdated(); - } - } - //=================================================================================================// - BoundaryConditionSetupInFVM::BoundaryConditionSetupInFVM(BaseInnerRelationInFVM& inner_relation, GhostCreationFromMesh& ghost_creation) - : fluid_dynamics::FluidDataInner(inner_relation), rho_(particles_->rho_), Vol_(particles_->Vol_), mass_(particles_->mass_), - p_(*particles_->getVariableByName("Pressure")), - vel_(particles_->vel_), pos_(particles_->pos_), mom_(*particles_->getVariableByName("Momentum")), - ghost_bound_(ghost_creation.ghost_bound_), - each_boundary_type_with_all_ghosts_index_(ghost_creation.each_boundary_type_with_all_ghosts_index_), - each_boundary_type_with_all_ghosts_eij_(ghost_creation.each_boundary_type_with_all_ghosts_eij_), - each_boundary_type_contact_real_index_(ghost_creation.each_boundary_type_contact_real_index_) {}; - //=================================================================================================// - void BoundaryConditionSetupInFVM::resetBoundaryConditions() - { - for (size_t boundary_type = 0; boundary_type < each_boundary_type_with_all_ghosts_index_.size(); ++boundary_type) - { - if (!each_boundary_type_with_all_ghosts_index_[boundary_type].empty()) - { - for (size_t ghost_number = 0; ghost_number != each_boundary_type_with_all_ghosts_index_[boundary_type].size(); ++ghost_number) - { - size_t ghost_index = each_boundary_type_with_all_ghosts_index_[boundary_type][ghost_number]; - size_t index_i = each_boundary_type_contact_real_index_[boundary_type][ghost_number]; - Vecd e_ij = each_boundary_type_with_all_ghosts_eij_[boundary_type][ghost_number]; - - // Dispatch the appropriate boundary condition - switch (boundary_type) - { - case 3: // this refer to the different types of wall boundary condtions - applyNonSlipWallBoundary(ghost_index, index_i); - applyReflectiveWallBoundary(ghost_index, index_i, e_ij); - break; - case 4: - applyTopBoundary(ghost_index, index_i); - break; - case 5: - applyPressureOutletBC(ghost_index, index_i); - break; - case 7: - applySymmetryBoundary(ghost_index, index_i, e_ij); - break; - case 9: - applyFarFieldBoundary(ghost_index); - break; - case 10: - applyGivenValueInletFlow(ghost_index); - applyVelocityInletFlow(ghost_index, index_i); - break; - case 36: - applyOutletBoundary(ghost_index, index_i); - break; - } - } - } - } - } - - -}// namespace SPH \ No newline at end of file diff --git a/src/for_3D_build/bodies/unstructured_mesh_3d.cpp b/src/for_3D_build/bodies/unstructured_mesh_3d.cpp new file mode 100644 index 0000000000..687e972c11 --- /dev/null +++ b/src/for_3D_build/bodies/unstructured_mesh_3d.cpp @@ -0,0 +1,301 @@ +#include "mesh_helper.h" +#include "unstructured_mesh.h" + +#include "base_particle_dynamics.h" +namespace SPH +{ +//=================================================================================================// +ANSYSMesh::ANSYSMesh(const std::string &full_path) +{ + getDataFromMeshFile(full_path); + getElementCenterCoordinates(); + getMinimumDistanceBetweenNodes(); +} +//=================================================================================================// +void ANSYSMesh::getDataFromMeshFile(const std::string &full_path) +{ + Real ICEM = 0; + std::ifstream mesh_file; /*!< \brief File object for the Ansys ASCII mesh file. */ + mesh_file.open(full_path); + if (mesh_file.fail()) + { + std::cout << "Error:Check if the file exists." << std::endl; + } + std::string text_line; + /*Check mesh file generation software*/ + (getline(mesh_file, text_line)); + text_line.erase(0, 4); + std::istringstream value(text_line); + if (text_line.find("Created by", 0) != std::string::npos) + { + ICEM = 1; + std::cout << "Reading 3D ICEM mesh." << std::endl; + } + + if (ICEM == 1) + { + + /*--- Read the dimension of the mesh ---*/ + size_t dimension(0); + MeshFileHelpers::meshDimension(mesh_file, dimension, text_line); + + /*--- Read the node data (index is starting from zero) ---*/ + size_t number_of_points(0); + MeshFileHelpers::numberOfNodes(mesh_file, number_of_points, text_line); + MeshFileHelpers::nodeCoordinates(mesh_file, node_coordinates_, text_line, dimension); + + size_t boundary_type(0); + size_t number_of_elements(0); + size_t mesh_type = 4; + MeshFileHelpers::numberOfElements(mesh_file, number_of_elements, text_line); + + /*Preparing and initializing the data structure of mesh topology and element node connection*/ + MeshFileHelpers::dataStruct(mesh_topology_, elements_nodes_connection_, number_of_elements, mesh_type, dimension); + + /*--- find the elements lines ---*/ + while (getline(mesh_file, text_line)) + { + if (text_line.find("(13", 0) != std::string::npos && text_line.find(")(", 0) != std::string::npos) + { + boundary_type = MeshFileHelpers::findBoundaryType(text_line, boundary_type); + types_of_boundary_condition_.push_back(boundary_type); + while (getline(mesh_file, text_line)) + { + if (text_line.find(")", 0) == std::string::npos) + { + Vecd nodes = MeshFileHelpers::nodeIndex(text_line); + Vec2d cells = MeshFileHelpers::cellIndex(text_line); + + /*--- build up all topology---*/ + bool check_neighbor_cell1 = 1; + bool check_neighbor_cell2 = 0; + for (int cell1_cell2 = 0; cell1_cell2 != cells.size(); ++cell1_cell2) + { + if (mesh_type == 4) + { + if (cells[check_neighbor_cell2] != 0) + { + MeshFileHelpers::updateElementsNodesConnection(elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2); + MeshFileHelpers::updateCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); + MeshFileHelpers::updateBoundaryCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2, boundary_type); + } + if (cells[check_neighbor_cell2] == 0) + { + break; + } + } + } + } + else + break; + } + } + if (text_line.find("Zone Sections", 0) != std::string::npos) + break; + if (text_line.find(")") != std::string::npos) + continue; + } + mesh_topology_.erase(mesh_topology_.begin()); + } + else /*This section is for mesh files created from fluent*/ + { + std::cout << "Reading 3D Fluent mesh." << std::endl; + size_t dimension(0); + MeshFileHelpers::meshDimension(mesh_file, dimension, text_line); + + /*--- Read the node data (index is starting from zero) ---*/ + size_t number_of_points(0); + MeshFileHelpers::numberOfNodesFluent(mesh_file, number_of_points, text_line); + + size_t boundary_type(0); + size_t number_of_elements(0); + size_t mesh_type = 4; + + MeshFileHelpers::numberOfElementsFluent(mesh_file, number_of_elements, text_line); + MeshFileHelpers::dataStruct(mesh_topology_, elements_nodes_connection_, number_of_elements, mesh_type, dimension); + MeshFileHelpers::nodeCoordinatesFluent(mesh_file, node_coordinates_, text_line, dimension); + + while (getline(mesh_file, text_line)) + { + + if (text_line.find("(13", 0) != std::string::npos && text_line.find(") (", 0) != std::string::npos) + { + boundary_type = MeshFileHelpers::findBoundaryType(text_line, boundary_type); + types_of_boundary_condition_.push_back(boundary_type); + while (getline(mesh_file, text_line)) + { + + if (text_line.find(")", 0) == std::string::npos) + { + Vecd nodes = MeshFileHelpers::nodeIndex(text_line); + Vec2d cells = MeshFileHelpers::cellIndex(text_line); + /*--- build up all topology---*/ + bool check_neighbor_cell1 = 1; + bool check_neighbor_cell2 = 0; + for (int cell1_cell2 = 0; cell1_cell2 != cells.size(); ++cell1_cell2) + { + if (mesh_type == 4) + { + if (cells[check_neighbor_cell2] != 0) + { + MeshFileHelpers::updateElementsNodesConnection(elements_nodes_connection_, nodes, cells, check_neighbor_cell1, check_neighbor_cell2); + MeshFileHelpers::updateCellLists(mesh_topology_, elements_nodes_connection_, nodes, cells, check_neighbor_cell1, + check_neighbor_cell2, boundary_type); + MeshFileHelpers::updateBoundaryCellListsFluent(mesh_topology_, elements_nodes_connection_, nodes, cells, + check_neighbor_cell1, check_neighbor_cell2, boundary_type); + } + if (cells[check_neighbor_cell2] == 0) + { + break; + } + } + } + } + else + break; + } + } + if (text_line.find("(12", 0) != std::string::npos && text_line.find("))", 0) != std::string::npos) + break; + if (text_line.find(")") != std::string::npos) + continue; + } + mesh_topology_.erase(mesh_topology_.begin()); + } +} +//=================================================================================================// + +void ANSYSMesh::getElementCenterCoordinates() +{ + elements_centroids_.resize(elements_nodes_connection_.size()); + elements_volumes_.resize(elements_nodes_connection_.size()); + for (std::size_t element = 1; element != elements_nodes_connection_.size(); ++element) + { + Vecd center_coordinate = Vecd::Zero(); + MeshFileHelpers::cellCenterCoordinates(elements_nodes_connection_, element, node_coordinates_, elements_centroids_, center_coordinate); + MeshFileHelpers::elementVolume(elements_nodes_connection_, element, node_coordinates_, elements_volumes_); + } + elements_volumes_.erase(elements_volumes_.begin()); + elements_centroids_.erase(elements_centroids_.begin()); + elements_nodes_connection_.erase(elements_nodes_connection_.begin()); +} +//=================================================================================================// + +void ANSYSMesh::getMinimumDistanceBetweenNodes() +{ + StdVec all_data_of_distance_between_nodes; + all_data_of_distance_between_nodes.resize(0); + MeshFileHelpers::minimumDistance(all_data_of_distance_between_nodes, elements_volumes_, mesh_topology_, node_coordinates_); + auto min_distance_iter = std::min_element(all_data_of_distance_between_nodes.begin(), all_data_of_distance_between_nodes.end()); + if (min_distance_iter != all_data_of_distance_between_nodes.end()) + { + min_distance_between_nodes_ = *min_distance_iter; + } + else + { + std::cout << "The array of all distance between nodes is empty " << std::endl; + } +} +//=================================================================================================// +void BaseInnerRelationInFVM::resetNeighborhoodCurrentSize() +{ + parallel_for( + IndexRange(0, base_particles_.total_real_particles_), + [&](const IndexRange &r) + { + for (size_t num = r.begin(); num != r.end(); ++num) + { + inner_configuration_[num].current_size_ = 0; + } + }, + ap); +} +//=================================================================================================// +void NeighborBuilderInFVM::createRelation(Neighborhood &neighborhood, Real &distance, + Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const +{ + neighborhood.j_.push_back(j_index); + neighborhood.r_ij_.push_back(distance); + neighborhood.e_ij_.push_back(interface_normal_direction); + neighborhood.dW_ij_.push_back(dW_ij); + neighborhood.allocated_size_++; +} +//=================================================================================================// +void NeighborBuilderInFVM::initializeRelation(Neighborhood &neighborhood, Real &distance, + Real &dW_ij, Vecd &interface_normal_direction, size_t j_index) const +{ + size_t current_size = neighborhood.current_size_; + neighborhood.j_[current_size] = j_index; + neighborhood.dW_ij_[current_size] = dW_ij; + neighborhood.r_ij_[current_size] = distance; + neighborhood.e_ij_[current_size] = interface_normal_direction; +} + +//=================================================================================================// +InnerRelationInFVM::InnerRelationInFVM(RealBody &real_body, ANSYSMesh &ansys_mesh) + : BaseInnerRelationInFVM(real_body, ansys_mesh), get_inner_neighbor_(&real_body){}; +//=================================================================================================// +template +void InnerRelationInFVM::searchNeighborsByParticles(size_t total_particles, BaseParticles &source_particles, + ParticleConfiguration &particle_configuration, + GetParticleIndex &get_particle_index, GetNeighborRelation &get_neighbor_relation) +{ + parallel_for( + IndexRange(0, base_particles_.total_real_particles_), + [&](const IndexRange &r) + { + for (size_t num = r.begin(); num != r.end(); ++num) + { + size_t index_i = get_particle_index(num); + Vecd &particle_position = pos_[index_i]; + + Neighborhood &neighborhood = particle_configuration[index_i]; + for (std::vector>::size_type neighbor = 0; neighbor != mesh_topology_[index_i].size(); ++neighbor) + { + size_t index_j = mesh_topology_[index_i][neighbor][0] - 1; + size_t boundary_type = mesh_topology_[index_i][neighbor][1]; + size_t interface_node1_index = mesh_topology_[index_i][neighbor][2]; + size_t interface_node2_index = mesh_topology_[index_i][neighbor][3]; + size_t interface_node3_index = mesh_topology_[index_i][neighbor][4]; + Vecd node1_position = Vecd(node_coordinates_[interface_node1_index][0], node_coordinates_[interface_node1_index][1], node_coordinates_[interface_node1_index][2]); + Vecd node2_position = Vecd(node_coordinates_[interface_node2_index][0], node_coordinates_[interface_node2_index][1], node_coordinates_[interface_node2_index][2]); + Vecd node3_position = Vecd(node_coordinates_[interface_node3_index][0], node_coordinates_[interface_node3_index][1], node_coordinates_[interface_node3_index][2]); + Vecd interface_area_vector1 = node1_position - node2_position; + Vecd interface_area_vector2 = node1_position - node3_position; + Vecd normal_vector = interface_area_vector1.cross(interface_area_vector2); + Real magnitude = normal_vector.norm(); + Vecd normalized_normal_vector = normal_vector / magnitude; + Vecd node1_to_center_direction = particle_position - node1_position; + if (node1_to_center_direction.dot(normalized_normal_vector) < 0) + { + normalized_normal_vector = -normalized_normal_vector; + }; + Real r_ij = 0; // we need r_ij to calculate the viscous force + // boundary_type == 2 means both of them are inside of fluid + if (boundary_type == 2) + { + r_ij = (particle_position - pos_[index_j]).dot(normalized_normal_vector); + } + // this refer to the different types of wall boundary conditions + if ((boundary_type == 3) | (boundary_type == 4) | (boundary_type == 5) | (boundary_type == 7) | (boundary_type == 9) | + (boundary_type == 10) | (boundary_type == 36)) + { + r_ij = node1_to_center_direction.dot(normalized_normal_vector) * 2.0; + } + Real dW_ij = (-0.5 * magnitude) / (2.0 * Vol_[index_i] * Vol_[index_j]); + get_neighbor_relation(neighborhood, r_ij, dW_ij, normalized_normal_vector, index_j); + } + } + }, + ap); +} +//=================================================================================================// +void InnerRelationInFVM::updateConfiguration() +{ + resetNeighborhoodCurrentSize(); + searchNeighborsByParticles(base_particles_.total_real_particles_, + base_particles_, inner_configuration_, + get_particle_index_, get_inner_neighbor_); +} +//=================================================================================================// +} // namespace SPH diff --git a/src/for_3D_build/common/scalar_functions_supplementary.cpp b/src/for_3D_build/common/scalar_functions_3d.cpp similarity index 100% rename from src/for_3D_build/common/scalar_functions_supplementary.cpp rename to src/for_3D_build/common/scalar_functions_3d.cpp diff --git a/src/for_3D_build/common/vector_functions_supplementary.cpp b/src/for_3D_build/common/vector_functions_3d.cpp similarity index 100% rename from src/for_3D_build/common/vector_functions_supplementary.cpp rename to src/for_3D_build/common/vector_functions_3d.cpp diff --git a/src/for_3D_build/geometries/level_set_supplementary.cpp b/src/for_3D_build/geometries/level_set_3d.cpp similarity index 100% rename from src/for_3D_build/geometries/level_set_supplementary.cpp rename to src/for_3D_build/geometries/level_set_3d.cpp diff --git a/src/for_3D_build/io_system/io_vtk_fvm_3d.cpp b/src/for_3D_build/io_system/io_vtk_fvm_3d.cpp new file mode 100644 index 0000000000..3900e331fb --- /dev/null +++ b/src/for_3D_build/io_system/io_vtk_fvm_3d.cpp @@ -0,0 +1,54 @@ +#include "io_vtk_fvm.h" + +#include "mesh_helper.h" +namespace SPH +{ +//=================================================================================================// +void BodyStatesRecordingInMeshToVtu::writeWithFileName(const std::string &sequence) +{ + for (SPHBody *body : bodies_) + { + if (body->checkNewlyUpdated() && state_recording_) + { + std::string filefullpath = io_environment_.output_folder_ + "/SPHBody_" + body->getName() + "_" + sequence + ".vtu"; + if (fs::exists(filefullpath)) + { + fs::remove(filefullpath); + } + std::ofstream out_file(filefullpath.c_str(), std::ios::trunc); + + MeshFileHelpers::vtuFileHeader(out_file); + Real range_max = 0.0; + MeshFileHelpers::vtuFileNodeCoordinates(out_file, node_coordinates_, elements_nodes_connection_, bounds_, range_max); + + MeshFileHelpers::vtuFileInformationKey(out_file, range_max); + + MeshFileHelpers::vtuFileCellConnectivity(out_file, elements_nodes_connection_, node_coordinates_); + + MeshFileHelpers::vtuFileOffsets(out_file, elements_nodes_connection_); + + MeshFileHelpers::vtuFileTypeOfCell(out_file, elements_nodes_connection_); + + // write Particle data to vtu file + out_file << "\n"; + body->writeParticlesToVtuFile(out_file); + out_file << "\n"; + // Write VTU file footer + out_file << "\n"; + out_file << "\n"; + out_file << "\n"; + out_file.close(); + } + body->setNotNewlyUpdated(); + } +} +//=================================================================================================// +void BodyStatesRecordingInMeshToVtp::writeWithFileName(const std::string &sequence) +{ + std::cout << "For 3D build:" + << "The method BodyStatesRecordingInMeshToVtp::writeWithFileName not implemented yet." + << std::endl; + exit(1); +} +//=================================================================================================// +} // namespace SPH diff --git a/src/for_3D_build/materials/elastic_solid_supplementary.cpp b/src/for_3D_build/materials/elastic_solid_3d.cpp similarity index 100% rename from src/for_3D_build/materials/elastic_solid_supplementary.cpp rename to src/for_3D_build/materials/elastic_solid_3d.cpp diff --git a/src/for_3D_build/meshes/base_mesh_supplementary.cpp b/src/for_3D_build/meshes/base_mesh_3d.cpp similarity index 100% rename from src/for_3D_build/meshes/base_mesh_supplementary.cpp rename to src/for_3D_build/meshes/base_mesh_3d.cpp diff --git a/src/for_3D_build/meshes/cell_linked_list.hpp b/src/for_3D_build/meshes/cell_linked_list.hpp index 0afda6cffa..548e3010a2 100644 --- a/src/for_3D_build/meshes/cell_linked_list.hpp +++ b/src/for_3D_build/meshes/cell_linked_list.hpp @@ -23,7 +23,7 @@ void CellLinkedList::searchNeighborsByParticles( DynamicsRange &dynamics_range, ParticleConfiguration &particle_configuration, GetSearchDepth &get_search_depth, GetNeighborRelation &get_neighbor_relation) { - StdLargeVec &pos = dynamics_range.getBaseParticles().pos_; + StdLargeVec &pos = dynamics_range.getBaseParticles().ParticlePositions(); particle_for(execution::ParallelPolicy(), dynamics_range.LoopRange(), [&](size_t index_i) { diff --git a/src/for_3D_build/meshes/cell_linked_list_supplementary.cpp b/src/for_3D_build/meshes/cell_linked_list_3d.cpp similarity index 99% rename from src/for_3D_build/meshes/cell_linked_list_supplementary.cpp rename to src/for_3D_build/meshes/cell_linked_list_3d.cpp index ac967d69f5..173edd19a4 100644 --- a/src/for_3D_build/meshes/cell_linked_list_supplementary.cpp +++ b/src/for_3D_build/meshes/cell_linked_list_3d.cpp @@ -34,7 +34,7 @@ void CellLinkedList::clearCellLists() //=================================================================================================// void CellLinkedList::UpdateCellListData(BaseParticles &base_particles) { - StdLargeVec &pos = base_particles.pos_; + StdLargeVec &pos = base_particles.ParticlePositions(); mesh_parallel_for( MeshRange(Array3i::Zero(), all_cells_), [&](int i, int j, int k) diff --git a/src/for_3D_build/particle_dynamics/general_dynamics/fvm_ghost_boundary_3d.cpp b/src/for_3D_build/particle_dynamics/general_dynamics/fvm_ghost_boundary_3d.cpp new file mode 100644 index 0000000000..54be2278d8 --- /dev/null +++ b/src/for_3D_build/particle_dynamics/general_dynamics/fvm_ghost_boundary_3d.cpp @@ -0,0 +1,130 @@ +#include "fvm_ghost_boundary.h" + +#include "base_particles.hpp" + +namespace SPH +{ +//=================================================================================================// +void GhostCreationFromMesh::addGhostParticleAndSetInConfiguration() +{ + ghost_bound_.second = ghost_bound_.first; + + for (size_t index_i = 0; index_i != particles_->total_real_particles_; ++index_i) + { + for (size_t neighbor_index = 0; neighbor_index != mesh_topology_[index_i].size(); ++neighbor_index) + { + size_t boundary_type = mesh_topology_[index_i][neighbor_index][1]; + if (mesh_topology_[index_i][neighbor_index][1] != 2) + { + mutex_create_ghost_particle_.lock(); + size_t ghost_particle_index = ghost_bound_.second; + ghost_bound_.second++; + ghost_boundary_.checkWithinGhostSize(ghost_bound_); + + particles_->updateGhostParticle(ghost_particle_index, index_i); + size_t node1_index = mesh_topology_[index_i][neighbor_index][2]; + size_t node2_index = mesh_topology_[index_i][neighbor_index][3]; + size_t node3_index = mesh_topology_[index_i][neighbor_index][4]; + Vecd node1_position = node_coordinates_[node1_index]; + Vecd node2_position = node_coordinates_[node2_index]; + Vecd node3_position = node_coordinates_[node3_index]; + Vecd ghost_particle_position = (1.0 / 3.0) * (node1_position + node2_position + node3_position); + + mesh_topology_[index_i][neighbor_index][0] = ghost_particle_index + 1; + pos_[ghost_particle_index] = ghost_particle_position; + mutex_create_ghost_particle_.unlock(); + + mesh_topology_.resize(ghost_particle_index); + std::vector> new_element; + + // Add (corresponding_index_i,boundary_type,node1_index,node2_index, node3_index) to the new element + std::vector sub_element1 = {index_i + 1, boundary_type, node1_index, node2_index, node3_index}; + new_element.push_back(sub_element1); + + // Add (corresponding_index_i,boundary_type,node1_index,node2_index, node3_index) to the new element + std::vector sub_element2 = {index_i + 1, boundary_type, node1_index, node2_index, node3_index}; + new_element.push_back(sub_element2); + + // Add (corresponding_index_i,boundary_type,node1_index,node2_index, node3_index) to the new element + std::vector sub_element3 = {index_i + 1, boundary_type, node1_index, node2_index, node3_index}; + new_element.push_back(sub_element3); + + // Add (corresponding_index_i,boundary_type,node1_index,node2_index) to the new element + std::vector sub_element4 = {index_i + 1, boundary_type, node1_index, node2_index, node3_index}; + new_element.push_back(sub_element4); + + // Add the new element to all_needed_data_from_mesh_file_ + mesh_topology_.push_back(new_element); + // all_needed_data_from_mesh_file_[ghost_particle_index][0][0].push_back(size_t(0); + + // creating the boundary files with ghost particle index + each_boundary_type_with_all_ghosts_index_[boundary_type].push_back(ghost_particle_index); + + // creating the boundary files with contact real particle index + each_boundary_type_contact_real_index_[boundary_type].push_back(index_i); + + // creating the boundary files with ghost eij + Vecd interface_area_vector1 = node2_position - node1_position; + Vecd interface_area_vector2 = node3_position - node1_position; + Vecd normal_vector = interface_area_vector1.cross(interface_area_vector2); + Real magnitude = normal_vector.norm(); + // Real interface_area_size = interface_area_vector.norm(); + Vecd normalized_normal_vector = normal_vector / magnitude; + // judge the direction + Vecd particle_position = pos_[index_i]; + Vecd node1_to_center_direction = particle_position - node1_position; + if (node1_to_center_direction.dot(normalized_normal_vector) < 0) + { + normalized_normal_vector = -normalized_normal_vector; + }; + each_boundary_type_with_all_ghosts_eij_[boundary_type].push_back(normalized_normal_vector); + } + } + } +} +//=================================================================================================// +void BoundaryConditionSetupInFVM::resetBoundaryConditions() +{ + for (size_t boundary_type = 0; boundary_type < each_boundary_type_with_all_ghosts_index_.size(); ++boundary_type) + { + if (!each_boundary_type_with_all_ghosts_index_[boundary_type].empty()) + { + for (size_t ghost_number = 0; ghost_number != each_boundary_type_with_all_ghosts_index_[boundary_type].size(); ++ghost_number) + { + size_t ghost_index = each_boundary_type_with_all_ghosts_index_[boundary_type][ghost_number]; + size_t index_i = each_boundary_type_contact_real_index_[boundary_type][ghost_number]; + Vecd e_ij = each_boundary_type_with_all_ghosts_eij_[boundary_type][ghost_number]; + + // Dispatch the appropriate boundary condition + switch (boundary_type) + { + case 3: // this refer to the different types of wall boundary conditions + applyNonSlipWallBoundary(ghost_index, index_i); + applyReflectiveWallBoundary(ghost_index, index_i, e_ij); + break; + case 4: + applyTopBoundary(ghost_index, index_i); + break; + case 5: + applyPressureOutletBC(ghost_index, index_i); + break; + case 7: + applySymmetryBoundary(ghost_index, index_i, e_ij); + break; + case 9: + applyFarFieldBoundary(ghost_index); + break; + case 10: + applyGivenValueInletFlow(ghost_index); + applyVelocityInletFlow(ghost_index, index_i); + break; + case 36: + applyOutletBoundary(ghost_index, index_i); + break; + } + } + } + } +} +//=================================================================================================// +} // namespace SPH diff --git a/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.cpp b/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.cpp index 082a982ee6..b8fab2d8e6 100644 --- a/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.cpp +++ b/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.cpp @@ -1,31 +1,30 @@ #include "slender_structure_dynamics.h" +#include "base_particles.hpp" namespace SPH { -//=====================================================================================================// namespace slender_structure_dynamics { //=================================================================================================// -BarDynamicsInitialCondition::BarDynamicsInitialCondition(SPHBody &sph_body) - : LocalDynamics(sph_body), BarDataSimple(sph_body), - n0_(particles_->n0_), n_(particles_->n_), pseudo_n_(particles_->pseudo_n_), - pos0_(particles_->pos0_), transformation_matrix_(particles_->transformation_matrix_), - b_n0_(particles_->b_n0_), b_n_(particles_->b_n_), pseudo_b_n_(particles_->pseudo_b_n_) {} -//=================================================================================================// BarAcousticTimeStepSize::BarAcousticTimeStepSize(SPHBody &sph_body, Real CFL) : LocalDynamicsReduce(sph_body), - BarDataSimple(sph_body), CFL_(CFL), - vel_(particles_->vel_), force_(particles_->force_), - angular_vel_(particles_->angular_vel_), dangular_vel_dt_(particles_->dangular_vel_dt_), - force_prior_(particles_->force_prior_), - thickness_(particles_->thickness_), mass_(particles_->mass_), - rho0_(particles_->elastic_solid_.ReferenceDensity()), - E0_(particles_->elastic_solid_.YoungsModulus()), - nu_(particles_->elastic_solid_.PoissonRatio()), - c0_(particles_->elastic_solid_.ReferenceSoundSpeed()), + DataDelegateSimple(sph_body), CFL_(CFL), + elastic_solid_(DynamicCast(this, sph_body.getBaseMaterial())), + vel_(*particles_->getVariableByName("Velocity")), + force_(*particles_->getVariableByName("Force")), + angular_vel_(*particles_->getVariableByName("AngularVelocity")), + dangular_vel_dt_(*particles_->getVariableByName("AngularAcceleration")), + force_prior_(*particles_->getVariableByName("ForcePrior")), + thickness_(*particles_->getVariableByName("Thickness")), + mass_(*particles_->getVariableByName("Mass")), + rho0_(elastic_solid_.ReferenceDensity()), + E0_(elastic_solid_.YoungsModulus()), + nu_(elastic_solid_.PoissonRatio()), + c0_(elastic_solid_.ReferenceSoundSpeed()), smoothing_length_(sph_body.sph_adaptation_->ReferenceSmoothingLength()), - angular_b_vel_(particles_->angular_b_vel_), dangular_b_vel_dt_(particles_->dangular_b_vel_dt_), - width_(particles_->thickness_) {} + angular_b_vel_(*particles_->getVariableByName("BinormalAngularVelocity")), + dangular_b_vel_dt_(*particles_->getVariableByName("BinormalAngularAcceleration")), + width_(*particles_->getVariableByName("Width")) {} //=================================================================================================// Real BarAcousticTimeStepSize::reduce(size_t index_i, Real dt) { @@ -44,66 +43,83 @@ Real BarAcousticTimeStepSize::reduce(size_t index_i, Real dt) //=================================================================================================// BarCorrectConfiguration:: BarCorrectConfiguration(BaseInnerRelation &inner_relation) - : LocalDynamics(inner_relation.getSPHBody()), BarDataInner(inner_relation), - Vol_(particles_->Vol_), B_(particles_->B_), - n0_(particles_->n0_), b_n0_(particles_->b_n0_), transformation_matrix_(particles_->transformation_matrix_) {} + : LocalDynamics(inner_relation.getSPHBody()), DataDelegateInner(inner_relation), + Vol_(*particles_->getVariableByName("VolumetricMeasure")), + B_(*particles_->registerSharedVariable("LinearGradientCorrectionMatrix", IdentityMatrix::value)), + n0_(*particles_->registerSharedVariableFrom("InitialNormalDirection", "NormalDirection")), + transformation_matrix0_(*particles_->getVariableByName("TransformationMatrix")) {} //=================================================================================================// BarDeformationGradientTensor:: BarDeformationGradientTensor(BaseInnerRelation &inner_relation) - : LocalDynamics(inner_relation.getSPHBody()), BarDataInner(inner_relation), - Vol_(particles_->Vol_), - pos_(particles_->pos_), pseudo_n_(particles_->pseudo_n_), n0_(particles_->n0_), - B_(particles_->B_), F_(particles_->F_), F_bending_(particles_->F_bending_), - transformation_matrix_(particles_->transformation_matrix_), - pseudo_b_n_(particles_->pseudo_n_), b_n0_(particles_->n0_), F_b_bending_(particles_->F_b_bending_) {} + : LocalDynamics(inner_relation.getSPHBody()), DataDelegateInner(inner_relation), + Vol_(*particles_->getVariableByName("VolumetricMeasure")), + pos_(*particles_->getVariableByName("Position")), + pseudo_n_(*particles_->registerSharedVariableFrom("PseudoNormal", "NormalDirection")), + n0_(*particles_->registerSharedVariableFrom("InitialNormalDirection", "NormalDirection")), + B_(*particles_->getVariableByName("LinearGradientCorrectionMatrix")), + F_(*particles_->registerSharedVariable("DeformationGradient", IdentityMatrix::value)), + F_bending_(*particles_->registerSharedVariable("BendingDeformationGradient")), + transformation_matrix0_(*particles_->getVariableByName("TransformationMatrix")), + pseudo_b_n_(*particles_->registerSharedVariableFrom("PseudoBinormal", "BinormalDirection")), + b_n0_(*particles_->registerSharedVariableFrom("InitialBinormalDirection", "BinormalDirection")), + F_b_bending_(*particles_->registerSharedVariable("BinormalBending")) {} //=================================================================================================// BaseBarRelaxation::BaseBarRelaxation(BaseInnerRelation &inner_relation) - : LocalDynamics(inner_relation.getSPHBody()), BarDataInner(inner_relation), - rho_(particles_->rho_), - thickness_(particles_->thickness_), mass_(particles_->mass_), Vol_(particles_->Vol_), - pos_(particles_->pos_), vel_(particles_->vel_), - force_(particles_->force_), - force_prior_(particles_->force_prior_), - n0_(particles_->n0_), pseudo_n_(particles_->pseudo_n_), - dpseudo_n_dt_(particles_->dpseudo_n_dt_), dpseudo_n_d2t_(particles_->dpseudo_n_d2t_), - rotation_(particles_->rotation_), angular_vel_(particles_->angular_vel_), - dangular_vel_dt_(particles_->dangular_vel_dt_), - B_(particles_->B_), F_(particles_->F_), dF_dt_(particles_->dF_dt_), - F_bending_(particles_->F_bending_), dF_bending_dt_(particles_->dF_bending_dt_), - transformation_matrix_(particles_->transformation_matrix_), - width_(particles_->width_), - b_n0_(particles_->b_n0_), pseudo_b_n_(particles_->pseudo_b_n_), - dpseudo_b_n_dt_(particles_->dpseudo_b_n_dt_), dpseudo_b_n_d2t_(particles_->dpseudo_b_n_d2t_), - rotation_b_(particles_->rotation_b_), angular_b_vel_(particles_->angular_b_vel_), - dangular_b_vel_dt_(particles_->dangular_b_vel_dt_), F_b_bending_(particles_->F_b_bending_), - dF_b_bending_dt_(particles_->dF_b_bending_dt_) {} + : LocalDynamics(inner_relation.getSPHBody()), DataDelegateInner(inner_relation), + Vol_(*particles_->getVariableByName("VolumetricMeasure")), + thickness_(*particles_->getVariableByName("Thickness")), + width_(*particles_->getVariableByName("Width")), + pos_(*particles_->getVariableByName("Position")), + vel_(*particles_->registerSharedVariable("Velocity")), + force_(*particles_->registerSharedVariable("Force")), + force_prior_(*particles_->registerSharedVariable("ForcePrior")), + n0_(*particles_->registerSharedVariableFrom("InitialNormalDirection", "NormalDirection")), + pseudo_n_(*particles_->registerSharedVariableFrom("PseudoNormal", "NormalDirection")), + dpseudo_n_dt_(*particles_->registerSharedVariable("PseudoNormalChangeRate")), + dpseudo_n_d2t_(*particles_->registerSharedVariable("PseudoNormal2ndOrderTimeDerivative")), + rotation_(*particles_->registerSharedVariable("Rotation")), + angular_vel_(*particles_->registerSharedVariable("AngularVelocity")), + dangular_vel_dt_(*particles_->registerSharedVariable("AngularAcceleration")), + B_(*particles_->getVariableByName("LinearGradientCorrectionMatrix")), + F_(*particles_->registerSharedVariable("DeformationGradient", IdentityMatrix::value)), + dF_dt_(*particles_->registerSharedVariable("DeformationRate")), + F_bending_(*particles_->registerSharedVariable("BendingDeformationGradient")), + dF_bending_dt_(*particles_->registerSharedVariable("BendingDeformationRate")), + pseudo_b_n_(*particles_->registerSharedVariableFrom("PseudoBinormal", "BinormalDirection")), + dpseudo_b_n_dt_(*particles_->registerSharedVariable("PseudoBinormalChangeRate")), + dpseudo_b_n_d2t_(*particles_->registerSharedVariable("PseudoBinormal2ndOrderTimeDerivative")), + rotation_b_(*particles_->registerSharedVariable("BinormalRotation")), + angular_b_vel_(*particles_->registerSharedVariable("BinormalAngularVelocity")), + dangular_b_vel_dt_(*particles_->registerSharedVariable("BinormalAngularAcceleration")), + transformation_matrix0_(*particles_->getVariableByName("TransformationMatrix")), + F_b_bending_(*particles_->registerSharedVariable("BinormalBending")), + dF_b_bending_dt_(*particles_->registerSharedVariable("BinormalBendingRate")) {} //=================================================================================================// BarStressRelaxationFirstHalf:: BarStressRelaxationFirstHalf(BaseInnerRelation &inner_relation, int number_of_gaussian_points, bool hourglass_control) : BaseBarRelaxation(inner_relation), - elastic_solid_(particles_->elastic_solid_), - Vol_(particles_->Vol_), - global_stress_(particles_->global_stress_), - global_moment_(particles_->global_moment_), - mid_surface_cauchy_stress_(particles_->mid_surface_cauchy_stress_), - numerical_damping_scaling_(particles_->numerical_damping_scaling_), - global_shear_stress_(particles_->global_shear_stress_), - n_(particles_->n_), - rho0_(elastic_solid_.ReferenceDensity()), - inv_rho0_(1.0 / rho0_), + elastic_solid_(DynamicCast(this, sph_body_.getBaseMaterial())), + rho0_(elastic_solid_.ReferenceDensity()), inv_rho0_(1.0 / rho0_), smoothing_length_(sph_body_.sph_adaptation_->ReferenceSmoothingLength()), + numerical_damping_scaling_matrix_(Matd::Identity() * smoothing_length_), + rho_(*particles_->getVariableByName("Density")), + mass_(*particles_->getVariableByName("Mass")), + global_stress_(*particles_->registerSharedVariable("GlobalStress")), + global_moment_(*particles_->registerSharedVariable("GlobalMoment")), + mid_surface_cauchy_stress_(*particles_->registerSharedVariable("MidSurfaceCauchyStress")), + global_shear_stress_(*particles_->registerSharedVariable("GlobalShearStress")), + n_(*particles_->getVariableByName("NormalDirection")), E0_(elastic_solid_.YoungsModulus()), G0_(elastic_solid_.ShearModulus()), nu_(elastic_solid_.PoissonRatio()), hourglass_control_(hourglass_control), number_of_gaussian_points_(number_of_gaussian_points), - global_b_stress_(particles_->global_b_stress_), - global_b_moment_(particles_->global_b_moment_), - global_b_shear_stress_(particles_->global_b_shear_stress_), - b_n_(particles_->b_n_) + global_b_stress_(*particles_->registerSharedVariable("GlobalBinormalStress")), + global_b_moment_(*particles_->registerSharedVariable("GlobalBinormalMoment")), + global_b_shear_stress_(*particles_->registerSharedVariable("GlobalBinormalShearStress")), + b_n_(*particles_->getVariableByName("BinormalDirection")) { - /** Note that, only three-point and five-point Gaussian quadrature rules are defined. */ switch (number_of_gaussian_points) { @@ -144,8 +160,8 @@ void BarStressRelaxationFirstHalf::initialization(size_t index_i, Real dt) rho_[index_i] = rho0_ / J; /** Calculate the current normal direction of mid-surface. */ - n_[index_i] = transformation_matrix_[index_i].transpose() * getNormalFromDeformationGradientTensor(F_[index_i]); - b_n_[index_i] = transformation_matrix_[index_i].transpose() * getBinormalFromDeformationGradientTensor(F_[index_i]); + n_[index_i] = transformation_matrix0_[index_i].transpose() * getNormalFromDeformationGradientTensor(F_[index_i]); + b_n_[index_i] = transformation_matrix0_[index_i].transpose() * getBinormalFromDeformationGradientTensor(F_[index_i]); /** Get transformation matrix from global coordinates to current local coordinates. */ Matd current_transformation_matrix = getTransformationMatrix(n_[index_i], b_n_[index_i]); @@ -163,27 +179,29 @@ void BarStressRelaxationFirstHalf::initialization(size_t index_i, Real dt) Matd dF_gaussian_point_dt = dF_dt_[index_i] + gaussian_point_y[i] * dF_bending_dt_[index_i] * thickness_[index_i] * 0.5 + gaussian_point_x[i] * dF_b_bending_dt_[index_i] * width_[index_i] * 0.5; Matd inverse_F_gaussian_point = F_gaussian_point.inverse(); - Matd current_local_almansi_strain = current_transformation_matrix * transformation_matrix_[index_i].transpose() * 0.5 * + Matd current_local_almansi_strain = current_transformation_matrix * transformation_matrix0_[index_i].transpose() * 0.5 * (Matd::Identity() - inverse_F_gaussian_point.transpose() * inverse_F_gaussian_point) * - transformation_matrix_[index_i] * current_transformation_matrix.transpose(); + transformation_matrix0_[index_i] * current_transformation_matrix.transpose(); /** correct Almansi strain tensor according to plane stress problem. */ current_local_almansi_strain = getCorrectedAlmansiStrain(current_local_almansi_strain, nu_); /** correct out-plane numerical damping. */ + numerical_damping_scaling_matrix_(1, 1) = width_[i] < smoothing_length_ ? width_[i] : smoothing_length_; + numerical_damping_scaling_matrix_(2, 2) = thickness_[i] < smoothing_length_ ? thickness_[i] : smoothing_length_; Matd cauchy_stress = elastic_solid_.StressCauchy(current_local_almansi_strain, index_i) + - current_transformation_matrix * transformation_matrix_[index_i].transpose() * - F_gaussian_point * elastic_solid_.NumericalDampingRightCauchy(F_gaussian_point, dF_gaussian_point_dt, numerical_damping_scaling_[index_i], index_i) * - F_gaussian_point.transpose() * transformation_matrix_[index_i] * current_transformation_matrix.transpose() / F_gaussian_point.determinant(); + current_transformation_matrix * transformation_matrix0_[index_i].transpose() * F_gaussian_point * + elastic_solid_.NumericalDampingRightCauchy(F_gaussian_point, dF_gaussian_point_dt, numerical_damping_scaling_matrix_, index_i) * + F_gaussian_point.transpose() * transformation_matrix0_[index_i] * current_transformation_matrix.transpose() / F_gaussian_point.determinant(); /** Impose modeling assumptions. */ - cauchy_stress.row(Dimensions - 1) *= shear_correction_factor_; - cauchy_stress.col(Dimensions - 1) *= shear_correction_factor_; - cauchy_stress.row(Dimensions - 2) *= shear_correction_factor_; - cauchy_stress.col(Dimensions - 2) *= shear_correction_factor_; + cauchy_stress.row(2) *= shear_correction_factor_; + cauchy_stress.col(2) *= shear_correction_factor_; + cauchy_stress.row(1) *= shear_correction_factor_; + cauchy_stress.col(1) *= shear_correction_factor_; - cauchy_stress(Dimensions - 1, Dimensions - 1) = 0.0; - cauchy_stress(Dimensions - 2, Dimensions - 2) = 0.0; + cauchy_stress(2, 2) = 0.0; + cauchy_stress(1, 1) = 0.0; if (i == 0) { mid_surface_cauchy_stress_[index_i] = cauchy_stress; @@ -197,36 +215,36 @@ void BarStressRelaxationFirstHalf::initialization(size_t index_i, Real dt) resultant_b_moment += 0.5 * width_[index_i] * 0.5 * thickness_[index_i] * gaussian_weight_[i] * ((cauchy_stress)*gaussian_point_x[i] * width_[index_i] * 0.5); resultant_shear_stress -= - 0.5 * width_[index_i] * 0.5 * thickness_[index_i] * gaussian_weight_[i] * cauchy_stress.col(Dimensions - 1); + 0.5 * width_[index_i] * 0.5 * thickness_[index_i] * gaussian_weight_[i] * cauchy_stress.col(2); resultant_b_shear_stress -= - 0.5 * width_[index_i] * 0.5 * thickness_[index_i] * gaussian_weight_[i] * cauchy_stress.col(Dimensions - 2); + 0.5 * width_[index_i] * 0.5 * thickness_[index_i] * gaussian_weight_[i] * cauchy_stress.col(1); - resultant_stress.row(Dimensions - 1) = Vecd::Zero().transpose(); - resultant_stress.col(Dimensions - 1) = Vecd::Zero(); + resultant_stress.row(2) = Vecd::Zero().transpose(); + resultant_stress.col(2) = Vecd::Zero(); - resultant_stress.row(Dimensions - 2) = Vecd::Zero().transpose(); - resultant_stress.col(Dimensions - 2) = Vecd::Zero(); + resultant_stress.row(1) = Vecd::Zero().transpose(); + resultant_stress.col(1) = Vecd::Zero(); - resultant_moment.row(Dimensions - 1) = Vecd::Zero().transpose(); - resultant_moment.col(Dimensions - 1) = Vecd::Zero(); + resultant_moment.row(2) = Vecd::Zero().transpose(); + resultant_moment.col(2) = Vecd::Zero(); - resultant_b_moment.row(Dimensions - 2) = Vecd::Zero().transpose(); - resultant_b_moment.col(Dimensions - 2) = Vecd::Zero(); + resultant_b_moment.row(1) = Vecd::Zero().transpose(); + resultant_b_moment.col(1) = Vecd::Zero(); - resultant_shear_stress[Dimensions - 2] = 0.0; - resultant_b_shear_stress[Dimensions - 1] = 0.0; + resultant_shear_stress[1] = 0.0; + resultant_b_shear_stress[2] = 0.0; } /** stress and moment in global coordinates for pair interaction */ global_stress_[index_i] = J * current_transformation_matrix.transpose() * - resultant_stress * current_transformation_matrix * transformation_matrix_[index_i].transpose() * - inverse_F.transpose() * transformation_matrix_[index_i]; + resultant_stress * current_transformation_matrix * transformation_matrix0_[index_i].transpose() * + inverse_F.transpose() * transformation_matrix0_[index_i]; global_moment_[index_i] = J * current_transformation_matrix.transpose() * resultant_moment * current_transformation_matrix * - transformation_matrix_[index_i].transpose() * inverse_F.transpose() * transformation_matrix_[index_i]; + transformation_matrix0_[index_i].transpose() * inverse_F.transpose() * transformation_matrix0_[index_i]; global_shear_stress_[index_i] = J * current_transformation_matrix.transpose() * resultant_shear_stress; global_b_moment_[index_i] = J * current_transformation_matrix.transpose() * resultant_b_moment * current_transformation_matrix * - transformation_matrix_[index_i].transpose() * inverse_F.transpose() * transformation_matrix_[index_i]; + transformation_matrix0_[index_i].transpose() * inverse_F.transpose() * transformation_matrix0_[index_i]; global_b_shear_stress_[index_i] = J * current_transformation_matrix.transpose() * resultant_b_shear_stress; } //=================================================================================================// @@ -245,10 +263,10 @@ void BarStressRelaxationSecondHalf::initialization(size_t index_i, Real dt) Vecd pseudo_n_temp = pseudo_n_[index_i]; Vecd pseudo_b_n_temp = pseudo_b_n_[index_i]; - pseudo_n_[index_i] = transformation_matrix_[index_i].transpose() * + pseudo_n_[index_i] = transformation_matrix0_[index_i].transpose() * getVectorAfterThinStructureRotation(local_pseudo_n_0, rotation_[index_i]); - pseudo_b_n_[index_i] = transformation_matrix_[index_i].transpose() * + pseudo_b_n_[index_i] = transformation_matrix0_[index_i].transpose() * getVectorAfterThinStructureRotation(local_pseudo_b_n_0, rotation_b_[index_i]); if (dt < 1e-10) @@ -272,8 +290,10 @@ void BarStressRelaxationSecondHalf::update(size_t index_i, Real dt) //=================================================================================================// ConstrainBarBodyRegion:: ConstrainBarBodyRegion(BodyPartByParticle &body_part) - : BaseLocalDynamics(body_part), BarDataSimple(sph_body_), - vel_(particles_->vel_), angular_vel_(particles_->angular_vel_), angular_b_vel_(particles_->angular_b_vel_) {} + : BaseLocalDynamics(body_part), DataDelegateSimple(body_part.getSPHBody()), + vel_(*particles_->getVariableByName("Velocity")), + angular_vel_(*particles_->getVariableByName("AngularVelocity")), + angular_b_vel_(*particles_->getVariableByName("BinormalAngularVelocity")) {} //=================================================================================================// void ConstrainBarBodyRegion::update(size_t index_i, Real dt) { @@ -283,11 +303,17 @@ void ConstrainBarBodyRegion::update(size_t index_i, Real dt) } //=================================================================================================// ConstrainBarBodyRegionAlongAxis::ConstrainBarBodyRegionAlongAxis(BodyPartByParticle &body_part, int axis) - : BaseLocalDynamics(body_part), BarDataSimple(sph_body_), - axis_(axis), pos_(particles_->pos_), pos0_(particles_->pos0_), vel_(particles_->vel_), - force_(particles_->force_), rotation_(particles_->rotation_), angular_vel_(particles_->angular_vel_), - dangular_vel_dt_(particles_->dangular_vel_dt_), rotation_b_(particles_->rotation_b_), - angular_b_vel_(particles_->angular_b_vel_), dangular_b_vel_dt_(particles_->dangular_b_vel_dt_) {} + : BaseLocalDynamics(body_part), DataDelegateSimple(body_part.getSPHBody()), + axis_(axis), pos_(*particles_->getVariableByName("Position")), + pos0_(*particles_->registerSharedVariableFrom("InitialPosition", "Position")), + vel_(*particles_->getVariableByName("Velocity")), + force_(*particles_->getVariableByName("Force")), + rotation_(*particles_->getVariableByName("Rotation")), + angular_vel_(*particles_->getVariableByName("AngularVelocity")), + dangular_vel_dt_(*particles_->getVariableByName("AngularAcceleration")), + rotation_b_(*particles_->getVariableByName("BinormalRotation")), + angular_b_vel_(*particles_->getVariableByName("BinormalAngularVelocity")), + dangular_b_vel_dt_(*particles_->getVariableByName("BinormalAngularAcceleration")) {} //=================================================================================================// void ConstrainBarBodyRegionAlongAxis::update(size_t index_i, Real dt) { @@ -298,12 +324,13 @@ DistributingPointForcesToBar:: DistributingPointForcesToBar(SPHBody &sph_body, std::vector point_forces, std::vector reference_positions, Real time_to_full_external_force, Real particle_spacing_ref, Real h_spacing_ratio) - : LocalDynamics(sph_body), BarDataSimple(sph_body), + : LocalDynamics(sph_body), DataDelegateSimple(sph_body), point_forces_(point_forces), reference_positions_(reference_positions), time_to_full_external_force_(time_to_full_external_force), particle_spacing_ref_(particle_spacing_ref), h_spacing_ratio_(h_spacing_ratio), - pos0_(particles_->pos0_), force_prior_(particles_->force_prior_), - thickness_(particles_->thickness_) + pos_(*particles_->getVariableByName("Position")), + force_prior_(*particles_->getVariableByName("ForcePrior")), + thickness_(*particles_->getVariableByName("Thickness")) { for (size_t i = 0; i < point_forces_.size(); i++) { @@ -329,7 +356,7 @@ void DistributingPointForcesToBar::getWeight() for (size_t index = 0; index < particles_->total_real_particles_; ++index) { weight_[i][index] = 0.0; - Vecd displacement = reference_positions_[i] - pos0_[index]; + Vecd displacement = reference_positions_[i] - pos_[index]; if (displacement.squaredNorm() <= cutoff_radius_sqr) { weight_[i][index] = kernel_->W(h_ratio, displacement.norm(), displacement); diff --git a/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.h b/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.h index 920cf173b4..96941bed09 100644 --- a/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.h +++ b/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_dynamics.h @@ -33,45 +33,24 @@ #include "all_body_relations.h" #include "all_particle_dynamics.h" #include "base_kernel.h" -#include "beam_particles.h" #include "elastic_solid.h" #include "slender_structure_math.h" #include "solid_body.h" -#include "solid_particles.h" namespace SPH { namespace slender_structure_dynamics { -typedef DataDelegateSimple BarDataSimple; -typedef DataDelegateInner BarDataInner; - -/** - * @class BarDynamicsInitialCondition - * @brief set initial condition for bar particles - * This is a abstract class to be override for case specific initial conditions. - */ -class BarDynamicsInitialCondition : public LocalDynamics, public BarDataSimple -{ - public: - explicit BarDynamicsInitialCondition(SPHBody &sph_body); - virtual ~BarDynamicsInitialCondition(){}; - - protected: - StdLargeVec &n0_, &n_, &pseudo_n_, &pos0_; - StdLargeVec &transformation_matrix_; - StdLargeVec &b_n0_, &b_n_, &pseudo_b_n_; -}; - /** * @class BarAcousticTimeStepSize * @brief Computing the acoustic time step size for bar */ class BarAcousticTimeStepSize : public LocalDynamicsReduce, - public BarDataSimple + public DataDelegateSimple { protected: Real CFL_; + ElasticSolid &elastic_solid_; StdLargeVec &vel_, &force_, &angular_vel_, &dangular_vel_dt_, &force_prior_; StdLargeVec &thickness_, &mass_; Real rho0_, E0_, nu_, c0_; @@ -91,7 +70,7 @@ class BarAcousticTimeStepSize : public LocalDynamicsReduce, * @class BarCorrectConfiguration * @brief obtain the corrected initial configuration in strong form */ -class BarCorrectConfiguration : public LocalDynamics, public BarDataInner +class BarCorrectConfiguration : public LocalDynamics, public DataDelegateInner { public: explicit BarCorrectConfiguration(BaseInnerRelation &inner_relation); @@ -110,7 +89,7 @@ class BarCorrectConfiguration : public LocalDynamics, public BarDataInner global_configuration += r_ji * gradW_ijV_j.transpose(); } Matd local_configuration = - transformation_matrix_[index_i] * global_configuration * transformation_matrix_[index_i].transpose(); + transformation_matrix0_[index_i] * global_configuration * transformation_matrix0_[index_i].transpose(); /** correction matrix is obtained from local configuration. */ B_[index_i] = getCorrectionMatrix_beam(local_configuration); }; @@ -119,8 +98,7 @@ class BarCorrectConfiguration : public LocalDynamics, public BarDataInner StdLargeVec &Vol_; StdLargeVec &B_; StdLargeVec &n0_; - StdLargeVec &b_n0_; - StdLargeVec &transformation_matrix_; + StdLargeVec &transformation_matrix0_; }; /** @@ -128,7 +106,7 @@ class BarCorrectConfiguration : public LocalDynamics, public BarDataInner * @brief computing deformation gradient tensor for bar * TODO: need a test case for this. */ -class BarDeformationGradientTensor : public LocalDynamics, public BarDataInner +class BarDeformationGradientTensor : public LocalDynamics, public DataDelegateInner { public: explicit BarDeformationGradientTensor(BaseInnerRelation &inner_relation); @@ -139,7 +117,7 @@ class BarDeformationGradientTensor : public LocalDynamics, public BarDataInner const Vecd &pseudo_n_i = pseudo_n_[index_i]; const Vecd &pseudo_b_n_i = pseudo_b_n_[index_i]; const Vecd &pos_n_i = pos_[index_i]; - const Matd &transformation_matrix_i = transformation_matrix_[index_i]; + const Matd &transformation_matrix_i = transformation_matrix0_[index_i]; Matd deformation_part_one = Matd::Zero(); Matd deformation_part_two = Matd::Zero(); @@ -154,8 +132,8 @@ class BarDeformationGradientTensor : public LocalDynamics, public BarDataInner deformation_part_three -= ((pseudo_b_n_i - b_n0_[index_i]) - (pseudo_b_n_[index_j] - b_n0_[index_j])) * gradW_ijV_j.transpose(); } F_[index_i] = transformation_matrix_i * deformation_part_one * transformation_matrix_i.transpose() * B_[index_i]; - F_[index_i].col(Dimensions - 1) = transformation_matrix_i * pseudo_n_[index_i]; - F_[index_i].col(Dimensions - 2) = transformation_matrix_i * pseudo_b_n_[index_i]; + F_[index_i].col(2) = transformation_matrix_i * pseudo_n_[index_i]; + F_[index_i].col(1) = transformation_matrix_i * pseudo_b_n_[index_i]; F_bending_[index_i] = transformation_matrix_i * deformation_part_two * transformation_matrix_i.transpose() * B_[index_i]; F_b_bending_[index_i] = transformation_matrix_i * deformation_part_three * transformation_matrix_i.transpose() * B_[index_i]; }; @@ -164,7 +142,7 @@ class BarDeformationGradientTensor : public LocalDynamics, public BarDataInner StdLargeVec &Vol_; StdLargeVec &pos_, &pseudo_n_, &n0_; StdLargeVec &B_, &F_, &F_bending_; - StdLargeVec &transformation_matrix_; + StdLargeVec &transformation_matrix0_; StdLargeVec &pseudo_b_n_, &b_n0_; StdLargeVec &F_b_bending_; @@ -174,23 +152,22 @@ class BarDeformationGradientTensor : public LocalDynamics, public BarDataInner * @class BaseBarRelaxation * @brief abstract class for preparing bar relaxation */ -class BaseBarRelaxation : public LocalDynamics, public BarDataInner +class BaseBarRelaxation : public LocalDynamics, public DataDelegateInner { public: explicit BaseBarRelaxation(BaseInnerRelation &inner_relation); virtual ~BaseBarRelaxation(){}; protected: - StdLargeVec &rho_, &thickness_, &mass_, &Vol_; + StdLargeVec &Vol_, &thickness_, &width_; StdLargeVec &pos_, &vel_, &force_, &force_prior_; StdLargeVec &n0_, &pseudo_n_, &dpseudo_n_dt_, &dpseudo_n_d2t_, &rotation_, &angular_vel_, &dangular_vel_dt_; StdLargeVec &B_, &F_, &dF_dt_, &F_bending_, &dF_bending_dt_; - StdLargeVec &transformation_matrix_; - StdLargeVec &width_; - StdLargeVec &b_n0_, &pseudo_b_n_, &dpseudo_b_n_dt_, &dpseudo_b_n_d2t_, &rotation_b_, + StdLargeVec &pseudo_b_n_, &dpseudo_b_n_dt_, &dpseudo_b_n_d2t_, &rotation_b_, &angular_b_vel_, dangular_b_vel_dt_; + StdLargeVec &transformation_matrix0_; StdLargeVec &F_b_bending_, &dF_b_bending_dt_; }; @@ -225,7 +202,7 @@ class BarStressRelaxationFirstHalf : public BaseBarRelaxation size_t index_j = inner_neighborhood.j_[n]; force += mass_[index_i] * (global_stress_i + global_stress_[index_j]) * - inner_neighborhood.dW_ij_[n] * Vol_[index_j] * inner_neighborhood.e_ij_[n]; + inner_neighborhood.dW_ij_[n] * Vol_[index_j] * inner_neighborhood.e_ij_[n]; pseudo_normal_acceleration += (global_moment_i + global_moment_[index_j]) * inner_neighborhood.dW_ij_[n] * Vol_[index_j] * inner_neighborhood.e_ij_[n]; pseudo_b_normal_acceleration += (global_b_moment_i + global_b_moment_[index_j]) * @@ -236,8 +213,8 @@ class BarStressRelaxationFirstHalf : public BaseBarRelaxation dpseudo_n_d2t_[index_i] = pseudo_normal_acceleration * inv_rho0_ * 12.0 / pow(thickness_[index_i], 4); dpseudo_b_n_d2t_[index_i] = -pseudo_b_normal_acceleration * inv_rho0_ * 12.0 / pow(thickness_[index_i], 4); - Vecd local_dpseudo_n_d2t = transformation_matrix_[index_i] * dpseudo_n_d2t_[index_i]; - Vecd local_dpseudo_b_n_d2t = transformation_matrix_[index_i] * dpseudo_b_n_d2t_[index_i]; + Vecd local_dpseudo_n_d2t = transformation_matrix0_[index_i] * dpseudo_n_d2t_[index_i]; + Vecd local_dpseudo_b_n_d2t = transformation_matrix0_[index_i] * dpseudo_b_n_d2t_[index_i]; dangular_b_vel_dt_[index_i] = getRotationFromPseudoNormalForSmallDeformation_b( Vec3d(local_dpseudo_b_n_d2t), Vec3d(local_dpseudo_n_d2t), Vec3d(rotation_b_[index_i]), Vec3d(angular_b_vel_[index_i]), dt); dangular_vel_dt_[index_i] = getRotationFromPseudoNormalForSmallDeformation( @@ -248,12 +225,14 @@ class BarStressRelaxationFirstHalf : public BaseBarRelaxation protected: ElasticSolid &elastic_solid_; - StdLargeVec& Vol_; - StdLargeVec &global_stress_, &global_moment_, &mid_surface_cauchy_stress_, &numerical_damping_scaling_; + Real rho0_, inv_rho0_; + Real smoothing_length_; + Matd numerical_damping_scaling_matrix_; + StdLargeVec &rho_, &mass_; + StdLargeVec &global_stress_, &global_moment_, &mid_surface_cauchy_stress_; StdLargeVec &global_shear_stress_, &n_; - Real rho0_, inv_rho0_; - Real smoothing_length_, E0_, G0_, nu_, hourglass_control_factor_; + Real E0_, G0_, nu_, hourglass_control_factor_; bool hourglass_control_; const Real inv_W0_ = 1.0 / sph_body_.sph_adaptation_->getKernel()->W0(ZeroVecd); const Real shear_correction_factor_ = 5.0 / 6.0; @@ -299,7 +278,7 @@ class BarStressRelaxationSecondHalf : public BaseBarRelaxation const Vecd &vel_n_i = vel_[index_i]; const Vecd &dpseudo_n_dt_i = dpseudo_n_dt_[index_i]; const Vecd &dpseudo_b_n_dt_i = dpseudo_b_n_dt_[index_i]; - const Matd &transformation_matrix_i = transformation_matrix_[index_i]; + const Matd &transformation_matrix_i = transformation_matrix0_[index_i]; Matd deformation_gradient_change_rate_part_one = Matd::Zero(); Matd deformation_gradient_change_rate_part_three = Matd::Zero(); @@ -316,8 +295,8 @@ class BarStressRelaxationSecondHalf : public BaseBarRelaxation } dF_dt_[index_i] = transformation_matrix_i * deformation_gradient_change_rate_part_one * transformation_matrix_i.transpose() * B_[index_i]; - dF_dt_[index_i].col(Dimensions - 1) = transformation_matrix_i * dpseudo_n_dt_[index_i]; - dF_dt_[index_i].col(Dimensions - 2) = transformation_matrix_i * dpseudo_b_n_dt_[index_i]; + dF_dt_[index_i].col(2) = transformation_matrix_i * dpseudo_n_dt_[index_i]; + dF_dt_[index_i].col(1) = transformation_matrix_i * dpseudo_b_n_dt_[index_i]; dF_bending_dt_[index_i] = transformation_matrix_i * deformation_gradient_change_rate_part_two * transformation_matrix_i.transpose() * B_[index_i]; dF_b_bending_dt_[index_i] = transformation_matrix_i * deformation_gradient_change_rate_part_three * @@ -330,7 +309,7 @@ class BarStressRelaxationSecondHalf : public BaseBarRelaxation /**@class ConstrainBarBodyRegion * @brief Fix the position and angle of a bar body part. */ -class ConstrainBarBodyRegion : public BaseLocalDynamics, public BarDataSimple +class ConstrainBarBodyRegion : public BaseLocalDynamics, public DataDelegateSimple { public: ConstrainBarBodyRegion(BodyPartByParticle &body_part); @@ -346,7 +325,7 @@ class ConstrainBarBodyRegion : public BaseLocalDynamics, pub * The axis must be 0 or 1. * Note that the average values for FSI are prescribed also. */ -class ConstrainBarBodyRegionAlongAxis : public BaseLocalDynamics, public BarDataSimple +class ConstrainBarBodyRegionAlongAxis : public BaseLocalDynamics, public DataDelegateSimple { public: ConstrainBarBodyRegionAlongAxis(BodyPartByParticle &body_part, int axis); @@ -365,13 +344,13 @@ class ConstrainBarBodyRegionAlongAxis : public BaseLocalDynamics point_forces_, reference_positions_, time_dependent_point_forces_; Real time_to_full_external_force_; Real particle_spacing_ref_, h_spacing_ratio_; - StdLargeVec &pos0_, &force_prior_; + StdLargeVec &pos_, &force_prior_; StdLargeVec &thickness_; std::vector> weight_; std::vector sum_of_weight_; diff --git a/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_math.h b/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_math.h index 94c2568437..38fb74df56 100644 --- a/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_math.h +++ b/src/for_3D_build/particle_dynamics/solid_dynamics/slender_structure_math.h @@ -32,7 +32,6 @@ #include "all_particle_dynamics.h" #include "base_kernel.h" -#include "beam_particles.h" #include "elastic_solid.h" #include "weakly_compressible_fluid.h" namespace SPH diff --git a/src/for_3D_build/particle_dynamics/solid_dynamics/solid_dynamics_3d.cpp b/src/for_3D_build/particle_dynamics/solid_dynamics/solid_dynamics_3d.cpp new file mode 100644 index 0000000000..8259e936f1 --- /dev/null +++ b/src/for_3D_build/particle_dynamics/solid_dynamics/solid_dynamics_3d.cpp @@ -0,0 +1,38 @@ +#include "all_solid_dynamics.h" +#include "base_data_package.h" +#include "base_kernel.h" +#include "base_particles.hpp" +#include "cell_linked_list.h" +#include "elastic_solid.h" +#include "external_force.h" +#include "neighborhood.h" +#include "polar_decomposition_3x3.h" +#include "solid_body.h" +#include "weakly_compressible_fluid.h" + +using namespace polar; + +namespace SPH +{ +namespace solid_dynamics +{ +//=================================================================================================// +Vec3d UpdateElasticNormalDirection::getRotatedNormalDirection(const Mat3d &F, const Vec3d &n0) +{ + Real Q[9], H[9], A[9]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + A[i * 3 + j] = F(i, j); + + polar::polar_decomposition(Q, H, A); + // this decomposition has the form A = Q*H, where Q is orthogonal and H is symmetric positive semi-definite. + // Ref. "An algorithm to compute the polar decomposition of a 3*3 matrix, Nicholas J. Higham et al. Numer Algor(2016) " + Mat3d R; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + R(i, j) = Q[i * 3 + j]; + return R * n0; +} +//=================================================================================================// +} // namespace solid_dynamics +} // namespace SPH diff --git a/src/for_3D_build/particles/solid_particles_supplementary.cpp b/src/for_3D_build/particle_dynamics/solid_dynamics/solid_dynamics_variable_3d.cpp similarity index 60% rename from src/for_3D_build/particles/solid_particles_supplementary.cpp rename to src/for_3D_build/particle_dynamics/solid_dynamics/solid_dynamics_variable_3d.cpp index 92d4014fd4..aeb8f10737 100644 --- a/src/for_3D_build/particles/solid_particles_supplementary.cpp +++ b/src/for_3D_build/particle_dynamics/solid_dynamics/solid_dynamics_variable_3d.cpp @@ -1,40 +1,40 @@ #include "base_body.h" -#include "solid_particles.h" -#include "solid_particles_variable.h" +#include "solid_dynamics_variable.h" #include namespace SPH { //=================================================================================================// -Real ElasticSolidParticles::getVonMisesStrain(size_t particle_i) +void VonMisesStrain::update(size_t index_i, Real dt) { + Mat3d F = F_[index_i]; + Mat3d green_lagrange_strain = 0.5 * (F.transpose() * F - Matd::Identity()); - Mat3d F = F_[particle_i]; - Mat3d epsilon = 0.5 * (F.transpose() * F - Matd::Identity()); // calculation of the Green-Lagrange strain tensor + Real epsilonxx = green_lagrange_strain(0, 0); + Real epsilonyy = green_lagrange_strain(1, 1); + Real epsilonzz = green_lagrange_strain(2, 2); + Real epsilonxy = green_lagrange_strain(0, 1); + Real epsilonxz = green_lagrange_strain(0, 2); + Real epsilonyz = green_lagrange_strain(1, 2); - Real epsilonxx = epsilon(0, 0); - Real epsilonyy = epsilon(1, 1); - Real epsilonzz = epsilon(2, 2); - Real epsilonxy = epsilon(0, 1); - Real epsilonxz = epsilon(0, 2); - Real epsilonyz = epsilon(1, 2); - - return sqrt((1.0 / 3.0) * (pow(epsilonxx - epsilonyy, 2) + - pow(epsilonyy - epsilonzz, 2) + pow(epsilonzz - epsilonxx, 2)) + - 2.0 * (pow(epsilonxy, 2) + pow(epsilonyz, 2) + pow(epsilonxz, 2))); + derived_variable_[index_i] = sqrt((1.0 / 3.0) * (pow(epsilonxx - epsilonyy, 2) + + pow(epsilonyy - epsilonzz, 2) + pow(epsilonzz - epsilonxx, 2)) + + 2.0 * (pow(epsilonxy, 2) + pow(epsilonyz, 2) + pow(epsilonxz, 2))); } -//=================================================================================================// -Real ElasticSolidParticles::getVonMisesStrainDynamic(size_t particle_i, Real poisson) +//=============================================================================================// +void VonMisesStrainDynamic::update(size_t index_i, Real dt) { - Mat3d epsilon = getGreenLagrangeStrain(particle_i); // calculation of the Green-Lagrange strain tensor + Mat3d F = F_[index_i]; + Mat3d green_lagrange_strain = 0.5 * (F.transpose() * F - Matd::Identity()); - Vec3d principal_strains = getPrincipalValuesFromMatrix(epsilon); + Vec3d principal_strains = getPrincipalValuesFromMatrix(green_lagrange_strain); Real eps_1 = principal_strains[0]; Real eps_2 = principal_strains[1]; Real eps_3 = principal_strains[2]; - return 1.0 / (1.0 + poisson) * std::sqrt(0.5 * (pow(eps_1 - eps_2, 2) + pow(eps_2 - eps_3, 2) + pow(eps_3 - eps_1, 2))); + derived_variable_[index_i] = 1.0 / (1.0 + poisson_ratio_) * + std::sqrt(0.5 * (pow(eps_1 - eps_2, 2) + pow(eps_2 - eps_3, 2) + pow(eps_3 - eps_1, 2))); } //=============================================================================================// void VonMisesStress::update(size_t index_i, Real dt) diff --git a/src/for_3D_build/particle_generator/particle_generator_lattice_supplementary.cpp b/src/for_3D_build/particle_generator/particle_generator_lattice_3d.cpp similarity index 100% rename from src/for_3D_build/particle_generator/particle_generator_lattice_supplementary.cpp rename to src/for_3D_build/particle_generator/particle_generator_lattice_3d.cpp diff --git a/src/for_3D_build/particles/all_particles.h b/src/for_3D_build/particles/all_particles.h index b37ec31202..4ad974a42c 100644 --- a/src/for_3D_build/particles/all_particles.h +++ b/src/for_3D_build/particles/all_particles.h @@ -30,6 +30,6 @@ #define ALL_PARTICLES_3D_H #include "all_shared_particles.h" -#include "beam_particles.h" +#include "linear_particles.h" #endif // ALL_PARTICLES_3D_H \ No newline at end of file diff --git a/src/for_3D_build/particles/beam_particles.cpp b/src/for_3D_build/particles/beam_particles.cpp deleted file mode 100644 index a56ec7474b..0000000000 --- a/src/for_3D_build/particles/beam_particles.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "solid_particles.h" -#include "solid_particles_variable.h" - -#include "base_body.h" -#include "elastic_solid.h" -#include "inelastic_solid.h" -#include "xml_engine.h" -#include "beam_particles.h" - -namespace SPH -{ -//=============================================================================================// - - - - BarParticles::BarParticles(SPHBody &sph_body, ElasticSolid *elastic_solid) - : ShellParticles(sph_body, elastic_solid), width_ref_(1.0) - { - //---------------------------------------------------------------------- - // modify kernel function for surface particles - //---------------------------------------------------------------------- - // sph_body.sph_adaptation_->getKernel()->reduceTwice(); - //---------------------------------------------------------------------- - // register geometric data only - //---------------------------------------------------------------------- - registerVariable(b_n_, "BinormalDirection"); - registerVariable(width_, "Width"); - /** - * add particle reload data - */ - //addVariableNameToList(variables_to_reload_, "BinormalDirection"); - //addVariableNameToList(variables_to_reload_, "Width"); - } - //=================================================================================================// - void BarParticles::initializeOtherVariables() - { - ShellParticles::initializeOtherVariables(); - /** - * register particle data - */ - registerVariable(b_n0_, "InitialBinormalDirection", - [&](size_t i) -> Vecd - { return b_n_[i]; }); - registerVariable(pseudo_b_n_, "PseudoBinormal", - [&](size_t i) -> Vecd - { return pseudo_b_n_[i]; }); - registerVariable(dpseudo_b_n_dt_, "PseudoBinormalChangeRate"); - registerVariable(dpseudo_b_n_d2t_, "PseudoBinormal2ndOrderTimeDerivative"); - registerVariable(rotation_b_, "Rotation_b"); - registerVariable(angular_b_vel_, "AngularVelocity_b"); - registerVariable(dangular_b_vel_dt_, "AngularAccelerationofBinormal"); - registerVariable(F_b_bending_, "b_BendingDeformationGradient"); - registerVariable(dF_b_bending_dt_, "b_BendingDeformationGradientChangeRate"); - - registerVariable(global_b_shear_stress_, "Global_b_ShearStress"); - registerVariable(global_b_stress_, "Global_b_Stress"); - registerVariable(global_b_moment_, "Global_b_Moment"); - - /** - * for rotation. - */ - - addVariableToRestart("PseudoBinormal"); - addVariableToRestart("Rotation_b"); - addVariableToRestart("AngularVelocity_b"); - /** - * add basic output particle data - */ - addVariableToWrite("BinormalDirection"); - addVariableToWrite("Rotation_b"); - /** - * initialize transformation matrix - */ - for (size_t i = 0; i != real_particles_bound_; ++i) - { - - transformation_matrix_[i] = getTransformationMatrix(n_[i], b_n_[i]); - - } - } - } diff --git a/src/for_3D_build/particles/beam_particles.h b/src/for_3D_build/particles/beam_particles.h deleted file mode 100644 index 21db54e023..0000000000 --- a/src/for_3D_build/particles/beam_particles.h +++ /dev/null @@ -1,84 +0,0 @@ -/* ------------------------------------------------------------------------- * - * SPHinXsys * - * ------------------------------------------------------------------------- * - * SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * - * Hydrodynamics for industrial compleX systems. It provides C++ APIs for * - * physical accurate simulation and aims to model coupled industrial dynamic * - * systems including fluid, solid, multi-body dynamics and beyond with SPH * - * (smoothed particle hydrodynamics), a meshless computational method using * - * particle discretization. * - * * - * SPHinXsys is partially funded by German Research Foundation * - * (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1, * - * HU1527/12-1 and HU1527/12-4 * - * * - * Portions copyright (c) 2017-2022 Technical University of Munich and * - * the authors' affiliations. * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); you may * - * not use this file except in compliance with the License. You may obtain a * - * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * - * * - * ------------------------------------------------------------------------- */ -/** - * @file beam_particles.h - * @brief This is the derived class of shell particles. - * @author Xipeng Lyu - */ - -#ifndef BEAM_PARTICLES_H -#define BEAM_PARTICLES_H - -#include "base_body.h" -#include "base_particles.h" -#include "base_particles.hpp" -#include "elastic_solid.h" -#include "particle_generator_lattice.h" -#include "solid_particles.h" -// #include "solid_particles.h" -#include "solid_particles_variable.h" - -#include -namespace SPH -{ -class ShellParticles; -class Solid; -class ElasticSolid; -class SPHBody; -class BarParticles : public ShellParticles -{ - public: - BarParticles(SPHBody &sph_body, ElasticSolid *elastic_solid); - virtual ~BarParticles(){}; - - Real width_ref_; - StdLargeVec b_n_; /**< binormal direction */ - StdLargeVec width_; - StdLargeVec b_n0_; /**< initial binormal direction */ - - StdLargeVec pseudo_b_n_; /**< current pseudo-binormal vector */ - StdLargeVec dpseudo_b_n_dt_; /**< pseudo-binormal vector change rate */ - StdLargeVec dpseudo_b_n_d2t_; /**< pseudo-binormal vector second order time derivation */ - StdLargeVec global_b_shear_stress_; /**< global b shear stress */ - StdLargeVec global_b_stress_; /**< global b stress for pair interaction */ - StdLargeVec global_b_moment_; /**< global b bending moment for pair interaction */ - //---------------------------------------------------------------------- - // extra generalized coordinate and velocity in local coordinate - //---------------------------------------------------------------------- - StdLargeVec rotation_b_; /**< rotation angle of the initial binormal respective to each axis */ - StdLargeVec angular_b_vel_; /**< angular velocity respective to each axis */ - StdLargeVec dangular_b_vel_dt_; /**< angular acceleration of respective to each axis*/ - // extra deformation and deformation rate in local coordinate - //---------------------------------------------------------------------- - StdLargeVec F_b_bending_; /**< bending deformation gradient */ - StdLargeVec dF_b_bending_dt_; /**< bending deformation gradient change rate */ - //---------------------------------------------------------------------- - /** get particle volume. */ - virtual Real ParticleVolume(size_t index_i) override { return Vol_[index_i] * thickness_[index_i] * width_[index_i]; } - /** Initialize variable for shell particles. */ - virtual void initializeOtherVariables() override; - virtual BarParticles *ThisObjectPtr() override { return this; }; -}; - -} // namespace SPH -#endif // SOLID_PARTICLES_H diff --git a/src/for_3D_build/particles/linear_particles.cpp b/src/for_3D_build/particles/linear_particles.cpp new file mode 100644 index 0000000000..f21b2596a4 --- /dev/null +++ b/src/for_3D_build/particles/linear_particles.cpp @@ -0,0 +1,38 @@ +#include "linear_particles.h" + +namespace SPH +{ +//=============================================================================================// +LinearParticles::LinearParticles(SPHBody &sph_body, BaseMaterial *base_material) + : SurfaceParticles(sph_body, base_material) +{ + //---------------------------------------------------------------------- + // modify kernel function for surface particles + //---------------------------------------------------------------------- + // sph_body.sph_adaptation_->getKernel()->reduceTwice(); + //---------------------------------------------------------------------- + // register geometric data only + //---------------------------------------------------------------------- + registerVariable(b_n_, "BinormalDirection"); + registerVariable(width_, "Width"); + /** + * add particle reload data + */ + // addVariableNameToList(variables_to_reload_, "BinormalDirection"); + // addVariableNameToList(variables_to_reload_, "Width"); +} +//=================================================================================================// +void LinearParticles::initializeOtherVariables() +{ + SurfaceParticles::initializeOtherVariables(); + + addVariableToWrite("BinormalDirection"); +} +//=================================================================================================// +void LinearParticles::registerTransformationMatrix() +{ + registerVariable(transformation_matrix0_, "TransformationMatrix", [&](size_t index_i) -> Matd + { return getTransformationMatrix(n_[index_i], b_n_[index_i]); }); +} +//=================================================================================================// +} // namespace SPH diff --git a/src/for_3D_build/particles/linear_particles.h b/src/for_3D_build/particles/linear_particles.h new file mode 100644 index 0000000000..d52bcd8f01 --- /dev/null +++ b/src/for_3D_build/particles/linear_particles.h @@ -0,0 +1,55 @@ +/* ------------------------------------------------------------------------- * + * SPHinXsys * + * ------------------------------------------------------------------------- * + * SPHinXsys (pronunciation: s'finksis) is an acronym from Smoothed Particle * + * Hydrodynamics for industrial compleX systems. It provides C++ APIs for * + * physical accurate simulation and aims to model coupled industrial dynamic * + * systems including fluid, solid, multi-body dynamics and beyond with SPH * + * (smoothed particle hydrodynamics), a meshless computational method using * + * particle discretization. * + * * + * SPHinXsys is partially funded by German Research Foundation * + * (Deutsche Forschungsgemeinschaft) DFG HU1527/6-1, HU1527/10-1, * + * HU1527/12-1 and HU1527/12-4 * + * * + * Portions copyright (c) 2017-2022 Technical University of Munich and * + * the authors' affiliations. * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); you may * + * not use this file except in compliance with the License. You may obtain a * + * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * + * * + * ------------------------------------------------------------------------- */ +/** + * @file linear_particles.h + * @brief This is the derived class of shell particles. + * @author Xipeng Lyu and Xiangyu Hu + */ + +#ifndef LINEAR_PARTICLES_H +#define LINEAR_PARTICLES_H + +#include "surface_particles.h" + +namespace SPH +{ + +class LinearParticles : public SurfaceParticles +{ + public: + LinearParticles(SPHBody &sph_body, BaseMaterial *base_material); + virtual ~LinearParticles(){}; + + StdLargeVec b_n_; /**< binormal direction */ + StdLargeVec width_; + + /** get particle volume. */ + virtual Real ParticleVolume(size_t index_i) override { return Vol_[index_i] * thickness_[index_i] * width_[index_i]; } + /** Initialize variable for shell particles. */ + virtual void initializeOtherVariables() override; + virtual void registerTransformationMatrix() override; + virtual LinearParticles *ThisObjectPtr() override { return this; }; +}; + +} // namespace SPH +#endif // SOLID_PARTICLES_H diff --git a/src/shared/adaptations/adaptation.cpp b/src/shared/adaptations/adaptation.cpp index 13f68f3988..709f6e1b81 100644 --- a/src/shared/adaptations/adaptation.cpp +++ b/src/shared/adaptations/adaptation.cpp @@ -2,10 +2,10 @@ #include "base_particle_dynamics.h" #include "base_particles.hpp" +#include "cell_linked_list.h" +#include "level_set.h" #include "mesh_with_data_packages.hpp" #include "vector_functions.h" -#include "level_set.h" -#include "cell_linked_list.h" namespace SPH { @@ -116,7 +116,7 @@ void ParticleWithLocalRefinement::initializeAdaptationVariables(BaseParticles &b SPHAdaptation::initializeAdaptationVariables(base_particles); base_particles.registerVariable(h_ratio_, "SmoothingLengthRatio", [&](size_t i) -> Real { return ReferenceSpacing() / base_particles.ParticleSpacing(i); }); - base_particles.registerSortableVariable("SmoothingLengthRatio"); + base_particles.addVariableToSort("SmoothingLengthRatio"); base_particles.addVariableToReload("SmoothingLengthRatio"); } //=================================================================================================// diff --git a/src/shared/bodies/base_body.cpp b/src/shared/bodies/base_body.cpp index 757c294543..9eb5366be2 100644 --- a/src/shared/bodies/base_body.cpp +++ b/src/shared/bodies/base_body.cpp @@ -11,7 +11,7 @@ SPHBody::SPHBody(SPHSystem &sph_system, Shape &shape, const std::string &name) : sph_system_(sph_system), body_name_(name), newly_updated_(true), base_particles_(nullptr), is_bound_set_(false), initial_shape_(&shape), sph_adaptation_(sph_adaptation_ptr_keeper_.createPtr(sph_system.ReferenceResolution())), - base_material_(nullptr) + base_material_(base_material_ptr_keeper_.createPtr()) { sph_system_.sph_bodies_.push_back(this); } diff --git a/src/shared/bodies/base_body.h b/src/shared/bodies/base_body.h index 18ad183c60..68f15ba72e 100644 --- a/src/shared/bodies/base_body.h +++ b/src/shared/bodies/base_body.h @@ -134,46 +134,40 @@ class SPHBody return level_set_shape; }; - /** partial construct particles with an already constructed material */ - template - void defineParticlesWithMaterial(MaterialType *material) + template + void assignMaterial(MaterialType *material) { base_material_ = material; - base_particles_ = base_particles_ptr_keeper_.createPtr(*this, material); }; - /** partial construct particles with material informaiton. note that particle data not initialized yet */ - template - void defineParticlesAndMaterial(Args &&...args) + template + MaterialType *defineMaterial(Args &&...args) { MaterialType *material = base_material_ptr_keeper_.createPtr(std::forward(args)...); - defineParticlesWithMaterial(material); + assignMaterial(material); + return material; }; //---------------------------------------------------------------------- // Particle generating methods // Initialize particle data using a particle generator for geometric data. // The local material parameters are also initialized. //---------------------------------------------------------------------- - template // for self-defined particle generator - void generateParticles(ParticleGeneratorType &&particle_generator) + template + void generateParticles(Args &&...args) { + base_particles_ = base_particles_ptr_keeper_.createPtr(*this, base_material_); + ParticleGenerator particle_generator(*this, std::forward(args)...); particle_generator.generateParticlesWithBasicVariables(); base_particles_->initializeOtherVariables(); sph_adaptation_->initializeAdaptationVariables(*base_particles_); base_material_->setLocalParameters(sph_system_.ReloadParticles(), base_particles_); }; - // Using predefined particle generator - template - void generateParticles(Args &&...args) - { - ParticleGenerator particle_generator(*this, std::forward(args)...); - generateParticles(particle_generator); - }; + // Buffer or ghost particles can be generated together with real particles - template + template void generateParticlesWithReserve(ReserveType &particle_reserve, Args &&...args) { - generateParticles(particle_reserve, std::forward(args)...); + generateParticles(particle_reserve, std::forward(args)...); }; template @@ -191,7 +185,7 @@ class SPHBody template void addDerivedBodyStateForRecording(Args &&...args) { - base_particles_->template addDerivedVariableToWrite(std::forward(args)...); + base_particles_->template addDerivedVariableToWrite(*this, std::forward(args)...); }; template diff --git a/src/shared/bodies/base_body_part.cpp b/src/shared/bodies/base_body_part.cpp index 22494ba4c0..cec1be9885 100644 --- a/src/shared/bodies/base_body_part.cpp +++ b/src/shared/bodies/base_body_part.cpp @@ -45,7 +45,7 @@ BodyRegionByParticle::BodyRegionByParticle(SPHBody &sph_body, SharedPtr s //=================================================================================================// void BodyRegionByParticle::tagByContain(size_t particle_index) { - if (body_part_shape_.checkContain(base_particles_.pos_[particle_index])) + if (body_part_shape_.checkContain(pos_[particle_index])) { body_part_particles_.push_back(particle_index); } @@ -62,7 +62,7 @@ BodySurface::BodySurface(SPHBody &sph_body) //=================================================================================================// void BodySurface::tagNearSurface(size_t particle_index) { - Real phi = sph_body_.getInitialShape().findSignedDistance(base_particles_.pos_[particle_index]); + Real phi = sph_body_.getInitialShape().findSignedDistance(pos_[particle_index]); if (fabs(phi) < particle_spacing_min_) body_part_particles_.push_back(particle_index); } @@ -78,7 +78,7 @@ BodySurfaceLayer::BodySurfaceLayer(SPHBody &sph_body, Real layer_thickness) //=================================================================================================// void BodySurfaceLayer::tagSurfaceLayer(size_t particle_index) { - Real distance = fabs(sph_body_.getInitialShape().findSignedDistance(base_particles_.pos_[particle_index])); + Real distance = fabs(sph_body_.getInitialShape().findSignedDistance(pos_[particle_index])); if (distance < thickness_threshold_) { body_part_particles_.push_back(particle_index); diff --git a/src/shared/bodies/base_body_part.h b/src/shared/bodies/base_body_part.h index 0986b93873..fc784f667e 100644 --- a/src/shared/bodies/base_body_part.h +++ b/src/shared/bodies/base_body_part.h @@ -45,7 +45,9 @@ class BodyPart { public: BodyPart(SPHBody &sph_body, const std::string &body_part_name) - : sph_body_(sph_body), body_part_name_(body_part_name){}; + : sph_body_(sph_body), body_part_name_(body_part_name), + base_particles_(sph_body.getBaseParticles()), + pos_(*base_particles_.getVariableByName("Position")){}; virtual ~BodyPart(){}; SPHBody &getSPHBody() { return sph_body_; }; @@ -54,6 +56,8 @@ class BodyPart protected: SPHBody &sph_body_; std::string body_part_name_; + BaseParticles &base_particles_; + StdLargeVec &pos_; }; /** @@ -69,7 +73,7 @@ class BodyPartByParticle : public BodyPart size_t SizeOfLoopRange() { return body_part_particles_.size(); }; BodyPartByParticle(SPHBody &sph_body, const std::string &body_part_name) - : BodyPart(sph_body, body_part_name), base_particles_(sph_body.getBaseParticles()), + : BodyPart(sph_body, body_part_name), body_part_bounds_(Vecd::Zero(), Vecd::Zero()), body_part_bounds_set_(false){}; virtual ~BodyPartByParticle(){}; @@ -87,7 +91,6 @@ class BodyPartByParticle : public BodyPart } protected: - BaseParticles &base_particles_; BoundingBox body_part_bounds_; bool body_part_bounds_set_; @@ -131,7 +134,7 @@ class BodyRegionByParticle : public BodyPartByParticle virtual ~BodyRegionByParticle(){}; Shape &getBodyPartShape() { return body_part_shape_; }; - private: + protected: Shape &body_part_shape_; void tagByContain(size_t particle_index); }; @@ -146,7 +149,7 @@ class BodySurface : public BodyPartByParticle explicit BodySurface(SPHBody &sph_body); virtual ~BodySurface(){}; - private: + protected: Real particle_spacing_min_; void tagNearSurface(size_t particle_index); }; @@ -221,6 +224,8 @@ class AlignedBoxRegion : public BodyRegionType public: AlignedBoxShape &aligned_box_; + AlignedBoxRegion(RealBody &real_body, AlignedBoxShape &aligned_box) + : BodyRegionType(real_body, aligned_box), aligned_box_(aligned_box){}; AlignedBoxRegion(RealBody &real_body, SharedPtr aligned_box_ptr) : BodyRegionType(real_body, aligned_box_ptr), aligned_box_(*aligned_box_ptr.get()){}; virtual ~AlignedBoxRegion(){}; diff --git a/src/shared/bodies/complex_bodies/mesh_helper.h b/src/shared/bodies/complex_bodies/mesh_helper.h index eac0f8b9db..5de292066d 100644 --- a/src/shared/bodies/complex_bodies/mesh_helper.h +++ b/src/shared/bodies/complex_bodies/mesh_helper.h @@ -20,67 +20,67 @@ * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * * * * ------------------------------------------------------------------------- */ - /** - * @file MeshHelper.h - * @brief Here, we define the functions used for reading the mesh data. - * @author Yash Mandaokar Zhentong Wang and Xiangyu Hu - */ -#ifndef MESHTYPE_H -#define MESHTYPE_H +/** + * @file mesh_helper.h + * @brief Here, we define the functions used for reading the mesh data. + * @author Yash Mandaokar Zhentong Wang and Xiangyu Hu + */ +#ifndef MESH_HELPER_H +#define MESH_HELPER_H #include "unstructured_mesh.h" -using namespace std; -namespace SPH -{ - class MeshFileHelpers - { - public: +#include +#include +#include +#include - MeshFileHelpers() - { - - }; - virtual ~MeshFileHelpers(){}; +namespace SPH +{ - static void meshDimension(ifstream& mesh_file, size_t& dimension, string& text_line); - static void numberofNodes(ifstream& mesh_file, size_t& number_of_points, string& text_line); - static void nodeCoordinates(ifstream& mesh_file, StdLargeVec& node_coordinates_, string& text_line,size_t& dimension); - static void numberofElements(ifstream& mesh_file, size_t& number_of_elements, string& text_line); - static void dataStruct(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - size_t number_of_elements, size_t mesh_type, size_t dimension); - static size_t findBoundaryType(string& text_line, size_t boundary_type); - static Vecd nodeIndex(string& text_line); - static Vec2d cellIndex(string& text_line); - static void updateElementsNodesConnection(StdLargeVec>& elements_nodes_connection_, Vecd nodes, Vec2d cells, - bool& check_neighbor_cell1, bool& check_neighbor_cell2); - static void updateCellLists(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, Vecd nodes, - Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type); - static void updateBoundaryCellLists(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - Vecd nodes, Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type); - static void cellCenterCoordinates(StdLargeVec>& elements_nodes_connection_, std::size_t& element, - StdLargeVec& node_coordinates_, StdLargeVec& elements_center_coordinates_, Vecd& center_coordinate); - static void elementVolume(StdLargeVec>& elements_nodes_connection_, std::size_t& element, - StdLargeVec& node_coordinates_, StdLargeVec& elements_volumes_); - static void minimumdistance(vector& all_data_of_distance_between_nodes, StdLargeVec& elements_volumes_, - vector>>& mesh_topology_, StdLargeVec& node_coordinates_); - static void vtuFileHeader(std::ofstream& out_file); - static void vtuFileNodeCoordinates(std::ofstream& out_file, StdLargeVec& nodes_coordinates_, - StdLargeVec>& elements_nodes_connection_, SPHBody& bounds_,Real& rangemax); - static void vtuFileInformationKey(std::ofstream& out_file, Real& rangemax); - static void vtuFileCellConnectivity(std::ofstream& out_file, StdLargeVec>& elements_nodes_connection_, StdLargeVec& node_coordinates_); - static void vtuFileOffsets(std::ofstream& out_file, StdLargeVec>& elements_nodes_connection_); - static void vtuFileTypeOfCell(std::ofstream& out_file, StdLargeVec>& elements_nodes_connection_); +class MeshFileHelpers +{ + public: + MeshFileHelpers(){}; + virtual ~MeshFileHelpers(){}; - /*Functions for .msh file from FLUENT*/ - static void numberofNodesFluent(ifstream& mesh_file, size_t& number_of_points, string& text_line); - static void numberofElementsFluent(ifstream& mesh_file, size_t& number_of_elements, string& text_line); - static void nodeCoordinatesFluent(ifstream& mesh_file, StdLargeVec& node_coordinates_, string& text_line, - size_t& dimension); - static void updateBoundaryCellListsFluent(vector>>& mesh_topology_, StdLargeVec>& elements_nodes_connection_, - Vecd nodes, Vec2d cells, bool& check_neighbor_cell1, bool& check_neighbor_cell2, size_t boundary_type); - }; + static void meshDimension(std::ifstream &mesh_file, size_t &dimension, std::string &text_line); + static void numberOfNodes(std::ifstream &mesh_file, size_t &number_of_points, std::string &text_line); + static void nodeCoordinates(std::ifstream &mesh_file, StdLargeVec &node_coordinates_, std::string &text_line, size_t &dimension); + static void numberOfElements(std::ifstream &mesh_file, size_t &number_of_elements, std::string &text_line); + static void dataStruct(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, + size_t number_of_elements, size_t mesh_type, size_t dimension); + static size_t findBoundaryType(std::string &text_line, size_t boundary_type); + static Vecd nodeIndex(std::string &text_line); + static Vec2d cellIndex(std::string &text_line); + static void updateElementsNodesConnection(StdLargeVec> &elements_nodes_connection_, Vecd nodes, Vec2d cells, + bool &check_neighbor_cell1, bool &check_neighbor_cell2); + static void updateCellLists(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, Vecd nodes, + Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type); + static void updateBoundaryCellLists(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, + Vecd nodes, Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type); + static void cellCenterCoordinates(StdLargeVec> &elements_nodes_connection_, std::size_t &element, + StdLargeVec &node_coordinates_, StdLargeVec &elements_center_coordinates_, Vecd ¢er_coordinate); + static void elementVolume(StdLargeVec> &elements_nodes_connection_, std::size_t &element, + StdLargeVec &node_coordinates_, StdLargeVec &elements_volumes_); + static void minimumDistance(StdVec &all_data_of_distance_between_nodes, StdLargeVec &elements_volumes_, + StdVec>> &mesh_topology_, StdLargeVec &node_coordinates_); + static void vtuFileHeader(std::ofstream &out_file); + static void vtuFileNodeCoordinates(std::ofstream &out_file, StdLargeVec &nodes_coordinates_, + StdLargeVec> &elements_nodes_connection_, SPHBody &bounds_, Real &range_max); + static void vtuFileInformationKey(std::ofstream &out_file, Real &range_max); + static void vtuFileCellConnectivity(std::ofstream &out_file, StdLargeVec> &elements_nodes_connection_, StdLargeVec &node_coordinates_); + static void vtuFileOffsets(std::ofstream &out_file, StdLargeVec> &elements_nodes_connection_); + static void vtuFileTypeOfCell(std::ofstream &out_file, StdLargeVec> &elements_nodes_connection_); + /*Functions for .msh file from FLUENT*/ + static void numberOfNodesFluent(std::ifstream &mesh_file, size_t &number_of_points, std::string &text_line); + static void numberOfElementsFluent(std::ifstream &mesh_file, size_t &number_of_elements, std::string &text_line); + static void nodeCoordinatesFluent(std::ifstream &mesh_file, StdLargeVec &node_coordinates_, std::string &text_line, + size_t &dimension); + static void updateBoundaryCellListsFluent(StdVec>> &mesh_topology_, StdLargeVec> &elements_nodes_connection_, + Vecd nodes, Vec2d cells, bool &check_neighbor_cell1, bool &check_neighbor_cell2, size_t boundary_type); +}; -} -#endif // MESHTYPE_H \ No newline at end of file +} // namespace SPH +#endif // MESH_HELPER_H \ No newline at end of file diff --git a/src/shared/bodies/complex_bodies/tree_body.cpp b/src/shared/bodies/complex_bodies/tree_body.cpp index 33b77a1770..a83c7215f2 100644 --- a/src/shared/bodies/complex_bodies/tree_body.cpp +++ b/src/shared/bodies/complex_bodies/tree_body.cpp @@ -3,7 +3,7 @@ #include "adaptation.h" #include "base_material.h" #include "base_particle_dynamics.h" -#include "base_particles.h" +#include "base_particles.hpp" #include "neighborhood.h" namespace SPH @@ -20,7 +20,7 @@ void TreeBody::buildParticleConfiguration(ParticleConfiguration &particle_config neighboring_ids.push_back(branches_[1]->inner_particles_[0]); neighboring_ids.push_back(branches_[1]->inner_particles_[1]); /** Build configuration. */ - const StdLargeVec &pos = base_particles_->pos_; + const StdLargeVec &pos = base_particles_->ParticlePositions(); NeighborBuilderInner neighbor_relation_inner(*this); for (size_t n = 0; n != neighboring_ids.size(); ++n) { diff --git a/src/shared/bodies/complex_bodies/unstructured_mesh.cpp b/src/shared/bodies/complex_bodies/unstructured_mesh.cpp new file mode 100644 index 0000000000..3a3a969330 --- /dev/null +++ b/src/shared/bodies/complex_bodies/unstructured_mesh.cpp @@ -0,0 +1,19 @@ + +#include "unstructured_mesh.h" + +#include "base_particle_dynamics.h" + +namespace SPH +{ +//=================================================================================================// +BaseInnerRelationInFVM::BaseInnerRelationInFVM(RealBody &real_body, ANSYSMesh &ansys_mesh) + : BaseInnerRelation(real_body), real_body_(&real_body), + node_coordinates_(ansys_mesh.node_coordinates_), + mesh_topology_(ansys_mesh.mesh_topology_), + Vol_(*base_particles_.getVariableByName("VolumetricMeasure")) +{ + subscribeToBody(); + inner_configuration_.resize(base_particles_.real_particles_bound_, Neighborhood()); +}; +//=============================================================================================// +} // namespace SPH diff --git a/src/shared/bodies/complex_bodies/unstructured_mesh.h b/src/shared/bodies/complex_bodies/unstructured_mesh.h index 3a86aeeed2..23a98ba734 100644 --- a/src/shared/bodies/complex_bodies/unstructured_mesh.h +++ b/src/shared/bodies/complex_bodies/unstructured_mesh.h @@ -28,13 +28,8 @@ #ifndef UNSTRUCTURED_MESH_H #define UNSTRUCTURED_MESH_H -#include "base_fluid_dynamics.h" -#include "base_particle_generator.h" -#include "compressible_fluid.h" -#include "fluid_body.h" -#include "io_vtk.h" -#include -using namespace std; +#include "base_body_relation.h" + namespace SPH { /** @@ -52,7 +47,7 @@ class ANSYSMesh StdLargeVec elements_centroids_; StdLargeVec elements_volumes_; StdLargeVec> elements_nodes_connection_; - vector>> mesh_topology_; + StdVec>> mesh_topology_; Real MinMeshEdge() { return min_distance_between_nodes_; } protected: @@ -69,16 +64,17 @@ class ANSYSMesh */ class BaseInnerRelationInFVM : public BaseInnerRelation { - protected: - virtual void resetNeighborhoodCurrentSize() override; - public: RealBody *real_body_; StdLargeVec &node_coordinates_; - vector>> &mesh_topology_; + StdVec>> &mesh_topology_; explicit BaseInnerRelationInFVM(RealBody &real_body, ANSYSMesh &ansys_mesh); virtual ~BaseInnerRelationInFVM(){}; + + protected: + StdLargeVec &Vol_; + virtual void resetNeighborhoodCurrentSize() override; }; /** @@ -147,88 +143,5 @@ class InnerRelationInFVM : public BaseInnerRelationInFVM virtual void updateConfiguration() override; }; -/** - * @class BaseGhostCreation - * @brief Base class for the ghost particle - */ -class GhostCreationFromMesh : public GeneralDataDelegateSimple -{ - public: - GhostCreationFromMesh(RealBody &real_body, ANSYSMesh &ansys_mesh, - Ghost &ghost_boundary); - virtual ~GhostCreationFromMesh(){}; - - protected: - Ghost &ghost_boundary_; - std::mutex mutex_create_ghost_particle_; /**< mutex exclusion for memory conflict */ - StdLargeVec &node_coordinates_; - vector>> &mesh_topology_; - StdLargeVec &pos_; - StdLargeVec &Vol_; - void addGhostParticleAndSetInConfiguration(); - - public: - std::pair &ghost_bound_; - vector> each_boundary_type_with_all_ghosts_index_; - vector> each_boundary_type_with_all_ghosts_eij_; - vector> each_boundary_type_contact_real_index_; -}; - -/** - * @class BodyStatesRecordingInMeshToVtp - * @brief Write files for bodies - * the output file is VTK XML format in FVMcan visualized by ParaView the data type vtkPolyData - */ -class BodyStatesRecordingInMeshToVtp : public BodyStatesRecording -{ - public: - BodyStatesRecordingInMeshToVtp(SPHBody &body, ANSYSMesh &ansys_mesh); - virtual ~BodyStatesRecordingInMeshToVtp(){}; - - protected: - virtual void writeWithFileName(const std::string &sequence) override; - StdLargeVec &node_coordinates_; - StdLargeVec>&elements_nodes_connection_; -}; -class BodyStatesRecordingInMeshToVtu : public BodyStatesRecording -{ -public: - BodyStatesRecordingInMeshToVtu(SPHBody& body, ANSYSMesh& ansys_mesh); - virtual ~BodyStatesRecordingInMeshToVtu() {}; - -protected: - virtual void writeWithFileName(const std::string& sequence) override; - StdLargeVec& node_coordinates_; - StdLargeVec>& elements_nodes_connection_; - SPHBody& bounds_; -}; -//---------------------------------------------------------------------- -// BoundaryConditionSetupInFVM -//---------------------------------------------------------------------- -class BoundaryConditionSetupInFVM : public fluid_dynamics::FluidDataInner -{ - public: - BoundaryConditionSetupInFVM(BaseInnerRelationInFVM &inner_relation, GhostCreationFromMesh &ghost_creation); - virtual ~BoundaryConditionSetupInFVM(){}; - virtual void applyReflectiveWallBoundary(size_t ghost_index, size_t index_i, Vecd e_ij){}; - virtual void applyNonSlipWallBoundary(size_t ghost_index, size_t index_i){}; - virtual void applyGivenValueInletFlow(size_t ghost_index){}; - virtual void applyOutletBoundary(size_t ghost_index, size_t index_i){}; - virtual void applyTopBoundary(size_t ghost_index, size_t index_i){}; - virtual void applyFarFieldBoundary(size_t ghost_index){}; - virtual void applyPressureOutletBC(size_t ghost_index, size_t index_i) {}; - virtual void applySymmetryBoundary(size_t ghost_index, size_t index_i, Vecd e_ij) {}; - virtual void applyVelocityInletFlow(size_t ghost_index, size_t index_i) {}; - // Common functionality for resetting boundary conditions - void resetBoundaryConditions(); - - protected: - StdLargeVec &rho_, &Vol_, &mass_, &p_; - StdLargeVec &vel_, &pos_, &mom_; - std::pair &ghost_bound_; - vector> &each_boundary_type_with_all_ghosts_index_; - vector> &each_boundary_type_with_all_ghosts_eij_; - vector> &each_boundary_type_contact_real_index_; -}; } // namespace SPH #endif // UNSTRUCTURED_MESH_H \ No newline at end of file diff --git a/src/shared/bodies/observer_body.h b/src/shared/bodies/observer_body.h index 2edb389e86..7760ec1bca 100644 --- a/src/shared/bodies/observer_body.h +++ b/src/shared/bodies/observer_body.h @@ -46,7 +46,6 @@ class ObserverBody : public SPHBody template ObserverBody(Args &&...args) : SPHBody(std::forward(args)...) { - defineParticlesAndMaterial(); sph_system_.observation_bodies_.push_back(this); }; virtual ~ObserverBody(){}; diff --git a/src/shared/bodies/solid_body.cpp b/src/shared/bodies/solid_body.cpp index ab56e0be74..9f6aec4179 100644 --- a/src/shared/bodies/solid_body.cpp +++ b/src/shared/bodies/solid_body.cpp @@ -1,6 +1,7 @@ #include "solid_body.h" + #include "base_material.h" -#include "solid_particles.h" +#include "base_particles.hpp" #include "sph_system.h" namespace SPH @@ -9,8 +10,9 @@ namespace SPH SolidBodyPartForSimbody:: SolidBodyPartForSimbody(SPHBody &body, Shape &body_part_shape) : BodyRegionByParticle(body, body_part_shape), - solid_body_density_(DynamicCast(this, body.base_material_)->ReferenceDensity()), - solid_particles_(DynamicCast(this, &body.getBaseParticles())) + rho0_(DynamicCast(this, body.base_material_)->ReferenceDensity()), + Vol_(*base_particles_.getVariableByName("VolumetricMeasure")), + pos_(*base_particles_.getVariableByName("Position")) { setMassProperties(); } diff --git a/src/shared/bodies/solid_body.h b/src/shared/bodies/solid_body.h index a277d37584..b4b4eb237f 100644 --- a/src/shared/bodies/solid_body.h +++ b/src/shared/bodies/solid_body.h @@ -38,7 +38,7 @@ namespace SPH * @brief pre-claimed class. */ class SPHSystem; -class SolidParticles; +class BaseParticles; /** * @class SolidBody * @brief Declaration of solid body which is used for Solid BCs and derived from RealBody. @@ -77,8 +77,9 @@ class SolidBodyPartForSimbody : public BodyRegionByParticle virtual ~SolidBodyPartForSimbody(){}; protected: - Real solid_body_density_; - SolidParticles *solid_particles_; + Real rho0_; + StdLargeVec &Vol_; + StdLargeVec &pos_; private: void setMassProperties(); diff --git a/src/shared/body_relations/base_body_relation.cpp b/src/shared/body_relations/base_body_relation.cpp index e560ffc2fb..3d58de935d 100644 --- a/src/shared/body_relations/base_body_relation.cpp +++ b/src/shared/body_relations/base_body_relation.cpp @@ -16,7 +16,9 @@ RealBodyVector BodyPartsToRealBodies(BodyPartVector body_parts) } //=================================================================================================// SPHRelation::SPHRelation(SPHBody &sph_body) - : sph_body_(sph_body), base_particles_(sph_body.getBaseParticles()) {} + : sph_body_(sph_body), + base_particles_(sph_body.getBaseParticles()), + pos_(*base_particles_.getVariableByName("Position")) {} //=================================================================================================// BaseInnerRelation::BaseInnerRelation(RealBody &real_body) : SPHRelation(real_body), real_body_(&real_body) diff --git a/src/shared/body_relations/base_body_relation.h b/src/shared/body_relations/base_body_relation.h index 421a67bb2a..8c2a945052 100644 --- a/src/shared/body_relations/base_body_relation.h +++ b/src/shared/body_relations/base_body_relation.h @@ -105,17 +105,18 @@ RealBodyVector BodyPartsToRealBodies(BodyPartVector body_parts); */ class SPHRelation { - protected: - SPHBody &sph_body_; - public: - BaseParticles &base_particles_; SPHBody &getSPHBody() { return sph_body_; }; explicit SPHRelation(SPHBody &sph_body); virtual ~SPHRelation(){}; void subscribeToBody() { sph_body_.body_relations_.push_back(this); }; virtual void updateConfiguration() = 0; + + protected: + SPHBody &sph_body_; + BaseParticles &base_particles_; + StdLargeVec &pos_; }; /** diff --git a/src/shared/common/base_data_type.h b/src/shared/common/base_data_type.h index 7b5e226359..92c2f477cc 100644 --- a/src/shared/common/base_data_type.h +++ b/src/shared/common/base_data_type.h @@ -116,6 +116,13 @@ struct ZeroData { static inline int value = 0; }; + +template +struct IdentityMatrix +{ + static inline DataType value = DataType::Identity(); +}; + /** Type trait for data type index. */ template struct DataTypeIndex diff --git a/src/shared/io_system/io_all.h b/src/shared/io_system/io_all.h index a29b05b7f3..066a8153ba 100644 --- a/src/shared/io_system/io_all.h +++ b/src/shared/io_system/io_all.h @@ -32,5 +32,6 @@ io class used in SPHinXsys. **/ #include "io_plt.h" #include "io_simbody.h" #include "io_vtk.h" +#include "io_vtk_fvm.h" #endif // IO_ALL_H diff --git a/src/shared/io_system/io_vtk.cpp b/src/shared/io_system/io_vtk.cpp index 210f1a1c80..1eb4b22d5b 100644 --- a/src/shared/io_system/io_vtk.cpp +++ b/src/shared/io_system/io_vtk.cpp @@ -40,7 +40,7 @@ void BodyStatesRecordingToVtp::writeWithFileName(const std::string &sequence) out_file << " "; for (size_t i = 0; i != total_real_particles; ++i) { - Vec3d particle_position = upgradeToVec3d(base_particles.pos_[i]); + Vec3d particle_position = upgradeToVec3d(base_particles.ParticlePositions()[i]); out_file << particle_position[0] << " " << particle_position[1] << " " << particle_position[2] << " "; } out_file << std::endl; diff --git a/src/shared/io_system/io_vtk_fvm.cpp b/src/shared/io_system/io_vtk_fvm.cpp new file mode 100644 index 0000000000..95a535336f --- /dev/null +++ b/src/shared/io_system/io_vtk_fvm.cpp @@ -0,0 +1,14 @@ +#include "io_vtk_fvm.h" + +namespace SPH +{ +//=================================================================================================// +BodyStatesRecordingInMeshToVtp::BodyStatesRecordingInMeshToVtp(SPHBody &body, ANSYSMesh &ansys_mesh) + : BodyStatesRecording(body), node_coordinates_(ansys_mesh.node_coordinates_), + elements_nodes_connection_(ansys_mesh.elements_nodes_connection_) {} +//=================================================================================================// +BodyStatesRecordingInMeshToVtu::BodyStatesRecordingInMeshToVtu(SPHBody &body, ANSYSMesh &ansys_mesh) + : BodyStatesRecording(body), node_coordinates_(ansys_mesh.node_coordinates_), + elements_nodes_connection_(ansys_mesh.elements_nodes_connection_), bounds_(body){}; +//=================================================================================================// +} // namespace SPH diff --git a/tests/extra_source_and_tests/extra_src/shared/porous_solid_particles.h b/src/shared/io_system/io_vtk_fvm.h similarity index 50% rename from tests/extra_source_and_tests/extra_src/shared/porous_solid_particles.h rename to src/shared/io_system/io_vtk_fvm.h index 035e24ae03..0a61e32bd0 100644 --- a/tests/extra_source_and_tests/extra_src/shared/porous_solid_particles.h +++ b/src/shared/io_system/io_vtk_fvm.h @@ -21,50 +21,47 @@ * * * ------------------------------------------------------------------------- */ /** - * @file solid_particles.h - * @brief This is the derived class of base particles. - * @author Chi ZHang, Dong Wu and Xiangyu Hu + * @file io_vtk_fvm.h + * @brief Classes for input and output with vtk (Paraview) for FVM unstructured mesh. + * @author Xiangyu Hu */ -#ifndef POROUS_SOLID_PARTICLES_H -#define POROUS_SOLID_PARTICLES_H +#ifndef IO_VTK_FVM_H +#define IO_VTK_FVM_H + +#include "io_vtk.h" +#include "unstructured_mesh.h" -#include "solid_particles.h" -#include "porous_media_solid.h" - namespace SPH { -namespace multi_species_continuum -{ - /** - * @class PorousMediaParticles - * @brief A group of particles with elastic body particle data. + * @class BodyStatesRecordingInMeshToVtp + * @brief Write files for bodies + * the output file is VTK XML format in FVMcan visualized by ParaView the data type vtkPolyData */ - class PorousMediaParticles : public ElasticSolidParticles - { - public: - PorousMediaParticles(SPHBody &body, PorousMediaSolid *porous_solid); - PorousMediaSolid &porous_solid_; - virtual ~PorousMediaParticles() {}; +class BodyStatesRecordingInMeshToVtp : public BodyStatesRecording +{ + public: + BodyStatesRecordingInMeshToVtp(SPHBody &body, ANSYSMesh &ansys_mesh); + virtual ~BodyStatesRecordingInMeshToVtp(){}; - StdLargeVec fluid_velocity_; /**< fluid velocity */ - StdLargeVec relative_fluid_flux_; /**< fluid flux through the boundary of solid unit */ - StdLargeVec fluid_saturation_; /**< fluid content quantity in solid */ + protected: + virtual void writeWithFileName(const std::string &sequence) override; // TODO: to be implemented in 3d + StdLargeVec &node_coordinates_; + StdLargeVec> &elements_nodes_connection_; +}; +class BodyStatesRecordingInMeshToVtu : public BodyStatesRecording +{ + public: + BodyStatesRecordingInMeshToVtu(SPHBody &body, ANSYSMesh &ansys_mesh); + virtual ~BodyStatesRecordingInMeshToVtu(){}; - StdLargeVec Vol_update_; /**< solid volume */ - StdLargeVec dfluid_mass_dt_; /**< fluid mass time gradient in solid */ - StdLargeVec fluid_mass_; /**< fluid mass in solid */ - StdLargeVec total_mass_; /**< total mass containing fluid mass and solid mass */ - StdLargeVec total_momentum_; /**< total momentum consists of fluid momentum and solid momentum */ - StdLargeVec dtotal_momentum_dt_; /**< total momentum time gradient */ - StdLargeVec outer_fluid_velocity_relative_fluid_flux_; /**< outer product of fluid veolcity and fluid flux */ - StdLargeVec Stress_; /**< Cauchy stress on solid */ - - virtual void initializeOtherVariables() override; - virtual ElasticSolidParticles *ThisObjectPtr() override { return this; }; - }; -} + protected: + virtual void writeWithFileName(const std::string &sequence) override; // TODO: to be implemented in 2d + StdLargeVec &node_coordinates_; + StdLargeVec> &elements_nodes_connection_; + SPHBody &bounds_; +}; } // namespace SPH -#endif // POROUS_SOLID_PARTICLES_H +#endif // IO_VTK_FVM_H diff --git a/src/shared/materials/base_material.cpp b/src/shared/materials/base_material.cpp index 4e126df160..ad7eb5d5a8 100644 --- a/src/shared/materials/base_material.cpp +++ b/src/shared/materials/base_material.cpp @@ -20,10 +20,14 @@ Fluid::Fluid(Real rho0, Real c0, Real mu) material_type_name_ = "Fluid"; } //=================================================================================================// -void Fluid::initializeLocalParameters(BaseParticles *base_particles) +StdLargeVec *Solid::AverageVelocity(BaseParticles *base_particles) { - BaseMaterial::initializeLocalParameters(base_particles); - base_particles->registerSharedVariable("Pressure", getPressure(rho0_)); + return base_particles->registerSharedVariable("Velocity"); +} +//=================================================================================================// +StdLargeVec *Solid::AverageAcceleration(BaseParticles *base_particles) +{ + return base_particles->registerSharedVariable("Acceleration"); } //=================================================================================================// } // namespace SPH diff --git a/src/shared/materials/base_material.h b/src/shared/materials/base_material.h index 85cc9a324c..7f7a60e3ef 100644 --- a/src/shared/materials/base_material.h +++ b/src/shared/materials/base_material.h @@ -94,7 +94,6 @@ class Fluid : public BaseMaterial virtual Real DensityFromPressure(Real p) = 0; virtual Real getSoundSpeed(Real p = 0.0, Real rho = 1.0) = 0; virtual Fluid *ThisObjectPtr() override { return this; }; - virtual void initializeLocalParameters(BaseParticles *base_particles) override; }; /** @class Solid @@ -116,6 +115,10 @@ class Solid : public BaseMaterial Real ContactFriction() { return contact_friction_; }; Real ContactStiffness() { return contact_stiffness_; }; virtual Solid *ThisObjectPtr() override { return this; }; + /** Get average velocity when interacting with fluid. */ + virtual StdLargeVec *AverageVelocity(BaseParticles *base_particles); + /** Get average acceleration when interacting with fluid. */ + virtual StdLargeVec *AverageAcceleration(BaseParticles *base_particles); protected: Real contact_stiffness_; /**< contact-force stiffness related to bulk modulus*/ diff --git a/src/shared/materials/complex_solid.cpp b/src/shared/materials/complex_solid.cpp index e166df2f78..864c28b485 100644 --- a/src/shared/materials/complex_solid.cpp +++ b/src/shared/materials/complex_solid.cpp @@ -48,8 +48,8 @@ void CompositeSolid::initializeLocalParameters(BaseParticles *base_particles) } //=================================================================================================// MaterialIdInitialization::MaterialIdInitialization(SPHBody &sph_body) - : LocalDynamics(sph_body), GeneralDataDelegateSimple(sph_body), + : LocalDynamics(sph_body), DataDelegateSimple(sph_body), material_id_(*particles_->getVariableByName("MaterialID")), - pos0_(*particles_->getVariableByName("InitialPosition")){}; + pos_(*particles_->getVariableByName("Position")){}; //=================================================================================================// } // namespace SPH diff --git a/src/shared/materials/complex_solid.h b/src/shared/materials/complex_solid.h index 0b8be4e9b6..2e5fd3b160 100644 --- a/src/shared/materials/complex_solid.h +++ b/src/shared/materials/complex_solid.h @@ -29,8 +29,8 @@ #ifndef COMPLEX_SOLID_H #define COMPLEX_SOLID_H -#include "elastic_solid.h" #include "base_general_dynamics.h" +#include "elastic_solid.h" namespace SPH { @@ -96,14 +96,14 @@ class CompositeSolid : public ElasticSolid */ class MaterialIdInitialization : public LocalDynamics, - public GeneralDataDelegateSimple + public DataDelegateSimple { public: explicit MaterialIdInitialization(SPHBody &sph_body); protected: StdLargeVec &material_id_; - StdLargeVec &pos0_; + StdLargeVec &pos_; }; } // namespace SPH #endif // COMPLEX_SOLID_H diff --git a/src/shared/materials/diffusion_reaction.cpp b/src/shared/materials/diffusion_reaction.cpp index fef56ffa64..5e459506e7 100644 --- a/src/shared/materials/diffusion_reaction.cpp +++ b/src/shared/materials/diffusion_reaction.cpp @@ -4,19 +4,87 @@ namespace SPH { //=================================================================================================// -void LocalIsotropicDiffusion::initializeLocalParameters(BaseParticles* base_particles) +BaseDiffusion::BaseDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name) + : BaseMaterial(), + diffusion_species_name_(diffusion_species_name), + gradient_species_name_(gradient_species_name) { - base_particles->registerVariable(local_thermal_conductivity_, "ThermalConductivity", [&](size_t i) -> Real {return diff_cf_; }); + material_type_name_ = "BaseDiffusion"; +} +//=================================================================================================// +BaseDiffusion::BaseDiffusion(const std::string &species_name) + : BaseDiffusion(species_name, species_name) {} +//=================================================================================================// +Real BaseDiffusion::getDiffusionTimeStepSize(Real smoothing_length) +{ + return 0.5 * smoothing_length * smoothing_length / getReferenceDiffusivity() / Real(Dimensions); +} +//=================================================================================================// +IsotropicDiffusion::IsotropicDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf) + : BaseDiffusion(diffusion_species_name, gradient_species_name), + diff_cf_(diff_cf) +{ + material_type_name_ = "IsotropicDiffusion"; +} +//=================================================================================================// +IsotropicDiffusion::IsotropicDiffusion(const std::string &species_name, Real diff_cf) + : IsotropicDiffusion(species_name, species_name, diff_cf) {} +//=================================================================================================// +LocalIsotropicDiffusion::LocalIsotropicDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf) + : IsotropicDiffusion(diffusion_species_name, gradient_species_name, diff_cf) +{ + material_type_name_ = "LocalIsotropicDiffusion"; +} +//=================================================================================================// +LocalIsotropicDiffusion::LocalIsotropicDiffusion(const std::string &species_name, Real diff_cf) + : LocalIsotropicDiffusion(species_name, species_name, diff_cf) {} +//=================================================================================================// +void LocalIsotropicDiffusion::initializeLocalParameters(BaseParticles *base_particles) +{ + base_particles->registerVariable(local_diffusivity_, "ThermalConductivity", [&](size_t i) -> Real { return diff_cf_; }); base_particles->addVariableToWrite("ThermalConductivity"); } //=================================================================================================// +DirectionalDiffusion::DirectionalDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction) + : IsotropicDiffusion(diffusion_species_name, gradient_species_name, diff_cf), + bias_direction_(bias_direction), bias_diff_cf_(bias_diff_cf), + transformed_diffusivity_(Matd::Identity()) +{ + material_type_name_ = "DirectionalDiffusion"; + initializeDirectionalDiffusivity(diff_cf, bias_diff_cf, bias_direction); +} +//=================================================================================================// +DirectionalDiffusion::DirectionalDiffusion(const std::string &species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction) + : DirectionalDiffusion(species_name, species_name, diff_cf, bias_diff_cf, bias_direction) {} +//=================================================================================================// void DirectionalDiffusion::initializeDirectionalDiffusivity(Real diff_cf, Real bias_diff_cf, Vecd bias_direction) { bias_diff_cf_ = bias_diff_cf; bias_direction_ = bias_direction; Matd diff_i = diff_cf_ * Matd::Identity() + bias_diff_cf_ * bias_direction_ * bias_direction_.transpose(); transformed_diffusivity_ = inverseCholeskyDecomposition(diff_i); -}; +} +//=================================================================================================// +LocalDirectionalDiffusion::LocalDirectionalDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction) + : DirectionalDiffusion(diffusion_species_name, gradient_species_name, + diff_cf, bias_diff_cf, bias_direction) +{ + material_type_name_ = "LocalDirectionalDiffusion"; +} +//=================================================================================================// +LocalDirectionalDiffusion::LocalDirectionalDiffusion(const std::string &species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction) + : LocalDirectionalDiffusion(species_name, species_name, diff_cf, bias_diff_cf, bias_direction) {} //=================================================================================================// void LocalDirectionalDiffusion::registerReloadLocalParameters(BaseParticles *base_particles) { @@ -29,9 +97,9 @@ void LocalDirectionalDiffusion::initializeLocalParameters(BaseParticles *base_pa DirectionalDiffusion::initializeLocalParameters(base_particles); base_particles->registerVariable( local_transformed_diffusivity_, "LocalTransformedDiffusivity", - [&](size_t i) -> Matd - { - Matd diff_i = diff_cf_ * Matd::Identity() + bias_diff_cf_ * local_bias_direction_[i] * local_bias_direction_[i].transpose(); + [&](size_t i) -> Matd { + Matd diff_i = diff_cf_ * Matd::Identity() + + bias_diff_cf_ * local_bias_direction_[i] * local_bias_direction_[i].transpose(); return inverseCholeskyDecomposition(diff_i); }); diff --git a/src/shared/materials/diffusion_reaction.h b/src/shared/materials/diffusion_reaction.h index 6ab5185df8..b6dcef6ebb 100644 --- a/src/shared/materials/diffusion_reaction.h +++ b/src/shared/materials/diffusion_reaction.h @@ -21,11 +21,11 @@ * * * ------------------------------------------------------------------------- */ /** - * @file diffusion_reaction.h - * @brief Describe the diffusive and reaction in which - * the dynamics is characterized by diffusion equation and reactive source terms. - * Typical physical processes are diffusion, heat conduction - * and chemical and biological reactions. + * @file diffusion_reaction.h + * @brief Describe the diffusive and reaction in which + * the dynamics is characterized by diffusion equation and reactive source terms. + * Typical physical processes are diffusion, heat conduction + * and chemical and biological reactions. */ #ifndef DIFFUSION_REACTION_H @@ -46,20 +46,21 @@ namespace SPH class BaseDiffusion : public BaseMaterial { public: - BaseDiffusion(size_t diffusion_species_index, size_t gradient_species_index) - : BaseMaterial(), diffusion_species_index_(diffusion_species_index), - gradient_species_index_(gradient_species_index) - { - material_type_name_ = "BaseDiffusion"; - }; + BaseDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name); + BaseDiffusion(const std::string &species_name); virtual ~BaseDiffusion(){}; - size_t diffusion_species_index_; - size_t gradient_species_index_; - + std::string DiffusionSpeciesName() { return diffusion_species_name_; }; + std::string GradientSpeciesName() { return gradient_species_name_; }; + Real getDiffusionTimeStepSize(Real smoothing_length); virtual Real getReferenceDiffusivity() = 0; - virtual Real getDiffusionCoeffWithBoundary(size_t particle_i) = 0; - virtual Real getInterParticleDiffusionCoeff(size_t particle_i, size_t particle_j, const Vecd &direction_from_j_to_i) = 0; + virtual Real getDiffusionCoeffWithBoundary(size_t index_i) = 0; + virtual Real getInterParticleDiffusionCoeff(size_t index_i, size_t index_j, const Vecd &e_ij) = 0; + + protected: + std::string diffusion_species_name_; + std::string gradient_species_name_; }; /** @@ -72,18 +73,15 @@ class IsotropicDiffusion : public BaseDiffusion Real diff_cf_; /**< diffusion coefficient. */ public: - IsotropicDiffusion(size_t diffusion_species_index, size_t gradient_species_index, - Real diff_cf = 1.0) - : BaseDiffusion(diffusion_species_index, gradient_species_index), - diff_cf_(diff_cf) - { - material_type_name_ = "IsotropicDiffusion"; - }; + IsotropicDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf = 1.0); + IsotropicDiffusion(const std::string &species_name, Real diff_cf = 1.0); virtual ~IsotropicDiffusion(){}; virtual Real getReferenceDiffusivity() override { return diff_cf_; }; - virtual Real getDiffusionCoeffWithBoundary(size_t particle_i) override { return diff_cf_; } - virtual Real getInterParticleDiffusionCoeff(size_t particle_i, size_t particle_j, const Vecd &direction_from_j_to_i) override + virtual Real getDiffusionCoeffWithBoundary(size_t index_i) override { return diff_cf_; } + virtual Real getInterParticleDiffusionCoeff(size_t index_i, size_t index_j, const Vecd &e_ij) override { return diff_cf_; }; @@ -92,28 +90,27 @@ class IsotropicDiffusion : public BaseDiffusion /** * @class LocalIsotropicDiffusion * @brief diffusion coefficient is locally different (k is not uniformly distributed). + * TODO: The difference between algebraic and geometric average should be identified. */ class LocalIsotropicDiffusion : public IsotropicDiffusion { -protected: - StdLargeVec local_thermal_conductivity_; + protected: + StdLargeVec local_diffusivity_; -public: - LocalIsotropicDiffusion(size_t diffusion_species_index, size_t gradient_species_index, - Real diff_cf = 1.0) - : IsotropicDiffusion(diffusion_species_index, gradient_species_index, diff_cf) - { - material_type_name_ = "LocalIstropicDiffusion"; - } - virtual ~LocalIsotropicDiffusion() {}; + public: + LocalIsotropicDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf = 1.0); + LocalIsotropicDiffusion(const std::string &species_name, Real diff_cf = 1.0); + virtual ~LocalIsotropicDiffusion(){}; - virtual void initializeLocalParameters(BaseParticles* base_particles) override; + virtual void initializeLocalParameters(BaseParticles *base_particles) override; virtual Real getReferenceDiffusivity() override { return diff_cf_; }; - virtual Real getDiffusionCoeffWithBoundary(size_t particle_i) override { return local_thermal_conductivity_[particle_i]; }; - virtual Real getInterParticleDiffusionCoeff(size_t particle_i, size_t particle_j, const Vecd& direction_from_j_to_i) override + virtual Real getDiffusionCoeffWithBoundary(size_t index_i) override { return local_diffusivity_[index_i]; }; + virtual Real getInterParticleDiffusionCoeff(size_t index_i, size_t index_j, const Vecd &e_ij) override { - return 0.5 * (local_thermal_conductivity_[particle_i] + local_thermal_conductivity_[particle_j]); + return 0.5 * (local_diffusivity_[index_i] + local_diffusivity_[index_j]); }; }; @@ -131,15 +128,11 @@ class DirectionalDiffusion : public IsotropicDiffusion void initializeDirectionalDiffusivity(Real diff_cf, Real bias_diff_cf, Vecd bias_direction); public: - DirectionalDiffusion(size_t diffusion_species_index, size_t gradient_species_index, - Real diff_cf, Real bias_diff_cf, Vecd bias_direction) - : IsotropicDiffusion(diffusion_species_index, gradient_species_index, diff_cf), - bias_direction_(bias_direction), bias_diff_cf_(bias_diff_cf), - transformed_diffusivity_(Matd::Identity()) - { - material_type_name_ = "DirectionalDiffusion"; - initializeDirectionalDiffusivity(diff_cf, bias_diff_cf, bias_direction); - }; + DirectionalDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction); + DirectionalDiffusion(const std::string &species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction); virtual ~DirectionalDiffusion(){}; virtual Real getReferenceDiffusivity() override @@ -147,10 +140,9 @@ class DirectionalDiffusion : public IsotropicDiffusion return SMAX(diff_cf_, diff_cf_ + bias_diff_cf_); }; - virtual Real getInterParticleDiffusionCoeff(size_t particle_index_i, - size_t particle_index_j, const Vecd &inter_particle_direction) override + virtual Real getInterParticleDiffusionCoeff(size_t index_i, size_t index_j, const Vecd &e_ij) override { - Vecd grad_ij = transformed_diffusivity_ * inter_particle_direction; + Vecd grad_ij = transformed_diffusivity_ * e_ij; return 1.0 / grad_ij.squaredNorm(); }; }; @@ -166,21 +158,20 @@ class LocalDirectionalDiffusion : public DirectionalDiffusion StdLargeVec local_transformed_diffusivity_; public: - LocalDirectionalDiffusion(size_t diffusion_species_index, size_t gradient_species_index, - Real diff_cf, Real bias_diff_cf, Vecd bias_direction) - : DirectionalDiffusion(diffusion_species_index, gradient_species_index, diff_cf, bias_diff_cf, bias_direction) - { - material_type_name_ = "LocalDirectionalDiffusion"; - }; + LocalDirectionalDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction); + LocalDirectionalDiffusion(const std::string &species_name, + Real diff_cf, Real bias_diff_cf, Vecd bias_direction); virtual ~LocalDirectionalDiffusion(){}; virtual void registerReloadLocalParameters(BaseParticles *base_particles) override; virtual void initializeLocalParameters(BaseParticles *base_particles) override; - virtual Real getInterParticleDiffusionCoeff(size_t particle_index_i, size_t particle_index_j, const Vecd &inter_particle_direction) override + virtual Real getInterParticleDiffusionCoeff(size_t index_i, size_t index_j, const Vecd &e_ij) override { - Matd trans_diffusivity = getAverageValue(local_transformed_diffusivity_[particle_index_i], local_transformed_diffusivity_[particle_index_j]); - Vecd grad_ij = trans_diffusivity * inter_particle_direction; + Matd trans_diffusivity = getAverageValue(local_transformed_diffusivity_[index_i], local_transformed_diffusivity_[index_j]); + Vecd grad_ij = trans_diffusivity * e_ij; return 1.0 / grad_ij.squaredNorm(); }; }; @@ -231,88 +222,43 @@ class BaseReactionModel SpeciesNames species_names_; std::map species_indexes_map_; }; -/** explicit specialization for empty reaction model */ -template <> -inline BaseReactionModel<0>::BaseReactionModel() : reaction_model_("EmptyReactionModel"){}; -using NoReaction = BaseReactionModel<0>; /** - * @class DiffusionReaction - * @brief Complex material for diffusion or/and reactions. + * @class ReactionDiffusion + * @brief Complex material for reaction and diffusion. */ -template -class DiffusionReaction : public BaseMaterialType +template +class ReactionDiffusion : public BaseMaterial { public: - static constexpr int NumReactiveSpecies = NUM_REACTIVE_SPECIES; + static constexpr int NumReactiveSpecies = ReactionType::NumSpecies; private: - UniquePtrsKeeper diffusion_ptr_keeper_; - SharedPtrKeeper> reaction_ptr_keeper_; + UniquePtrsKeeper diffusion_ptrs_keeper_; protected: - typedef std::array ReactiveSpeciesNames; - StdVec all_species_names_; - BaseReactionModel &reaction_model_; - std::map all_species_indexes_map_; - StdVec all_diffusions_; - IndexVector reactive_species_indexes_; - IndexVector diffusion_species_indexes_; - IndexVector gradient_species_indexes_; + ReactionType &reaction_model_; + StdVec all_diffusions_; public: /** Constructor for material with diffusion and reaction. */ - template - DiffusionReaction(const StdVec &all_species_names, - SharedPtr> reaction_model_ptr, - MaterialArgs &&...material_args) - : BaseMaterialType(std::forward(material_args)...), - all_species_names_(all_species_names), - reaction_model_(reaction_ptr_keeper_.assignRef(reaction_model_ptr)) + ReactionDiffusion(ReactionType &reaction_model) + : BaseMaterial(), reaction_model_(reaction_model) { - BaseMaterialType::material_type_name_ = - NUM_REACTIVE_SPECIES == 0 ? "Diffusion" : "DiffusionReaction"; - - for (size_t i = 0; i != all_species_names.size(); ++i) - { - all_species_indexes_map_.insert(make_pair(all_species_names[i], i)); - } - - for (size_t i = 0; i != NUM_REACTIVE_SPECIES; ++i) - { - const ReactiveSpeciesNames &reactive_species_names = reaction_model_.getSpeciesNames(); - size_t reactive_species_index = all_species_indexes_map_[reactive_species_names[i]]; - if (reactive_species_index != all_species_indexes_map_.size()) - { - reactive_species_indexes_.push_back(reactive_species_index); - } - else - { - std::cout << "\n Error: reactive species '" << reactive_species_names[i] << "' not defined!" << std::endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - exit(1); - } - } + material_type_name_ = "ReactionDiffusion"; }; - virtual ~DiffusionReaction(){}; - StdVec &AllSpeciesNames() { return all_species_names_; }; - std::map AllSpeciesIndexMap() { return all_species_indexes_map_; }; - IndexVector &ReactiveSpeciesIndexes() { return reactive_species_indexes_; }; - IndexVector &DiffusionSpeciesIndexes() { return diffusion_species_indexes_; }; - IndexVector &GradientSpeciesIndexes() { return gradient_species_indexes_; }; - StdVec &AllDiffusions() { return all_diffusions_; }; - BaseReactionModel &ReactionModel() { return reaction_model_; }; + virtual ~ReactionDiffusion(){}; + StdVec AllDiffusions() { return all_diffusions_; }; + ReactionType &ReactionModel() { return reaction_model_; }; virtual void registerReloadLocalParameters(BaseParticles *base_particles) override { - BaseMaterialType::registerReloadLocalParameters(base_particles); for (size_t k = 0; k < all_diffusions_.size(); ++k) all_diffusions_[k]->registerReloadLocalParameters(base_particles); }; virtual void initializeLocalParameters(BaseParticles *base_particles) override { - BaseMaterialType::initializeLocalParameters(base_particles); for (size_t k = 0; k < all_diffusions_.size(); ++k) all_diffusions_[k]->initializeLocalParameters(base_particles); }; @@ -323,28 +269,34 @@ class DiffusionReaction : public BaseMaterialType */ Real getDiffusionTimeStepSize(Real smoothing_length) { - Real diff_coeff_max = 0.0; + Real dt = MaxReal; for (size_t k = 0; k < all_diffusions_.size(); ++k) - diff_coeff_max = SMAX(diff_coeff_max, all_diffusions_[k]->getReferenceDiffusivity()); - return 0.5 * smoothing_length * smoothing_length / diff_coeff_max / Real(Dimensions); + dt = SMIN(dt, all_diffusions_[k]->getDiffusionTimeStepSize(smoothing_length)); + return dt; }; - /** Initialize a diffusion material. */ - template - void initializeAnDiffusion(const std::string &diffusion_species_name, - const std::string &gradient_species_name, Args &&...args) + template + void addDiffusion(const std::string &diffusion_species_name, + const std::string &gradient_species_name, Args &&...args) { - size_t diffusion_species_index = all_species_indexes_map_[diffusion_species_name]; - size_t gradient_species_index = all_species_indexes_map_[gradient_species_name]; - diffusion_species_indexes_.push_back(diffusion_species_index); - gradient_species_indexes_.push_back(gradient_species_index); - - all_diffusions_.push_back( - diffusion_ptr_keeper_.createPtr( - diffusion_species_index, gradient_species_index, std::forward(args)...)); - }; + auto species_names = reaction_model_.getSpeciesNames(); - virtual DiffusionReaction *ThisObjectPtr() override { return this; }; + if (std::find(species_names.begin(), species_names.end(), diffusion_species_name) != std::end(species_names) && + std::find(species_names.begin(), species_names.end(), gradient_species_name) != std::end(species_names)) + { + all_diffusions_.push_back( + diffusion_ptrs_keeper_.template createPtr( + diffusion_species_name, gradient_species_name, std::forward(args)...)); + } + else + { + std::cout << "\n Error: diffusion species '" << diffusion_species_name + << "' or gradient species '" << gradient_species_name + << "' not defined!" << std::endl; + std::cout << __FILE__ << ':' << __LINE__ << std::endl; + exit(1); + } + }; }; } // namespace SPH #endif // DIFFUSION_REACTION_H \ No newline at end of file diff --git a/src/shared/materials/elastic_solid.cpp b/src/shared/materials/elastic_solid.cpp index 047f7364b7..e4cf5df2dc 100644 --- a/src/shared/materials/elastic_solid.cpp +++ b/src/shared/materials/elastic_solid.cpp @@ -25,6 +25,16 @@ Matd ElasticSolid::DeviatoricKirchhoff(const Matd &deviatoric_be) return G0_ * deviatoric_be; } //=================================================================================================// +StdLargeVec *ElasticSolid::AverageVelocity(BaseParticles *base_particles) +{ + return base_particles->registerSharedVariable("AverageVelocity"); +} +//=================================================================================================// +StdLargeVec *ElasticSolid::AverageAcceleration(BaseParticles *base_particles) +{ + return base_particles->registerSharedVariable("AverageAcceleration"); +} +//=================================================================================================// LinearElasticSolid:: LinearElasticSolid(Real rho0, Real youngs_modulus, Real poisson_ratio) : ElasticSolid(rho0) { diff --git a/src/shared/materials/elastic_solid.h b/src/shared/materials/elastic_solid.h index fa34bbf17b..5387cd9df4 100644 --- a/src/shared/materials/elastic_solid.h +++ b/src/shared/materials/elastic_solid.h @@ -102,7 +102,10 @@ class ElasticSolid : public Solid virtual Real VolumetricKirchhoff(Real J) = 0; /** Define the calculation of the stress matrix for postprocessing */ virtual std::string getRelevantStressMeasureName() = 0; - + /** Get average velocity when interacting with fluid. */ + virtual StdLargeVec *AverageVelocity(BaseParticles *base_particles) override; + /** Get average acceleration when interacting with fluid. */ + virtual StdLargeVec *AverageAcceleration(BaseParticles *base_particles) override; virtual ElasticSolid *ThisObjectPtr() override { return this; }; }; diff --git a/src/shared/meshes/cell_linked_list.cpp b/src/shared/meshes/cell_linked_list.cpp index 35f58ad771..d106304005 100644 --- a/src/shared/meshes/cell_linked_list.cpp +++ b/src/shared/meshes/cell_linked_list.cpp @@ -48,7 +48,7 @@ CellLinkedList::CellLinkedList(BoundingBox tentative_bounds, Real grid_spacing, void CellLinkedList::UpdateCellLists(BaseParticles &base_particles) { clearCellLists(); - StdLargeVec &pos_n = base_particles.pos_; + StdLargeVec &pos_n = base_particles.ParticlePositions(); size_t total_real_particles = base_particles.total_real_particles_; parallel_for( IndexRange(0, total_real_particles), @@ -71,7 +71,7 @@ void CellLinkedList::UpdateCellLists(BaseParticles &base_particles) //=================================================================================================// StdLargeVec &CellLinkedList::computingSequence(BaseParticles &base_particles) { - StdLargeVec &pos = base_particles.pos_; + StdLargeVec &pos = base_particles.ParticlePositions(); StdLargeVec &sequence = base_particles.sequence_; size_t total_real_particles = base_particles.total_real_particles_; particle_for(execution::ParallelPolicy(), IndexRange(0, total_real_particles), [&](size_t i) @@ -117,7 +117,7 @@ void MultilevelCellLinkedList::UpdateCellLists(BaseParticles &base_particles) for (size_t level = 0; level != total_levels_; ++level) mesh_levels_[level]->clearCellLists(); - StdLargeVec &pos_n = base_particles.pos_; + StdLargeVec &pos_n = base_particles.ParticlePositions(); size_t total_real_particles = base_particles.total_real_particles_; // rebuild the corresponding particle list. parallel_for( @@ -139,7 +139,7 @@ void MultilevelCellLinkedList::UpdateCellLists(BaseParticles &base_particles) //=================================================================================================// StdLargeVec &MultilevelCellLinkedList::computingSequence(BaseParticles &base_particles) { - StdLargeVec &pos = base_particles.pos_; + StdLargeVec &pos = base_particles.ParticlePositions(); StdLargeVec &sequence = base_particles.sequence_; size_t total_real_particles = base_particles.total_real_particles_; particle_for(execution::ParallelPolicy(), IndexRange(0, total_real_particles), diff --git a/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.cpp b/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.cpp index 2f4de7d2b7..635d595f82 100644 --- a/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.cpp +++ b/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.cpp @@ -5,10 +5,10 @@ namespace SPH namespace active_muscle_dynamics { //=================================================================================================// -MuscleActivation:: - MuscleActivation(SPHBody &sph_body) : LocalDynamics(sph_body), ElasticSolidDataSimple(sph_body), - pos0_(particles_->pos0_), - active_contraction_stress_(*particles_->getVariableByName("ActiveContractionStress")){}; +MuscleActivation::MuscleActivation(SPHBody &sph_body) + : LocalDynamics(sph_body), DataDelegateSimple(sph_body), + pos0_(*particles_->registerSharedVariableFrom("InitialPosition", "Position")), + active_contraction_stress_(*particles_->getVariableByName("ActiveContractionStress")){}; //=================================================================================================// } // namespace active_muscle_dynamics } // namespace SPH diff --git a/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.h b/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.h index 2ee6c9468a..c437c23732 100644 --- a/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.h +++ b/src/shared/particle_dynamics/active_muscle_dynamics/active_muscle_dynamics.h @@ -33,20 +33,17 @@ #include "base_kernel.h" #include "elastic_solid.h" #include "solid_body.h" -#include "solid_particles.h" namespace SPH { namespace active_muscle_dynamics { -typedef DataDelegateSimple ElasticSolidDataSimple; - /** * @class MuscleActivation * @brief impose cases specific muscle activation * This is a abstract class to be override for case specific activation */ -class MuscleActivation : public LocalDynamics, public ElasticSolidDataSimple +class MuscleActivation : public LocalDynamics, public DataDelegateSimple { public: explicit MuscleActivation(SPHBody &sph_body); diff --git a/src/shared/particle_dynamics/base_local_dynamics.h b/src/shared/particle_dynamics/base_local_dynamics.h index 6f6889372b..a9e89ee811 100644 --- a/src/shared/particle_dynamics/base_local_dynamics.h +++ b/src/shared/particle_dynamics/base_local_dynamics.h @@ -62,13 +62,10 @@ class BaseLocalDynamics explicit BaseLocalDynamics(DynamicsIdentifier &identifier) : identifier_(identifier){}; virtual ~BaseLocalDynamics(){}; - SPHBody &getSPHBody() { return sph_body_; }; DynamicsIdentifier &getDynamicsIdentifier() { return identifier_; }; - virtual void setupDynamics(Real dt = 0.0){}; // setup global parameters + virtual void setupDynamics(Real dt = 0.0) {}; // setup global parameters protected: DynamicsIdentifier &identifier_; - SPHBody &sph_body_ = identifier_.getSPHBody(); - BaseParticles &base_particles_ = sph_body_.getBaseParticles(); }; using LocalDynamics = BaseLocalDynamics; @@ -107,7 +104,7 @@ class Average : public ReduceSumType { public: template - Average(DynamicsIdentifier &identifier, Args &&... args) + Average(DynamicsIdentifier &identifier, Args &&...args) : ReduceSumType(identifier, std::forward(args)...){}; virtual ~Average(){}; using ReturnType = typename ReduceSumType::ReturnType; @@ -131,8 +128,8 @@ struct ConstructorArgs BodyRelationType &body_relation_; std::tuple others_; SPHBody &getSPHBody() { return body_relation_.getSPHBody(); }; - ConstructorArgs(BodyRelationType &body_relation, OtherArgs &&... other_args) - : body_relation_(body_relation), others_(std::forward(other_args)...){}; + ConstructorArgs(BodyRelationType &body_relation, OtherArgs... other_args) + : body_relation_(body_relation), others_(other_args...){}; }; /** @@ -150,7 +147,7 @@ class ComplexInteraction, CommonParameters...> public: ComplexInteraction(){}; - void interaction(size_t index_i, Real dt = 0.0){}; + void interaction(size_t index_i, Real dt = 0.0) {}; }; template class LocalDynamicsName, @@ -164,7 +161,7 @@ class ComplexInteraction explicit ComplexInteraction(FirstParameterSet &&first_parameter_set, - OtherParameterSets &&... other_parameter_sets) + OtherParameterSets &&...other_parameter_sets) : LocalDynamicsName(first_parameter_set), other_interactions_(std::forward(other_parameter_sets)...){}; diff --git a/src/shared/particle_dynamics/base_particle_dynamics.h b/src/shared/particle_dynamics/base_particle_dynamics.h index 4a6d52fcad..4147d4b826 100644 --- a/src/shared/particle_dynamics/base_particle_dynamics.h +++ b/src/shared/particle_dynamics/base_particle_dynamics.h @@ -102,68 +102,76 @@ class DataDelegateEmptyBase * @class DataDelegateSimple * @brief prepare data for simple particle dynamics. */ -template class DataDelegateSimple { public: explicit DataDelegateSimple(SPHBody &sph_body) - : particles_(DynamicCast(this, &sph_body.getBaseParticles())), - sorted_id_(sph_body.getBaseParticles().sorted_id_), - unsorted_id_(sph_body.getBaseParticles().unsorted_id_){}; + : sph_body_(sph_body), + particles_(&sph_body.getBaseParticles()){}; virtual ~DataDelegateSimple(){}; - ParticlesType *getParticles() { return particles_; }; + SPHBody &getSPHBody() { return sph_body_; }; + BaseParticles *getParticles() { return particles_; }; protected: - ParticlesType *particles_; - StdLargeVec &sorted_id_; - StdLargeVec &unsorted_id_; + SPHBody &sph_body_; + BaseParticles *particles_; }; /** * @class DataDelegateInner * @brief prepare data for inner particle dynamics */ -template > -class DataDelegateInner : public BaseDataDelegateType +template +class BaseDataDelegateInner : public BaseDataDelegateType { BaseInnerRelation &inner_relation_; public: - explicit DataDelegateInner(BaseInnerRelation &inner_relation) + explicit BaseDataDelegateInner(BaseInnerRelation &inner_relation) : BaseDataDelegateType(inner_relation.getSPHBody()), inner_relation_(inner_relation), inner_configuration_(inner_relation.inner_configuration_){}; - virtual ~DataDelegateInner(){}; + virtual ~BaseDataDelegateInner(){}; BaseInnerRelation &getBodyRelation() { return inner_relation_; }; protected: /** inner configuration of the designated body */ ParticleConfiguration &inner_configuration_; }; - +using DataDelegateInner = BaseDataDelegateInner; +using DataDelegateInnerOnly = BaseDataDelegateInner; /** * @class DataDelegateContact * @brief prepare data for contact particle dynamics */ -template > -class DataDelegateContact : public BaseDataDelegateType +template +class BaseDataDelegateContact : public BaseDataDelegateType { BaseContactRelation &contact_relation_; public: - explicit DataDelegateContact(BaseContactRelation &contact_relation); - virtual ~DataDelegateContact(){}; - void addExtraContactRelation(SPHBody &this_body, BaseContactRelation &extra_contact_relation); + explicit BaseDataDelegateContact(BaseContactRelation &contact_relation) + : BaseDataDelegateType(contact_relation.getSPHBody()), + contact_relation_(contact_relation) + { + RealBodyVector contact_sph_bodies = contact_relation.contact_bodies_; + for (size_t i = 0; i != contact_sph_bodies.size(); ++i) + { + contact_bodies_.push_back(contact_sph_bodies[i]); + contact_particles_.push_back(&contact_sph_bodies[i]->getBaseParticles()); + contact_configuration_.push_back(&contact_relation.contact_configuration_[i]); + } + }; + virtual ~BaseDataDelegateContact(){}; BaseContactRelation &getBodyRelation() { return contact_relation_; }; protected: SPHBodyVector contact_bodies_; - StdVec contact_particles_; + StdVec contact_particles_; /** Configurations for particle interaction between bodies. */ StdVec contact_configuration_; }; +using DataDelegateContact = BaseDataDelegateContact; +using DataDelegateContactOnly = BaseDataDelegateContact; } // namespace SPH #endif // BASE_PARTICLE_DYNAMICS_H \ No newline at end of file diff --git a/src/shared/particle_dynamics/base_particle_dynamics.hpp b/src/shared/particle_dynamics/base_particle_dynamics.hpp deleted file mode 100644 index 65b80a416f..0000000000 --- a/src/shared/particle_dynamics/base_particle_dynamics.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file base_particle_dynamics.hpp - * @brief This is for the base classes of particle dynamics, which describe the - * interaction between particles. These interactions are used to define - * differential operators for surface forces or fluxes in continuum mechanics - * @author Chi Zhang and Xiangyu Hu - */ - -#ifndef BASE_PARTICLE_DYNAMICS_HPP -#define BASE_PARTICLE_DYNAMICS_HPP - -#include "base_body.h" -#include "base_particle_dynamics.h" - -namespace SPH -{ -//=================================================================================================// -template -DataDelegateContact:: - DataDelegateContact(BaseContactRelation &contact_relation) - : BaseDataDelegateType(contact_relation.getSPHBody()), - contact_relation_(contact_relation) -{ - RealBodyVector contact_sph_bodies = contact_relation.contact_bodies_; - for (size_t i = 0; i != contact_sph_bodies.size(); ++i) - { - contact_bodies_.push_back(contact_sph_bodies[i]); - contact_particles_.push_back(DynamicCast(this, &contact_sph_bodies[i]->getBaseParticles())); - contact_configuration_.push_back(&contact_relation.contact_configuration_[i]); - } -} -//=================================================================================================// -template -void DataDelegateContact:: - addExtraContactRelation(SPHBody &this_body, BaseContactRelation &extra_contact_relation) -{ - if (&this_body != &extra_contact_relation.getSPHBody()) - { - std::cout << "\n Error: the two body_relations do not have the same source body!" << std::endl; - std::cout << __FILE__ << ':' << __LINE__ << std::endl; - exit(1); - } - - for (auto &extra_body : extra_contact_relation.contact_bodies_) - { - // here we first obtain the pointer to the most derived class and then implicitly downcast it to - // the types defined in the base complex dynamics - contact_bodies_.push_back(extra_body); - contact_particles_.push_back(DynamicCast(this, &extra_body->getBaseParticles())); - } - - for (size_t i = 0; i != extra_contact_relation.contact_bodies_.size(); ++i) - { - contact_configuration_.push_back(&extra_contact_relation.contact_configuration_[i]); - } -} -//=================================================================================================// -} // namespace SPH -//=================================================================================================// -#endif // BASE_PARTICLE_DYNAMICS_HPP \ No newline at end of file diff --git a/src/shared/particle_dynamics/continuum_dynamics/base_continuum_dynamics.h b/src/shared/particle_dynamics/continuum_dynamics/base_continuum_dynamics.h index eea284f754..df0521e0d7 100644 --- a/src/shared/particle_dynamics/continuum_dynamics/base_continuum_dynamics.h +++ b/src/shared/particle_dynamics/continuum_dynamics/base_continuum_dynamics.h @@ -29,38 +29,36 @@ #define BASE_CONTINUUM_DYNAMICS_H #include "base_fluid_dynamics.h" -#include "continuum_particles.h" namespace SPH { namespace continuum_dynamics { -typedef DataDelegateContact FSIContactData; /** - * @class InteractionWithWall - * @brief Base class adding interaction with wall to general relaxation process - */ + * @class InteractionWithWall + * @brief Base class adding interaction with wall to general relaxation process + */ template