Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
acd7186
add test case
WeiyiVirtonomy Feb 10, 2025
b4cff0b
Merge https://github.com/Xiangyu-Hu/SPHinXsys into study/shell-to-sol…
WeiyiVirtonomy Feb 13, 2025
c4d9ecf
change test case
WeiyiVirtonomy Feb 13, 2025
fd01e0c
temp change: use curvature instead of ave curvature
WeiyiVirtonomy Feb 18, 2025
54b5a8b
try to compute coupling force
WeiyiVirtonomy Feb 18, 2025
75bf5ac
try to use solid material for shell pk1
WeiyiVirtonomy Feb 18, 2025
6b09db2
use solid internal force as the coupling force
WeiyiVirtonomy Feb 24, 2025
8ffac73
add NearestNeighbor coupling to source files
WeiyiVirtonomy Feb 28, 2025
56e3e0a
add check coupling ids
WeiyiVirtonomy Mar 3, 2025
2bc1982
add interpolation method
WeiyiVirtonomy Mar 3, 2025
f38d0c9
fix inf
WeiyiVirtonomy Mar 4, 2025
08ee4ee
refactor test
WeiyiVirtonomy Mar 4, 2025
bd646bf
calculate weight each time to reduce storage
WeiyiVirtonomy Mar 4, 2025
67f4173
add two sided parameters
WeiyiVirtonomy Mar 4, 2025
190822f
fix geometry
WeiyiVirtonomy Mar 5, 2025
78adfad
add multiresolution
WeiyiVirtonomy Mar 5, 2025
3ffff1e
add nearest neighbor builder
WeiyiVirtonomy Mar 18, 2025
d7d1fd4
use conservative mapping for force
WeiyiVirtonomy Mar 18, 2025
bb88efd
modification in test case
WeiyiVirtonomy Mar 18, 2025
7d5c31c
add solid simulation and observer
WeiyiVirtonomy Mar 19, 2025
f110db9
add doc
Mar 19, 2025
cabee4c
update readme
Mar 19, 2025
9dbeabb
rename classes
Apr 10, 2025
380c4f3
delete kernel reduction
Apr 10, 2025
01627a0
add a 2d test
Apr 10, 2025
c814c19
add full solid simulation and observers
Apr 11, 2025
e941956
add 3d test
Apr 14, 2025
71b4985
clean up and renaming
Apr 17, 2025
925530c
Merge branch 'study/shell-to-solid_coupling' of https://github.com/Xi…
Apr 17, 2025
c73c9fb
Merge HEAD, branch 'study/shell-to-solid_coupling' of https://github.…
Apr 17, 2025
9b5c9e5
fix
Apr 17, 2025
e769451
delete unneeded case
Apr 17, 2025
88998bd
delete old results
Apr 17, 2025
65b636a
change thickness
Apr 17, 2025
a2762a6
add an example to readme
Apr 25, 2025
0d71396
revert
Apr 25, 2025
048daf5
delete unused equations and fix typo
Apr 25, 2025
ac74f80
fix particle tagging
Apr 29, 2025
bd5d943
rename
Apr 29, 2025
6a26e59
use template for variable
Apr 30, 2025
5f3550f
change alg structures
Apr 30, 2025
8a8fe1f
fix data type
May 9, 2025
751fef8
Merge https://github.com/Xiangyu-Hu/SPHinXsys into study/shell-to-sol…
May 20, 2025
59cc899
fix after merge
May 20, 2025
f4c3fe9
modify readme
May 20, 2025
6b0427f
use larger thickness and add comments
May 21, 2025
2a7de1c
add comment in readme
May 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/shared/body_relations/contact_body_relation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,30 @@ void SurfaceContactRelation::updateConfiguration()
}
}
//=================================================================================================//
MaxSmoothingLengthContactRelation::MaxSmoothingLengthContactRelation(SPHBody &sph_body,
RealBodyVector contact_bodies,
const std::vector<Real> &factors)
: ContactRelationCrossResolution(sph_body, contact_bodies)
{
for (size_t k = 0; k != contact_bodies_.size(); ++k)
{
Real factor = factors.empty() ? 1 : factors[k];
get_contact_neighbors_.push_back(
neighbor_builder_contact_ptrs_keeper_.createPtr<MaxSmoothingLengthNeighborBuilder>(
sph_body_, *contact_bodies_[k], factor));
}
}
//=================================================================================================//
void MaxSmoothingLengthContactRelation::updateConfiguration()
{
resetNeighborhoodCurrentSize();
for (size_t k = 0; k != contact_bodies_.size(); ++k)
{
Mesh &mesh = target_cell_linked_lists_[k]->getMesh();
target_cell_linked_lists_[k]->searchNeighborsByMesh(
mesh, 0, sph_body_, contact_configuration_[k],
*get_search_depths_[k], *get_contact_neighbors_[k]);
}
}
//=================================================================================================//
} // namespace SPH
31 changes: 24 additions & 7 deletions src/shared/body_relations/contact_body_relation.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ContactRelationCrossResolution : public BaseContactRelation
sph_body_, target_cell_linked_list->getMesh()));
}
};
virtual ~ContactRelationCrossResolution(){};
virtual ~ContactRelationCrossResolution() {};
StdVec<CellLinkedList *> getContactCellLinkedList() { return target_cell_linked_lists_; }

protected:
Expand All @@ -79,7 +79,7 @@ class ContactRelation : public ContactRelationCrossResolution

public:
ContactRelation(SPHBody &sph_body, RealBodyVector contact_bodies);
virtual ~ContactRelation(){};
virtual ~ContactRelation() {};
virtual void updateConfiguration() override;

protected:
Expand All @@ -103,8 +103,8 @@ class ShellSurfaceContactRelation : public ContactRelationCrossResolution
ShellSurfaceContactRelation(SPHBody &sph_body, RealBodyVector contact_bodies);
ShellSurfaceContactRelation(SelfSurfaceContactRelation &solid_body_relation_self_contact,
RealBodyVector contact_bodies)
: ShellSurfaceContactRelation(*solid_body_relation_self_contact.real_body_, contact_bodies){};
virtual ~ShellSurfaceContactRelation(){};
: ShellSurfaceContactRelation(*solid_body_relation_self_contact.real_body_, contact_bodies) {};
virtual ~ShellSurfaceContactRelation() {};
virtual void updateConfiguration() override;

protected:
Expand All @@ -127,7 +127,7 @@ class ContactRelationToBodyPart : public ContactRelationCrossResolution
StdVec<NeighborBuilderContactBodyPart *> get_part_contact_neighbors_;

ContactRelationToBodyPart(SPHBody &sph_body, BodyPartVector contact_body_parts_);
virtual ~ContactRelationToBodyPart(){};
virtual ~ContactRelationToBodyPart() {};

virtual void updateConfiguration() override;
};
Expand All @@ -149,7 +149,7 @@ class AdaptiveContactRelation : public BaseContactRelation

public:
AdaptiveContactRelation(SPHBody &body, RealBodyVector contact_bodies);
virtual ~AdaptiveContactRelation(){};
virtual ~AdaptiveContactRelation() {};

virtual void updateConfiguration() override;
};
Expand Down Expand Up @@ -211,7 +211,7 @@ class SurfaceContactRelation : public ContactRelationCrossResolution
StdVec<bool> normal_corrections = {})
: SurfaceContactRelation(*solid_body_relation_self_contact.real_body_,
std::move(contact_bodies),
std::move(normal_corrections)){};
std::move(normal_corrections)) {};
~SurfaceContactRelation() override = default;
void updateConfiguration() override;
BodySurfaceLayer *get_body_surface_layer() { return body_surface_layer_; }
Expand All @@ -223,5 +223,22 @@ class SurfaceContactRelation : public ContactRelationCrossResolution

void resetNeighborhoodCurrentSize() override;
};

/**
* @class MaxSmoothingLengthContactRelation
* @brief The relation between a SPH body and its contact SPH bodies, where the cut-off radius is set as factor * 2h_max
*/
class MaxSmoothingLengthContactRelation : public ContactRelationCrossResolution
{
private:
UniquePtrsKeeper<MaxSmoothingLengthNeighborBuilder> neighbor_builder_contact_ptrs_keeper_;

public:
MaxSmoothingLengthContactRelation(SPHBody &sph_body, RealBodyVector contact_bodies, const std::vector<Real> &factors = {});
void updateConfiguration() override;

private:
StdVec<MaxSmoothingLengthNeighborBuilder *> get_contact_neighbors_;
};
} // namespace SPH
#endif // CONTACT_BODY_RELATION_H
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,7 @@
#include "inelastic_dynamics.h"
#include "loading_dynamics.h"
#include "solid_dynamics_variable.h"
#include "solid_to_shell_coupling.h"
#include "solid_to_shell_coupling.hpp"
#include "thin_structure_dynamics.h"
#include "thin_structure_math.h"
104 changes: 104 additions & 0 deletions src/shared/particle_dynamics/solid_dynamics/solid_to_shell_coupling.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* ------------------------------------------------------------------------- *
* 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-2023 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 solid_to_shell_coupling.h
* @brief Constraints for solid to shell coupling.
* @author Xiangyu Hu, Weiyi Kong (Virtonomy GmbH)
*/

#ifndef SOLID_TO_SHELL_CONSTRAINT_H
#define SOLID_TO_SHELL_CONSTRAINT_H

#include "force_prior.h"
#include "general_constraint.h"

namespace SPH
{
namespace solid_dynamics
{
/**@class ComputeWeight
* @brief Compute the total weight for each solid particle from the coupled shell particles.
* This weight is used for interpolation of velocity and force
*/
template <class DynamicsIdentifier>
class TotalWeightComputation : public BaseLocalDynamics<DynamicsIdentifier>,
public DataDelegateContact
{
private:
Real *total_weight_; // \sum_i W_ij * Vol_j for j of all contact bodies
StdVec<Real *> contact_Vol_;

public:
TotalWeightComputation(DynamicsIdentifier &identifier, BaseContactRelation &contact_relation);
void update(size_t index_i, Real dt = 0.0);
};

/**@class ConsistentMapping
* @brief Constrain the variable by the interpolation from coupled particle velocities with consistent mapping.
* Usually used for velocity.
* When there is more than one contact body, interpolate from all contact bodies.
*/
template <class DynamicsIdentifier, typename DataType>
class ConsistentMapping : public BaseLocalDynamics<DynamicsIdentifier>,
public DataDelegateContact
{
private:
DataType *interpolated_quantities_;
Real *total_weight_;
StdVec<Real *> contact_Vol_;
StdVec<DataType *> contact_data_;

public:
ConsistentMapping(DynamicsIdentifier &identifier,
BaseContactRelation &contact_relation,
const std::string &variable_name, // variable name of the source body, e.g., "Velocity"
const std::string &contact_variable_name); // variable name of the contact body, e.g., "Velocity"
void update(size_t index_i, Real dt = 0.0);
};

/**@class ConservativeMapping
* @brief Constrain the variable by the interpolation from coupled particle with conservative mapping.
* Usually used for force. Note that for prior force, the force needs to be registered as a new prior force.
* When there is more than one contact body, interpolate force from each contact body and sum up.
*/
template <class DynamicsIdentifier, typename DataType>
class ConservativeMapping : public BaseLocalDynamics<DynamicsIdentifier>,
public DataDelegateContact
{
private:
DataType *interpolated_quantities_;
Real *Vol_;
StdVec<Real *> contact_total_weight_;
StdVec<DataType *> contact_data_;

public:
ConservativeMapping(DynamicsIdentifier &identifier,
BaseContactRelation &contact_relation,
const std::string &variable_name, // variable name of the source body, e.g., "CouplingForce"
const std::string &contact_variable_name); // variable name of the contact body, e.g., "Force"
void update(size_t index_i, Real dt = 0.0);
};
} // namespace solid_dynamics
} // namespace SPH

#endif // SOLID_TO_SHELL_CONSTRAINT_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#ifndef SOLID_TO_SHELL_CONSTRAINT_HPP
#define SOLID_TO_SHELL_CONSTRAINT_HPP

#include "solid_to_shell_coupling.h"

namespace SPH
{
namespace solid_dynamics
{
template <class DynamicsIdentifier>
TotalWeightComputation<DynamicsIdentifier>::
TotalWeightComputation(DynamicsIdentifier &identifier, BaseContactRelation &contact_relation)
: BaseLocalDynamics<DynamicsIdentifier>(identifier),
DataDelegateContact(contact_relation),
total_weight_(this->particles_->template registerStateVariable<Real>("TotalWeight"))
{
for (auto *contact_particle : contact_particles_)
contact_Vol_.emplace_back(contact_particle->template getVariableDataByName<Real>("VolumetricMeasure"));
}

template <class DynamicsIdentifier>
void TotalWeightComputation<DynamicsIdentifier>::update(size_t index_i, Real dt)
{
Real weight_ttl = 0;
for (size_t k = 0; k != contact_configuration_.size(); ++k)
{
const Real *Vol_k = contact_Vol_[k];
const Neighborhood &contact_neighborhood = (*contact_configuration_[k])[index_i];
for (size_t n = 0; n != contact_neighborhood.current_size_; ++n)
{
size_t index_j = contact_neighborhood.j_[n];
Real weight_j = contact_neighborhood.W_ij_[n] * Vol_k[index_j];
weight_ttl += weight_j;
}
}
total_weight_[index_i] = weight_ttl;
}
//=================================================================================================//
template <class DynamicsIdentifier, typename DataType>
ConsistentMapping<DynamicsIdentifier, DataType>::
ConsistentMapping(DynamicsIdentifier &identifier,
BaseContactRelation &contact_relation,
const std::string &variable_name,
const std::string &contact_variable_name)
: BaseLocalDynamics<DynamicsIdentifier>(identifier),
DataDelegateContact(contact_relation),
interpolated_quantities_(this->particles_->template registerStateVariable<DataType>(variable_name)),
total_weight_(this->particles_->template getVariableDataByName<Real>("TotalWeight"))
{
for (auto *contact_particle : contact_particles_)
{
contact_Vol_.emplace_back(contact_particle->template getVariableDataByName<Real>("VolumetricMeasure"));
contact_data_.emplace_back(contact_particle->template getVariableDataByName<DataType>(contact_variable_name));
}
};

template <class DynamicsIdentifier, typename DataType>
void ConsistentMapping<DynamicsIdentifier, DataType>::update(size_t index_i, Real)
{
// only consider particles with contact neighbors
if (total_weight_[index_i] < TinyReal)
return;

DataType interpolated_quantities = ZeroData<DataType>::value;
for (size_t k = 0; k != contact_configuration_.size(); ++k)
{
const Real *Vol_k = contact_Vol_[k];
const DataType *data_k = contact_data_[k];
const Neighborhood &contact_neighborhood = (*contact_configuration_[k])[index_i];
for (size_t n = 0; n != contact_neighborhood.current_size_; ++n)
{
size_t index_j = contact_neighborhood.j_[n];
Real weight_j = contact_neighborhood.W_ij_[n] * Vol_k[index_j];
interpolated_quantities += weight_j * data_k[index_j];
}
}
interpolated_quantities_[index_i] = interpolated_quantities / total_weight_[index_i];
}
//=================================================================================================//
template <class DynamicsIdentifier, typename DataType>
ConservativeMapping<DynamicsIdentifier, DataType>::
ConservativeMapping(DynamicsIdentifier &identifier,
BaseContactRelation &contact_relation,
const std::string &variable_name,
const std::string &contact_variable_name)
: BaseLocalDynamics<DynamicsIdentifier>(identifier),
DataDelegateContact(contact_relation),
interpolated_quantities_(this->particles_->template registerStateVariable<DataType>(variable_name)),
Vol_(this->particles_->template getVariableDataByName<Real>("VolumetricMeasure"))
{
for (auto *contact_particle : contact_particles_)
{
contact_total_weight_.emplace_back(contact_particle->template getVariableDataByName<Real>("TotalWeight"));
contact_data_.emplace_back(contact_particle->template getVariableDataByName<DataType>(contact_variable_name));
}
};

template <class DynamicsIdentifier, typename DataType>
void ConservativeMapping<DynamicsIdentifier, DataType>::update(size_t index_i, Real)
{
DataType interpolated_quantities = ZeroData<DataType>::value;
for (size_t k = 0; k != contact_configuration_.size(); ++k)
{
const DataType *data_k = contact_data_[k];
const Real *total_weight_k = contact_total_weight_[k];
const Neighborhood &contact_neighborhood = (*contact_configuration_[k])[index_i];
for (size_t n = 0; n != contact_neighborhood.current_size_; ++n)
{
size_t index_j = contact_neighborhood.j_[n];
if (total_weight_k[index_j] < TinyReal)
continue;
Real weight_j = contact_neighborhood.W_ij_[n] * Vol_[index_i] / total_weight_k[index_j];
interpolated_quantities += weight_j * data_k[index_j];
}
}
interpolated_quantities_[index_i] = interpolated_quantities;
}
} // namespace solid_dynamics
} // namespace SPH

#endif // SOLID_TO_SHELL_CONSTRAINT_HPP
10 changes: 10 additions & 0 deletions src/shared/particle_neighborhood/neighborhood.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,5 +558,15 @@ operator()(Neighborhood &neighborhood, const Vecd &pos_i, size_t index_i, const
}
};
//=================================================================================================//
MaxSmoothingLengthNeighborBuilder::MaxSmoothingLengthNeighborBuilder(SPHBody &body, SPHBody &contact_body, Real factor)
: NeighborBuilderContact(body, contact_body)
{
// create a kernel with a cut-off radius of factor * dp_max
Real h_max = SMAX(body.getSPHAdaptation().ReferenceSmoothingLength(), contact_body.getSPHAdaptation().ReferenceSmoothingLength());
Real h = factor * h_max;
// smoothing length: cut_off_radius/2.0
kernel_ = kernel_keeper_.createPtr<KernelWendlandC2>(h);
}
//=================================================================================================//
} // namespace SPH
//=================================================================================================//
Loading
Loading